Add tvOS display frame rate and dynamic range matching

Lets the Apple TV switch its HDMI output to match the playing video's
frame rate and dynamic range via AVDisplayManager.preferredDisplayCriteria,
driven from MPV's container-fps and video-params/gamma. Two opt-in toggles
(default off) live under Playback → Display on tvOS; both are no-ops on
other platforms. Anchor an AVKit class symbol so the linker keeps AVKit
linked — Swift only autolinks AVFoundation here, and without AVKit the
UIWindow.avDisplayManager category isn't loaded at runtime.
This commit is contained in:
Arkadiusz Fal
2026-05-10 01:30:55 +02:00
parent 100e762d4b
commit 6a343311ea
8 changed files with 333 additions and 0 deletions

View File

@@ -108,6 +108,8 @@ enum SettingsKey: String, CaseIterable {
case mpvBufferSeconds
case mpvUseEDLStreams
case zoomTransitionsEnabled
case tvMatchDisplayFrameRate
case tvMatchDisplayDynamicRange
// Details panel
case floatingDetailsPanelSide // Landscape only - which side the panel appears on

View File

@@ -141,6 +141,36 @@ extension SettingsManager {
}
}
/// Whether tvOS should request the Apple TV switch its HDMI output to match the
/// playing video's frame rate. Has no effect unless the user also enables
/// "Match Content Frame Rate" in tvOS Settings Video and Audio.
/// Default is true on tvOS (no-op on other platforms).
var tvMatchDisplayFrameRate: Bool {
get {
if let cached = _tvMatchDisplayFrameRate { return cached }
return bool(for: .tvMatchDisplayFrameRate, default: false)
}
set {
_tvMatchDisplayFrameRate = newValue
set(newValue, for: .tvMatchDisplayFrameRate)
}
}
/// Whether tvOS should request the Apple TV switch its HDMI output to match the
/// playing video's dynamic range (SDR / HDR10 / HLG). Has no effect unless the
/// user also enables "Match Content Dynamic Range" in tvOS Settings.
/// Default is true on tvOS (no-op on other platforms).
var tvMatchDisplayDynamicRange: Bool {
get {
if let cached = _tvMatchDisplayDynamicRange { return cached }
return bool(for: .tvMatchDisplayDynamicRange, default: false)
}
set {
_tvMatchDisplayDynamicRange = newValue
set(newValue, for: .tvMatchDisplayDynamicRange)
}
}
/// Whether zoom navigation transitions are enabled (iOS only).
/// When enabled, navigating to video/channel/playlist details shows a zoom animation
/// from the source thumbnail. Disable if experiencing visual glitches with swipe-back gestures.

View File

@@ -158,6 +158,8 @@ final class SettingsManager {
var _mpvBufferSeconds: Double?
var _mpvUseEDLStreams: Bool?
var _zoomTransitionsEnabled: Bool?
var _tvMatchDisplayFrameRate: Bool?
var _tvMatchDisplayDynamicRange: Bool?
// Details panel settings
var _floatingDetailsPanelSide: FloatingPanelSide?
@@ -492,6 +494,8 @@ final class SettingsManager {
_mpvBufferSeconds = nil
_mpvUseEDLStreams = nil
_zoomTransitionsEnabled = nil
_tvMatchDisplayFrameRate = nil
_tvMatchDisplayDynamicRange = nil
_floatingDetailsPanelSide = nil
_floatingDetailsPanelWidth = nil
_landscapeDetailsPanelVisible = nil