mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Choose backend to play media in context menu (#1325)
## Description Adds a context menu option to choose the player backend or transcoding to start playback. This allows for temporarily swapping to another backend without having to updating the settings. ### Related issues A couple comments have suggested this, but I don't think there's a specific feature request ### Testing Emulator ## Screenshots <img width="1280" height="720" alt="play_with Large" src="https://github.com/user-attachments/assets/2a75756f-5d7f-45f6-8ea6-a406f3d7f3e1" /> ## AI or LLM usage None
This commit is contained in:
parent
c718d903a4
commit
b94faceb2f
4 changed files with 91 additions and 16 deletions
|
|
@ -17,12 +17,14 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ChosenStreams
|
||||
import com.github.damontecres.wholphin.data.model.AudioItem
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||
import com.github.damontecres.wholphin.data.model.Person
|
||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.util.supportedPlayableTypes
|
||||
|
|
@ -185,6 +187,7 @@ fun ContextMenu(
|
|||
val context = LocalContext.current
|
||||
var chooseVersion by remember { mutableStateOf<DialogParams?>(null) }
|
||||
var showDeleteDialog by remember { mutableStateOf(false) }
|
||||
var showPlayWithDialog by remember { mutableStateOf(false) }
|
||||
|
||||
val dialogItems =
|
||||
remember(context, item, chosenStreams) {
|
||||
|
|
@ -211,6 +214,7 @@ fun ContextMenu(
|
|||
) { idx ->
|
||||
val source = item.data.mediaSources!![idx]
|
||||
actions.onChooseVersion.invoke(item, source)
|
||||
onDismissRequest.invoke()
|
||||
}
|
||||
},
|
||||
onChooseTracks = { type ->
|
||||
|
|
@ -239,6 +243,7 @@ fun ContextMenu(
|
|||
itemPlayback = chosenStreams?.itemPlayback,
|
||||
),
|
||||
)
|
||||
onDismissRequest.invoke()
|
||||
},
|
||||
preferredSubtitleLanguage = preferredSubtitleLanguage,
|
||||
)
|
||||
|
|
@ -249,6 +254,7 @@ fun ContextMenu(
|
|||
actions.onClearChosenStreams.invoke(chosenStreams)
|
||||
},
|
||||
onClickDelete = { showDeleteDialog = true },
|
||||
onClickPlayWith = { showPlayWithDialog = true },
|
||||
)
|
||||
}
|
||||
DialogPopup(
|
||||
|
|
@ -281,6 +287,31 @@ fun ContextMenu(
|
|||
},
|
||||
)
|
||||
}
|
||||
if (showPlayWithDialog) {
|
||||
val dialogItems =
|
||||
remember {
|
||||
buildPlayWith(context) { transcode, backend ->
|
||||
onDismissRequest.invoke()
|
||||
actions.navigateTo(
|
||||
Destination.Playback(
|
||||
itemId = item.id,
|
||||
positionMs = item.resumeMs,
|
||||
forceTranscoding = transcode,
|
||||
backend = backend,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
DialogPopup(
|
||||
showDialog = true,
|
||||
title = stringResource(R.string.play_with),
|
||||
dialogItems = dialogItems,
|
||||
onDismissRequest = { showPlayWithDialog = false },
|
||||
dismissOnClick = true,
|
||||
waitToLoad = false,
|
||||
elevation = 3.dp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildContextMenuItems(
|
||||
|
|
@ -302,6 +333,7 @@ private fun buildContextMenuItems(
|
|||
onShowOverview: () -> Unit,
|
||||
onClearChosenStreams: () -> Unit,
|
||||
onClickDelete: () -> Unit,
|
||||
onClickPlayWith: () -> Unit,
|
||||
): List<DialogItem> =
|
||||
buildList {
|
||||
if (showGoTo) {
|
||||
|
|
@ -316,7 +348,7 @@ private fun buildContextMenuItems(
|
|||
)
|
||||
}
|
||||
if (item.type in supportedPlayableTypes) {
|
||||
if (item.playbackPosition >= Duration.ZERO) {
|
||||
if (item.playbackPosition > Duration.ZERO) {
|
||||
add(
|
||||
DialogItem(
|
||||
context.getString(R.string.resume),
|
||||
|
|
@ -566,18 +598,11 @@ private fun buildContextMenuItems(
|
|||
if (item.type in supportedPlayableTypes) {
|
||||
add(
|
||||
DialogItem(
|
||||
context.getString(R.string.play_with_transcoding),
|
||||
context.getString(R.string.play_with),
|
||||
Icons.Default.PlayArrow,
|
||||
dismissOnClick = true,
|
||||
) {
|
||||
actions.navigateTo(
|
||||
Destination.Playback(
|
||||
item.id,
|
||||
item.resumeMs ?: 0L,
|
||||
forceTranscoding = true,
|
||||
),
|
||||
)
|
||||
},
|
||||
dismissOnClick = false,
|
||||
onClick = onClickPlayWith,
|
||||
),
|
||||
)
|
||||
}
|
||||
if (item.data.mediaSources?.isNotEmpty() == true) {
|
||||
|
|
@ -593,6 +618,35 @@ private fun buildContextMenuItems(
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildPlayWith(
|
||||
context: Context,
|
||||
onClick: (Boolean, PlayerBackend?) -> Unit,
|
||||
) = buildList {
|
||||
val entries =
|
||||
PlayerBackend.entries
|
||||
.filterNot { it == PlayerBackend.UNRECOGNIZED }
|
||||
.zip(context.resources.getStringArray(R.array.player_backend_options))
|
||||
.filterNot { it.first == PlayerBackend.PREFER_MPV }
|
||||
entries.forEach { (backend, title) ->
|
||||
add(
|
||||
DialogItem(
|
||||
title,
|
||||
dismissOnClick = true,
|
||||
) {
|
||||
onClick.invoke(false, backend)
|
||||
},
|
||||
)
|
||||
}
|
||||
add(
|
||||
DialogItem(
|
||||
context.getString(R.string.transcoding),
|
||||
dismissOnClick = true,
|
||||
) {
|
||||
onClick.invoke(true, null)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ContextMenu(
|
||||
onDismissRequest: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -76,9 +76,25 @@ fun DestinationContent(
|
|||
HomeSettingsPage(preferences, modifier)
|
||||
}
|
||||
|
||||
is Destination.PlaybackList,
|
||||
is Destination.Playback,
|
||||
-> {
|
||||
is Destination.Playback -> {
|
||||
val backend =
|
||||
destination.backend ?: preferences.appPreferences.playbackPreferences.playerBackend
|
||||
if (backend == PlayerBackend.EXTERNAL_PLAYER) {
|
||||
PlayExternalPage(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
} else {
|
||||
PlaybackPage(
|
||||
preferences = preferences,
|
||||
destination = destination,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is Destination.PlaybackList -> {
|
||||
if (preferences.appPreferences.playbackPreferences.playerBackend == PlayerBackend.EXTERNAL_PLAYER) {
|
||||
PlayExternalPage(
|
||||
preferences = preferences,
|
||||
|
|
|
|||
|
|
@ -231,8 +231,11 @@ class PlaybackViewModel
|
|||
) {
|
||||
val softwareDecoding =
|
||||
!preferences.appPreferences.playbackPreferences.mpvOptions.enableHardwareDecoding
|
||||
val requestBackend =
|
||||
(destination as? Destination.Playback)?.backend
|
||||
?: preferences.appPreferences.playbackPreferences.playerBackend
|
||||
val playerBackend =
|
||||
when (preferences.appPreferences.playbackPreferences.playerBackend) {
|
||||
when (requestBackend) {
|
||||
PlayerBackend.UNRECOGNIZED,
|
||||
PlayerBackend.EXO_PLAYER,
|
||||
-> PlayerBackend.EXO_PLAYER
|
||||
|
|
|
|||
|
|
@ -771,6 +771,8 @@
|
|||
<string name="show_more">Show %1$s more</string>
|
||||
<string name="skip_behavior">Skip behavior</string>
|
||||
<string name="skip_behavior_summary">For intros, credits, etc</string>
|
||||
<string name="play_with">Play with</string>
|
||||
<string name="transcoding">Transcoding</string>
|
||||
<array name="ass_subtitle_modes">
|
||||
<item>@string/ass_subtitle_mode_libass</item>
|
||||
<item>@string/ass_subtitle_mode_exoplayer</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue