diff --git a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt
index 9bc61d7f1..7fcb7d815 100644
--- a/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt
+++ b/composeApp/src/androidMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.android.kt
@@ -1149,6 +1149,9 @@ actual object PlayerSettingsStorage {
?.apply()
}
+ actual fun loadWindowsHdmiPassthroughEnabled(): Boolean? = null
+
+ actual fun saveWindowsHdmiPassthroughEnabled(enabled: Boolean) = Unit
actual fun exportToSyncPayload(): JsonObject = buildJsonObject {
loadShowLoadingOverlay()?.let { put(showLoadingOverlayKey, encodeSyncBoolean(it)) }
diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 6d6cb1443..214b0728b 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -1952,6 +1952,10 @@
Custom
Use your advanced values below.
Off
+
+ Windows audio
+ HDMI audio passthrough
+ Send Dolby Digital, Dolby Digital Plus/Atmos, TrueHD/Atmos, DTS, DTS-HD, and DTS:X unchanged to the Windows default HDMI receiver. The receiver controls volume; unsupported audio plays as decoded PCM.
NVIDIA RTX Video
RTX Video Super Resolution
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt
index df6e40cc0..4be9929d3 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsRepository.kt
@@ -95,6 +95,7 @@ data class PlayerSettingsUiState(
val iosSaturation: Int = 0,
val iosGamma: Int = 0,
val nvidiaRtxSuperResolutionEnabled: Boolean = false,
+ val windowsHdmiPassthroughEnabled: Boolean = false,
)
object PlayerSettingsRepository {
@@ -164,6 +165,7 @@ object PlayerSettingsRepository {
private var iosSaturation = 0
private var iosGamma = 0
private var nvidiaRtxSuperResolutionEnabled = false
+ private var windowsHdmiPassthroughEnabled = false
fun ensureLoaded() {
if (hasLoaded) return
@@ -238,6 +240,7 @@ object PlayerSettingsRepository {
iosSaturation = 0
iosGamma = 0
nvidiaRtxSuperResolutionEnabled = false
+ windowsHdmiPassthroughEnabled = false
publish()
}
@@ -389,6 +392,7 @@ object PlayerSettingsRepository {
iosSaturation = PlayerSettingsStorage.loadIosSaturation() ?: 0
iosGamma = PlayerSettingsStorage.loadIosGamma() ?: 0
nvidiaRtxSuperResolutionEnabled = PlayerSettingsStorage.loadNvidiaRtxSuperResolutionEnabled() ?: false
+ windowsHdmiPassthroughEnabled = PlayerSettingsStorage.loadWindowsHdmiPassthroughEnabled() ?: false
publish()
}
@@ -794,6 +798,14 @@ object PlayerSettingsRepository {
PlayerSettingsStorage.saveNvidiaRtxSuperResolutionEnabled(enabled)
}
+ fun setWindowsHdmiPassthroughEnabled(enabled: Boolean) {
+ ensureLoaded()
+ if (windowsHdmiPassthroughEnabled == enabled) return
+ windowsHdmiPassthroughEnabled = enabled
+ publish()
+ PlayerSettingsStorage.saveWindowsHdmiPassthroughEnabled(enabled)
+ }
+
fun setLibassRenderType(renderType: String) {
ensureLoaded()
if (libassRenderType == renderType) return
@@ -1031,6 +1043,7 @@ object PlayerSettingsRepository {
iosSaturation = iosSaturation,
iosGamma = iosGamma,
nvidiaRtxSuperResolutionEnabled = nvidiaRtxSuperResolutionEnabled,
+ windowsHdmiPassthroughEnabled = windowsHdmiPassthroughEnabled,
)
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt
index 108fa1da5..ac22d381c 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.kt
@@ -148,6 +148,8 @@ internal expect object PlayerSettingsStorage {
fun saveIosGamma(value: Int)
fun loadNvidiaRtxSuperResolutionEnabled(): Boolean?
fun saveNvidiaRtxSuperResolutionEnabled(enabled: Boolean)
+ fun loadWindowsHdmiPassthroughEnabled(): Boolean?
+ fun saveWindowsHdmiPassthroughEnabled(enabled: Boolean)
fun exportToSyncPayload(): JsonObject
fun replaceFromSyncPayload(payload: JsonObject)
}
diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/PlaybackSettingsPage.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/PlaybackSettingsPage.kt
index 0c63b92b6..12b59594b 100644
--- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/PlaybackSettingsPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/settings/PlaybackSettingsPage.kt
@@ -986,6 +986,21 @@ private fun PlaybackSettingsSection(
}
if (isWindows) {
+ SettingsSection(
+ title = stringResource(Res.string.settings_playback_windows_audio_section),
+ isTablet = isTablet,
+ ) {
+ SettingsGroup(isTablet = isTablet) {
+ SettingsSwitchRow(
+ title = stringResource(Res.string.settings_playback_hdmi_passthrough),
+ description = stringResource(Res.string.settings_playback_hdmi_passthrough_desc),
+ checked = autoPlayPlayerSettings.windowsHdmiPassthroughEnabled,
+ isTablet = isTablet,
+ onCheckedChange = PlayerSettingsRepository::setWindowsHdmiPassthroughEnabled,
+ )
+ }
+ }
+
SettingsSection(
title = stringResource(Res.string.settings_playback_nvidia_rtx_video_section),
isTablet = isTablet,
diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerEngine.desktop.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerEngine.desktop.kt
index 89cb42fba..205e278e5 100644
--- a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerEngine.desktop.kt
+++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerEngine.desktop.kt
@@ -126,6 +126,8 @@ private fun NativePlayerSurface(
val playerSettings by PlayerSettingsRepository.uiState.collectAsState()
val decoderPriority = playerSettings.decoderPriority
val nvidiaRtxSuperResolutionEnabled = playerSettings.nvidiaRtxSuperResolutionEnabled
+ val windowsHdmiPassthroughEnabled =
+ DesktopHostOs.current == DesktopHostOs.WINDOWS && playerSettings.windowsHdmiPassthroughEnabled
SideEffect {
onControllerReady(controller)
@@ -188,6 +190,7 @@ private fun NativePlayerSurface(
playbackHeaders,
decoderPriority,
nvidiaRtxSuperResolutionEnabled,
+ windowsHdmiPassthroughEnabled,
hostFirstFullSizePaintComplete.value,
initialPositionMs,
initialPositionRequestKey,
@@ -203,6 +206,7 @@ private fun NativePlayerSurface(
initialPositionMs = initialPositionMs,
decoderPriority = decoderPriority,
nvidiaRtxSuperResolutionEnabled = nvidiaRtxSuperResolutionEnabled,
+ windowsHdmiPassthroughEnabled = windowsHdmiPassthroughEnabled,
onError = { message -> latestOnError.value(message) },
)
initialPositionRequestKey?.let { key ->
diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.desktop.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.desktop.kt
index 401e31fb7..fe04c0c48 100644
--- a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.desktop.kt
+++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.desktop.kt
@@ -89,6 +89,7 @@ internal actual object PlayerSettingsStorage {
private const val iosSaturationKey = "ios_saturation"
private const val iosGammaKey = "ios_gamma"
private const val nvidiaRtxSuperResolutionEnabledKey = "nvidia_rtx_super_resolution_enabled"
+ private const val windowsHdmiPassthroughEnabledKey = "windows_hdmi_passthrough_enabled"
private val syncKeys = listOf(
showLoadingOverlayKey,
showParentalGuideKey,
@@ -312,6 +313,9 @@ internal actual object PlayerSettingsStorage {
actual fun loadNvidiaRtxSuperResolutionEnabled(): Boolean? = loadBoolean(nvidiaRtxSuperResolutionEnabledKey)
actual fun saveNvidiaRtxSuperResolutionEnabled(enabled: Boolean) = saveBoolean(nvidiaRtxSuperResolutionEnabledKey, enabled)
+ actual fun loadWindowsHdmiPassthroughEnabled(): Boolean? = loadBoolean(windowsHdmiPassthroughEnabledKey)
+ actual fun saveWindowsHdmiPassthroughEnabled(enabled: Boolean) =
+ saveBoolean(windowsHdmiPassthroughEnabledKey, enabled)
private fun scoped(key: String): String = ProfileScopedKey.of(key)
private fun loadString(key: String): String? = store.getString(scoped(key))
diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerBridge.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerBridge.kt
index 9d78dea90..061a9a95e 100644
--- a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerBridge.kt
+++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerBridge.kt
@@ -43,6 +43,7 @@ internal object NativePlayerBridge {
controlsPageUrl: String,
decoderPriority: Int,
nvidiaRtxSuperResolutionEnabled: Boolean,
+ windowsHdmiPassthroughEnabled: Boolean,
eventSink: NativePlayerEventSink,
): Long
diff --git a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerController.kt b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerController.kt
index b108d3f59..c54a99f09 100644
--- a/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerController.kt
+++ b/composeApp/src/desktopMain/kotlin/com/nuvio/app/features/player/desktop/NativePlayerController.kt
@@ -43,6 +43,7 @@ internal typealias NativePlayerCreate = (
String,
Int,
Boolean,
+ Boolean,
NativePlayerEventSink,
) -> Long
@@ -113,6 +114,7 @@ internal class NativePlayerController(
initialPositionMs: Long,
decoderPriority: Int,
nvidiaRtxSuperResolutionEnabled: Boolean,
+ windowsHdmiPassthroughEnabled: Boolean,
onError: (String?) -> Unit,
) {
val pending = PendingSource(
@@ -122,6 +124,7 @@ internal class NativePlayerController(
initialPositionMs = initialPositionMs.coerceAtLeast(0L),
decoderPriority = decoderPriority,
nvidiaRtxSuperResolutionEnabled = nvidiaRtxSuperResolutionEnabled,
+ windowsHdmiPassthroughEnabled = windowsHdmiPassthroughEnabled,
onError = onError,
)
var terminalFailure: String? = null
@@ -144,7 +147,8 @@ internal class NativePlayerController(
}
log.d {
"attach requested source=${sourceUrl.toPlaybackLogKey()} headers=${sourceHeaders.size} " +
- "playWhenReady=$playWhenReady initialPositionMs=$initialPositionMs decoderPriority=$decoderPriority"
+ "playWhenReady=$playWhenReady initialPositionMs=$initialPositionMs decoderPriority=$decoderPriority " +
+ "hdmiPassthrough=$windowsHdmiPassthroughEnabled"
}
host.onPeerReady = { attachPending() }
if (isHostDisplayable()) {
@@ -296,6 +300,7 @@ internal class NativePlayerController(
NativePlayerBridge.controlsPageUrl,
pending.decoderPriority,
pending.nvidiaRtxSuperResolutionEnabled,
+ pending.windowsHdmiPassthroughEnabled,
eventSink,
).also { if (it == 0L) error("Native player did not return a handle.") }
}.onSuccess { created ->
@@ -546,6 +551,7 @@ internal class NativePlayerController(
}
private fun setFallbackVolume(level: Float) {
+ if (pendingSource?.windowsHdmiPassthroughEnabled == true) return
val current = handle
if (current != 0L) {
val nextLevel = level.coerceIn(0f, 1f)
@@ -570,6 +576,10 @@ internal class NativePlayerController(
private fun applyRememberedVolume() {
val current = handle
if (current == 0L) return
+ if (pendingSource?.windowsHdmiPassthroughEnabled == true) {
+ controlsState = controlsState.copy(volumeLevel = 1f)
+ return
+ }
val level = rememberedVolumeLevel.coerceIn(0f, 1f)
NativePlayerBridge.setVolume(current, level)
controlsState = controlsState.copy(volumeLevel = level)
@@ -584,6 +594,7 @@ internal class NativePlayerController(
}
private fun cycleFallbackSpeed() {
+ if (pendingSource?.windowsHdmiPassthroughEnabled == true) return
val current = handle
if (current == 0L) return
val speeds = listOf(1f, 1.25f, 1.5f, 2f)
@@ -873,12 +884,14 @@ internal class NativePlayerController(
initialPositionMs = pending.initialPositionMs,
decoderPriority = pending.decoderPriority,
nvidiaRtxSuperResolutionEnabled = pending.nvidiaRtxSuperResolutionEnabled,
+ windowsHdmiPassthroughEnabled = pending.windowsHdmiPassthroughEnabled,
onError = pending.onError,
)
}
override fun setPlaybackSpeed(speed: Float) {
log.d { "setPlaybackSpeed speed=$speed handle=$handle" }
+ if (pendingSource?.windowsHdmiPassthroughEnabled == true) return
handle.takeIf { it != 0L }?.let { NativePlayerBridge.setSpeed(it, speed) }
}
@@ -1089,6 +1102,7 @@ private data class PendingSource(
val initialPositionMs: Long,
val decoderPriority: Int,
val nvidiaRtxSuperResolutionEnabled: Boolean,
+ val windowsHdmiPassthroughEnabled: Boolean,
val onError: (String?) -> Unit,
)
diff --git a/composeApp/src/desktopMain/native/linux/player_bridge.cpp b/composeApp/src/desktopMain/native/linux/player_bridge.cpp
index 5c3d47f11..97ab84f04 100644
--- a/composeApp/src/desktopMain/native/linux/player_bridge.cpp
+++ b/composeApp/src/desktopMain/native/linux/player_bridge.cpp
@@ -1457,7 +1457,8 @@ JNIEXPORT jlong JNICALL NP(create)(
JNIEnv *env, jobject /*thiz*/, jlong hostViewPtr, jstring sourceUrl,
jobjectArray headerLines, jboolean playWhenReady, jlong initialPositionMs,
jstring controlsPageUrl, jint decoderPriority,
- jboolean /*nvidiaRtxSuperResolutionEnabled*/, jobject eventSink) {
+ jboolean /*nvidiaRtxSuperResolutionEnabled*/,
+ jboolean /*windowsHdmiPassthroughEnabled*/, jobject eventSink) {
// libmpv requires LC_NUMERIC=C (e.g. non-"C" locales with comma
// decimals make mpv_create fail); the JVM uses java.util.Locale, so
diff --git a/composeApp/src/desktopMain/native/macos/player_bridge.mm b/composeApp/src/desktopMain/native/macos/player_bridge.mm
index dee7cc7e7..1138268e5 100644
--- a/composeApp/src/desktopMain/native/macos/player_bridge.mm
+++ b/composeApp/src/desktopMain/native/macos/player_bridge.mm
@@ -2543,6 +2543,7 @@ static void throwJavaError(JNIEnv *env, NSString *message) {
jstring controlsPageUrl,
jint decoderPriority,
jboolean nvidiaRtxSuperResolutionEnabled,
+ jboolean /* windowsHdmiPassthroughEnabled */,
jobject eventSink
) {
NSView *hostView = (__bridge NSView *)(void *)(intptr_t)hostViewPtr;
diff --git a/composeApp/src/desktopMain/native/windows/player_bridge.cpp b/composeApp/src/desktopMain/native/windows/player_bridge.cpp
index a97bccd9e..1b6925364 100644
--- a/composeApp/src/desktopMain/native/windows/player_bridge.cpp
+++ b/composeApp/src/desktopMain/native/windows/player_bridge.cpp
@@ -849,6 +849,7 @@ class WindowsMpvWebPlayer : public std::enable_shared_from_this();
auto self = shared_from_this();
uiThread = std::thread(
- [self, sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled, initState]() {
- self->runNativeUiThread(sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled, initState);
+ [self, sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled, windowsHdmiPassthroughEnabled, initState]() {
+ self->runNativeUiThread(sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled, windowsHdmiPassthroughEnabled, initState);
}
);
@@ -1302,11 +1303,12 @@ class WindowsMpvWebPlayer : public std::enable_shared_from_this initState
) {
std::string failure;
try {
- initializeOnNativeUiThread(sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled);
+ initializeOnNativeUiThread(sourceUrl, headerLines, playWhenReady, initialPositionMs, controlsUrl, decoderPriority, nvidiaRtxSuperResolutionEnabled, windowsHdmiPassthroughEnabled);
} catch (const std::exception &error) {
failure = error.what();
cleanupUiResources();
@@ -1337,7 +1339,8 @@ class WindowsMpvWebPlayer : public std::enable_shared_from_this
+private val failNativeCreate: NativePlayerCreate = { _, _, _, _, _, _, _, _, _, _ ->
error("native create must not run in lifecycle unit tests")
}
@@ -52,6 +52,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = {},
)
@@ -78,7 +79,7 @@ class NativePlayerControllerTeardownTest {
val disposedHandles = Collections.synchronizedList(mutableListOf())
val controller = NativePlayerController(
host = NativePlayerHost(),
- nativeCreate = { _, source, _, _, _, _, _, _, _ ->
+ nativeCreate = { _, source, _, _, _, _, _, _, _, _ ->
createdSources += source
when (source) {
sourceA -> {
@@ -113,6 +114,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = {},
)
assertTrue(createAStarted.await(2, TimeUnit.SECONDS))
@@ -125,6 +127,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = {},
)
@@ -174,6 +177,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { errors.incrementAndGet() },
)
SwingUtilities.invokeAndWait {}
@@ -234,6 +238,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = {},
)
SwingUtilities.invokeAndWait {}
@@ -251,6 +256,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { replacementErrors.incrementAndGet() },
)
allowEdt.countDown()
@@ -293,6 +299,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { errors.incrementAndGet() },
)
SwingUtilities.invokeAndWait {}
@@ -330,6 +337,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { errors.incrementAndGet() },
)
@@ -356,6 +364,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = {},
)
@@ -425,6 +434,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { retryError.countDown() },
)
controller.startTrackedDisposeForTest(42L)
@@ -471,6 +481,7 @@ class NativePlayerControllerTeardownTest {
initialPositionMs = 0L,
decoderPriority = 0,
nvidiaRtxSuperResolutionEnabled = false,
+ windowsHdmiPassthroughEnabled = false,
onError = { replacementError.countDown() },
)
SwingUtilities.invokeAndWait {}
diff --git a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt
index aef697c46..0ca9f839f 100644
--- a/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt
+++ b/composeApp/src/iosMain/kotlin/com/nuvio/app/features/player/PlayerSettingsStorage.ios.kt
@@ -947,6 +947,10 @@ actual object PlayerSettingsStorage {
NSUserDefaults.standardUserDefaults.setBool(enabled, forKey = ProfileScopedKey.of(nvidiaRtxSuperResolutionEnabledKey))
}
+ actual fun loadWindowsHdmiPassthroughEnabled(): Boolean? = null
+
+ actual fun saveWindowsHdmiPassthroughEnabled(enabled: Boolean) = Unit
+
actual fun exportToSyncPayload(): JsonObject = buildJsonObject {
loadShowLoadingOverlay()?.let { put(showLoadingOverlayKey, encodeSyncBoolean(it)) }
loadShowParentalGuide()?.let { put(showParentalGuideKey, encodeSyncBoolean(it)) }