mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-05 18:30:59 +01:00
Add experimental settings & video tunneling (#1624)
## Description This PR introduces the concept of "experimental" settings or features. These may cause instabilities or may need further testing. They may be changed or removed any time. Also, the developers won't provide lots of support for them. The goal is expose some specialized settings that might only apply to a small subset of users or test out tweaks to playback. The first experimental feature is a toggle to enable [video tunneling](https://developer.android.com/media/media3/exoplayer/track-selection#tunneling). ### Related issues Related to #1283 ### Testing Emulator ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
21e720c420
commit
083d4e4fa8
13 changed files with 183 additions and 14 deletions
12
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
12
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
name: "Bug Report"
|
name: "Bug Report"
|
||||||
description: Report a bug
|
description: Report a bug
|
||||||
title: "<title>"
|
title: ""
|
||||||
labels: [
|
labels: [
|
||||||
"bug"
|
"bug"
|
||||||
]
|
]
|
||||||
|
|
@ -23,6 +23,16 @@ body:
|
||||||
3. See error
|
3. See error
|
||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
id: experimental
|
||||||
|
attributes:
|
||||||
|
label: Experimental settings
|
||||||
|
description: Do you have experiment settings turn on?
|
||||||
|
options:
|
||||||
|
- "Yes"
|
||||||
|
- "No"
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: app-version
|
id: app-version
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
||||||
22
.github/ISSUE_TEMPLATE/01-playback.yml
vendored
22
.github/ISSUE_TEMPLATE/01-playback.yml
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
name: "Playback Problem"
|
name: "Playback Problem"
|
||||||
description: Report an issue with playback
|
description: Report an issue with playback
|
||||||
title: "<title>"
|
title: ""
|
||||||
labels: [
|
labels: [
|
||||||
"bug", "playback"
|
"bug", "playback"
|
||||||
]
|
]
|
||||||
|
|
@ -12,12 +12,14 @@ body:
|
||||||
description: Please enter a description of the playback issue
|
description: Please enter a description of the playback issue
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: dropdown
|
||||||
id: mediainfo
|
id: experimental
|
||||||
attributes:
|
attributes:
|
||||||
label: "Media info"
|
label: Experimental settings
|
||||||
description: Please enter details about what media you are trying to play (video or audio codecs, container, etc)
|
description: Do you have experiment settings turn on?
|
||||||
placeholder: Use mediainfo or "Send media info to server" in the app to gather this
|
options:
|
||||||
|
- "Yes"
|
||||||
|
- "No"
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
|
@ -32,6 +34,14 @@ body:
|
||||||
- External App (please specify)
|
- External App (please specify)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: mediainfo
|
||||||
|
attributes:
|
||||||
|
label: "Media info"
|
||||||
|
description: Please enter details about what media you are trying to play (video or audio codecs, container, etc)
|
||||||
|
placeholder: Use mediainfo or "Send media info to server" in the app to gather this
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
- type: input
|
- type: input
|
||||||
id: app-version
|
id: app-version
|
||||||
attributes:
|
attributes:
|
||||||
|
|
|
||||||
|
|
@ -97,3 +97,9 @@ Some of the models, such as `GetItemsFilter` or `ViewOptions`, are stored as JSO
|
||||||
These settings are similar to Room ones and are usually stored per user. These can be accessed via `KeyValueService`. The values are `@Serializable` objects saved as JSON.
|
These settings are similar to Room ones and are usually stored per user. These can be accessed via `KeyValueService`. The values are `@Serializable` objects saved as JSON.
|
||||||
|
|
||||||
This should be used sparingly.
|
This should be used sparingly.
|
||||||
|
|
||||||
|
#### Experimental
|
||||||
|
|
||||||
|
Some settings are considered "experimental". These may cause instabilities or may need further testing. They may be changed or removed any time.
|
||||||
|
|
||||||
|
These are stored in the `ExperimentalPreferences` object in `AppPreferences`. Accessing them should always be gated with `ExperimentalPreferences.enabled`. There are a few helper functions for this purpose.
|
||||||
|
|
|
||||||
|
|
@ -1266,8 +1266,16 @@ val advancedPreferences =
|
||||||
AppPreference.DebugLogging,
|
AppPreference.DebugLogging,
|
||||||
AppPreference.ImageDiskCacheSize,
|
AppPreference.ImageDiskCacheSize,
|
||||||
AppPreference.ClearImageCache,
|
AppPreference.ClearImageCache,
|
||||||
|
ExperimentalPreference.Enable,
|
||||||
AppPreference.OssLicenseInfo,
|
AppPreference.OssLicenseInfo,
|
||||||
),
|
),
|
||||||
|
conditionalPreferences =
|
||||||
|
listOf(
|
||||||
|
ConditionalPreferences(
|
||||||
|
condition = { it.experimentalPreferences.enabled },
|
||||||
|
preferences = listOf(ExperimentalPreference.ExperimentalSettings),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,14 @@ class AppPreferencesSerializer
|
||||||
showLyrics = true
|
showLyrics = true
|
||||||
showAlbumArt = true
|
showAlbumArt = true
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
|
experimentalPreferences =
|
||||||
|
ExperimentalPreferences
|
||||||
|
.newBuilder()
|
||||||
|
.apply {
|
||||||
|
enabled = false
|
||||||
|
videoTunnelingEnabled = false
|
||||||
|
}.build()
|
||||||
}.build()
|
}.build()
|
||||||
|
|
||||||
override suspend fun readFrom(input: InputStream): AppPreferences {
|
override suspend fun readFrom(input: InputStream): AppPreferences {
|
||||||
|
|
@ -252,6 +260,11 @@ inline fun AppPreferences.updateMusicPreferences(block: MusicPreferences.Builder
|
||||||
musicPreferences = musicPreferences.toBuilder().apply(block).build()
|
musicPreferences = musicPreferences.toBuilder().apply(block).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun AppPreferences.updateExperimentalPreferences(block: ExperimentalPreferences.Builder.() -> Unit): AppPreferences =
|
||||||
|
update {
|
||||||
|
experimentalPreferences = experimentalPreferences.toBuilder().apply(block).build()
|
||||||
|
}
|
||||||
|
|
||||||
fun SubtitlePreferences.Builder.resetSubtitles() {
|
fun SubtitlePreferences.Builder.resetSubtitles() {
|
||||||
fontSize = SubtitleSettings.FontSize.defaultValue.toInt()
|
fontSize = SubtitleSettings.FontSize.defaultValue.toInt()
|
||||||
fontColor = SubtitleSettings.FontColor.defaultValue.toArgb()
|
fontColor = SubtitleSettings.FontColor.defaultValue.toArgb()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
package com.github.damontecres.wholphin.preferences
|
||||||
|
|
||||||
|
import com.github.damontecres.wholphin.R
|
||||||
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
|
import com.github.damontecres.wholphin.ui.preferences.PreferenceGroup
|
||||||
|
import com.github.damontecres.wholphin.ui.preferences.PreferenceScreenOption
|
||||||
|
|
||||||
|
object ExperimentalPreference {
|
||||||
|
val Enable =
|
||||||
|
AppSwitchPreference<AppPreferences>(
|
||||||
|
title = R.string.experimental_settings,
|
||||||
|
defaultValue = false,
|
||||||
|
getter = { it.experimentalPreferences.enabled },
|
||||||
|
setter = { prefs, value ->
|
||||||
|
prefs.updateExperimentalPreferences { enabled = value }
|
||||||
|
},
|
||||||
|
summaryOn = R.string.enabled,
|
||||||
|
summaryOff = R.string.disabled,
|
||||||
|
)
|
||||||
|
|
||||||
|
val ExperimentalSettings =
|
||||||
|
AppDestinationPreference<AppPreferences>(
|
||||||
|
title = R.string.experimental_settings,
|
||||||
|
destination = Destination.Settings(PreferenceScreenOption.EXPERIMENTAL),
|
||||||
|
)
|
||||||
|
|
||||||
|
val VideoTunneling =
|
||||||
|
AppSwitchPreference<AppPreferences>(
|
||||||
|
title = R.string.video_tunneling,
|
||||||
|
defaultValue = false,
|
||||||
|
getter = { it.experimentalPreferences.videoTunnelingEnabled },
|
||||||
|
setter = { prefs, value ->
|
||||||
|
prefs.updateExperimentalPreferences { videoTunnelingEnabled = value }
|
||||||
|
},
|
||||||
|
summaryOn = R.string.enabled,
|
||||||
|
summaryOff = R.string.disabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val experimentalPreferences =
|
||||||
|
buildList {
|
||||||
|
add(
|
||||||
|
PreferenceGroup(
|
||||||
|
title = R.string.experimental_settings,
|
||||||
|
preferences =
|
||||||
|
listOf(
|
||||||
|
ExperimentalPreference.VideoTunneling,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a value from [ExperimentalPreference] or null if not enabled
|
||||||
|
*/
|
||||||
|
fun <T> ExperimentalPreferences.get(block: ExperimentalPreferences.() -> T): T? = if (enabled) block.invoke(this) else null
|
||||||
|
|
||||||
|
fun ExperimentalPreferences.enabled(block: ExperimentalPreferences.() -> Boolean): Boolean = enabled && block.invoke(this)
|
||||||
|
|
@ -26,10 +26,11 @@ import androidx.media3.exoplayer.video.VideoRendererEventListener
|
||||||
import androidx.media3.extractor.DefaultExtractorsFactory
|
import androidx.media3.extractor.DefaultExtractorsFactory
|
||||||
import androidx.media3.session.MediaSession
|
import androidx.media3.session.MediaSession
|
||||||
import com.github.damontecres.wholphin.mpv.MpvPlayer
|
import com.github.damontecres.wholphin.mpv.MpvPlayer
|
||||||
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.AssPlaybackMode
|
import com.github.damontecres.wholphin.preferences.AssPlaybackMode
|
||||||
import com.github.damontecres.wholphin.preferences.MediaExtensionStatus
|
import com.github.damontecres.wholphin.preferences.MediaExtensionStatus
|
||||||
import com.github.damontecres.wholphin.preferences.PlaybackPreferences
|
|
||||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||||
|
import com.github.damontecres.wholphin.preferences.get
|
||||||
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
||||||
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
|
@ -61,8 +62,9 @@ class PlayerFactory
|
||||||
|
|
||||||
suspend fun createVideoPlayer(
|
suspend fun createVideoPlayer(
|
||||||
backend: PlayerBackend,
|
backend: PlayerBackend,
|
||||||
prefs: PlaybackPreferences,
|
appPreferences: AppPreferences,
|
||||||
): PlayerCreation {
|
): PlayerCreation {
|
||||||
|
val prefs = appPreferences.playbackPreferences
|
||||||
withContext(WholphinDispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (currentPlayer?.isReleased == false) {
|
if (currentPlayer?.isReleased == false) {
|
||||||
Timber.w("Player was not released before trying to create a new one!")
|
Timber.w("Player was not released before trying to create a new one!")
|
||||||
|
|
@ -105,6 +107,7 @@ class PlayerFactory
|
||||||
WholphinRenderersFactory(context, decodeAv1)
|
WholphinRenderersFactory(context, decodeAv1)
|
||||||
.setEnableDecoderFallback(true)
|
.setEnableDecoderFallback(true)
|
||||||
.setExtensionRendererMode(rendererMode)
|
.setExtensionRendererMode(rendererMode)
|
||||||
|
|
||||||
val mediaSourceFactory =
|
val mediaSourceFactory =
|
||||||
if (useLibAss) {
|
if (useLibAss) {
|
||||||
val renderType =
|
val renderType =
|
||||||
|
|
@ -129,7 +132,9 @@ class PlayerFactory
|
||||||
extractorsFactory,
|
extractorsFactory,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val trackSelector = createTrackSelector()
|
val tunneling =
|
||||||
|
appPreferences.experimentalPreferences.get { videoTunnelingEnabled }
|
||||||
|
val trackSelector = createTrackSelector(tunneling)
|
||||||
|
|
||||||
ExoPlayer
|
ExoPlayer
|
||||||
.Builder(context)
|
.Builder(context)
|
||||||
|
|
@ -200,11 +205,13 @@ class PlayerFactory
|
||||||
.setConstantBitrateSeekingEnabled(true)
|
.setConstantBitrateSeekingEnabled(true)
|
||||||
.setConstantBitrateSeekingAlwaysEnabled(true)
|
.setConstantBitrateSeekingAlwaysEnabled(true)
|
||||||
|
|
||||||
private fun createTrackSelector() =
|
private fun createTrackSelector(tunneling: Boolean? = null) =
|
||||||
DefaultTrackSelector(context).apply {
|
DefaultTrackSelector(context).apply {
|
||||||
setParameters(
|
setParameters(
|
||||||
buildUponParameters()
|
buildUponParameters()
|
||||||
.setAudioOffloadPreferences(
|
.apply {
|
||||||
|
tunneling?.let { setTunnelingEnabled(tunneling) }
|
||||||
|
}.setAudioOffloadPreferences(
|
||||||
AudioOffloadPreferences
|
AudioOffloadPreferences
|
||||||
.Builder()
|
.Builder()
|
||||||
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
|
.setAudioOffloadMode(AudioOffloadPreferences.AUDIO_OFFLOAD_MODE_ENABLED)
|
||||||
|
|
|
||||||
|
|
@ -253,7 +253,7 @@ class PlaybackViewModel
|
||||||
val playerCreation =
|
val playerCreation =
|
||||||
playerFactory.createVideoPlayer(
|
playerFactory.createVideoPlayer(
|
||||||
playerBackend,
|
playerBackend,
|
||||||
preferences.appPreferences.playbackPreferences,
|
preferences.appPreferences,
|
||||||
)
|
)
|
||||||
this.player = playerCreation.player
|
this.player = playerCreation.player
|
||||||
currentPlayer.update {
|
currentPlayer.update {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ enum class PreferenceScreenOption {
|
||||||
MPV,
|
MPV,
|
||||||
SCREENSAVER,
|
SCREENSAVER,
|
||||||
SKIP_SEGMENTS,
|
SKIP_SEGMENTS,
|
||||||
|
EXPERIMENTAL,
|
||||||
;
|
;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,16 @@ import coil3.imageLoader
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
|
import com.github.damontecres.wholphin.preferences.AppSwitchPreference
|
||||||
import com.github.damontecres.wholphin.preferences.ExoPlayerPreferences
|
import com.github.damontecres.wholphin.preferences.ExoPlayerPreferences
|
||||||
|
import com.github.damontecres.wholphin.preferences.ExperimentalPreference
|
||||||
import com.github.damontecres.wholphin.preferences.MpvPreferences
|
import com.github.damontecres.wholphin.preferences.MpvPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||||
import com.github.damontecres.wholphin.preferences.ScreensaverPreference
|
import com.github.damontecres.wholphin.preferences.ScreensaverPreference
|
||||||
import com.github.damontecres.wholphin.preferences.SkipSegmentPreferences
|
import com.github.damontecres.wholphin.preferences.SkipSegmentPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.advancedPreferences
|
import com.github.damontecres.wholphin.preferences.advancedPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.basicPreferences
|
import com.github.damontecres.wholphin.preferences.basicPreferences
|
||||||
|
import com.github.damontecres.wholphin.preferences.experimentalPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.screensaverPreferences
|
import com.github.damontecres.wholphin.preferences.screensaverPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences
|
import com.github.damontecres.wholphin.preferences.updatePlaybackPreferences
|
||||||
import com.github.damontecres.wholphin.services.Release
|
import com.github.damontecres.wholphin.services.Release
|
||||||
|
|
@ -148,6 +151,7 @@ fun PreferencesContent(
|
||||||
PreferenceScreenOption.MPV -> MpvPreferences
|
PreferenceScreenOption.MPV -> MpvPreferences
|
||||||
PreferenceScreenOption.SCREENSAVER -> screensaverPreferences
|
PreferenceScreenOption.SCREENSAVER -> screensaverPreferences
|
||||||
PreferenceScreenOption.SKIP_SEGMENTS -> SkipSegmentPreferences
|
PreferenceScreenOption.SKIP_SEGMENTS -> SkipSegmentPreferences
|
||||||
|
PreferenceScreenOption.EXPERIMENTAL -> experimentalPreferences
|
||||||
}
|
}
|
||||||
val screenTitle =
|
val screenTitle =
|
||||||
when (preferenceScreenOption) {
|
when (preferenceScreenOption) {
|
||||||
|
|
@ -157,6 +161,7 @@ fun PreferencesContent(
|
||||||
PreferenceScreenOption.MPV -> R.string.mpv_options
|
PreferenceScreenOption.MPV -> R.string.mpv_options
|
||||||
PreferenceScreenOption.SCREENSAVER -> R.string.screensaver_settings
|
PreferenceScreenOption.SCREENSAVER -> R.string.screensaver_settings
|
||||||
PreferenceScreenOption.SKIP_SEGMENTS -> R.string.skip_behavior
|
PreferenceScreenOption.SKIP_SEGMENTS -> R.string.skip_behavior
|
||||||
|
PreferenceScreenOption.EXPERIMENTAL -> R.string.experimental_settings
|
||||||
}
|
}
|
||||||
|
|
||||||
var visible by remember { mutableStateOf(false) }
|
var visible by remember { mutableStateOf(false) }
|
||||||
|
|
@ -569,6 +574,46 @@ fun PreferencesContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExperimentalPreference.Enable -> {
|
||||||
|
var showConfirm by remember { mutableStateOf(false) }
|
||||||
|
pref as AppSwitchPreference<AppPreferences>
|
||||||
|
val value = pref.getter.invoke(preferences)
|
||||||
|
SwitchPreference(
|
||||||
|
title = stringResource(pref.title),
|
||||||
|
value = value,
|
||||||
|
onClick = {
|
||||||
|
if (value) {
|
||||||
|
scope.launch(ExceptionHandler()) {
|
||||||
|
preferences =
|
||||||
|
viewModel.preferenceDataStore.updateData { prefs ->
|
||||||
|
pref.setter.invoke(prefs, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
showConfirm = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
summaryOn = pref.summaryOn?.let { stringResource(pref.summaryOn) },
|
||||||
|
summaryOff = pref.summaryOff?.let { stringResource(pref.summaryOff) },
|
||||||
|
)
|
||||||
|
if (showConfirm) {
|
||||||
|
ConfirmDialog(
|
||||||
|
title = stringResource(R.string.confirm_enable_experimental_title),
|
||||||
|
body = stringResource(R.string.confirm_enable_experimental_body),
|
||||||
|
onCancel = { showConfirm = false },
|
||||||
|
onConfirm = {
|
||||||
|
showConfirm = false
|
||||||
|
scope.launch(ExceptionHandler()) {
|
||||||
|
preferences =
|
||||||
|
viewModel.preferenceDataStore.updateData { prefs ->
|
||||||
|
pref.setter.invoke(prefs, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val value = pref.getter.invoke(preferences)
|
val value = pref.getter.invoke(preferences)
|
||||||
ComposablePreference(
|
ComposablePreference(
|
||||||
|
|
@ -762,6 +807,7 @@ fun PreferencesPage(
|
||||||
PreferenceScreenOption.MPV,
|
PreferenceScreenOption.MPV,
|
||||||
PreferenceScreenOption.SCREENSAVER,
|
PreferenceScreenOption.SCREENSAVER,
|
||||||
PreferenceScreenOption.SKIP_SEGMENTS,
|
PreferenceScreenOption.SKIP_SEGMENTS,
|
||||||
|
PreferenceScreenOption.EXPERIMENTAL,
|
||||||
-> {
|
-> {
|
||||||
PreferencesContent(
|
PreferencesContent(
|
||||||
initialPreferences,
|
initialPreferences,
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ class SlideshowViewModel
|
||||||
val playerCreation =
|
val playerCreation =
|
||||||
playerFactory.createVideoPlayer(
|
playerFactory.createVideoPlayer(
|
||||||
backend = PlayerBackend.EXO_PLAYER,
|
backend = PlayerBackend.EXO_PLAYER,
|
||||||
appPreferences.playbackPreferences,
|
appPreferences,
|
||||||
)
|
)
|
||||||
player = playerCreation.player
|
player = playerCreation.player
|
||||||
player.addListener(this@SlideshowViewModel)
|
player.addListener(this@SlideshowViewModel)
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,11 @@ message MusicPreferences {
|
||||||
bool show_backdrop = 4;
|
bool show_backdrop = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ExperimentalPreferences {
|
||||||
|
bool enabled = 1;
|
||||||
|
bool video_tunneling_enabled = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message AppPreferences {
|
message AppPreferences {
|
||||||
// The currently signed in server and user IDs, mostly for restoring a session
|
// The currently signed in server and user IDs, mostly for restoring a session
|
||||||
string current_server_id = 1;
|
string current_server_id = 1;
|
||||||
|
|
@ -229,4 +234,5 @@ message AppPreferences {
|
||||||
bool sign_in_automatically = 11;
|
bool sign_in_automatically = 11;
|
||||||
PhotoPreferences photo_preferences = 12;
|
PhotoPreferences photo_preferences = 12;
|
||||||
MusicPreferences music_preferences = 13;
|
MusicPreferences music_preferences = 13;
|
||||||
|
ExperimentalPreferences experimental_preferences = 14;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -829,4 +829,8 @@
|
||||||
<string name="popularity">Popularity</string>
|
<string name="popularity">Popularity</string>
|
||||||
<string name="production_status">Production status</string>
|
<string name="production_status">Production status</string>
|
||||||
<string name="different_for_hdr">Use different style for HDR</string>
|
<string name="different_for_hdr">Use different style for HDR</string>
|
||||||
|
<string name="experimental_settings">Experimental settings</string>
|
||||||
|
<string name="confirm_enable_experimental_title">Enable experimental settings?</string>
|
||||||
|
<string name="confirm_enable_experimental_body">Experimental settings may be unstable!\n\n These may removed or changed in any release.</string>
|
||||||
|
<string name="video_tunneling">Video tunneling</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue