diff --git a/Limelight/Stream/Connection.m b/Limelight/Stream/Connection.m index 2129ca2..664b7ad 100644 --- a/Limelight/Stream/Connection.m +++ b/Limelight/Stream/Connection.m @@ -302,6 +302,11 @@ void ClConnectionStatusUpdate(int status) [_callbacks connectionStatusUpdate:status]; } +void ClSetHdrMode(bool enabled) +{ + [_callbacks setHdrMode:enabled]; +} + -(void) terminate { // Interrupt any action blocking LiStartConnection(). This is @@ -453,6 +458,7 @@ void ClConnectionStatusUpdate(int status) _clCallbacks.logMessage = ClLogMessage; _clCallbacks.rumble = ClRumble; _clCallbacks.connectionStatusUpdate = ClConnectionStatusUpdate; + _clCallbacks.setHdrMode = ClSetHdrMode; return self; } diff --git a/Limelight/Stream/ConnectionCallbacks.h b/Limelight/Stream/ConnectionCallbacks.h index c7acac9..3da578b 100644 --- a/Limelight/Stream/ConnectionCallbacks.h +++ b/Limelight/Stream/ConnectionCallbacks.h @@ -16,6 +16,7 @@ - (void) launchFailed:(NSString*)message; - (void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor; - (void) connectionStatusUpdate:(int)status; +- (void) setHdrMode:(bool)enabled; - (void) videoContentShown; @end diff --git a/Limelight/ViewControllers/StreamFrameViewController.h b/Limelight/ViewControllers/StreamFrameViewController.h index 6e95919..a8a3806 100644 --- a/Limelight/ViewControllers/StreamFrameViewController.h +++ b/Limelight/ViewControllers/StreamFrameViewController.h @@ -21,4 +21,6 @@ #endif @property (nonatomic) StreamConfiguration* streamConfig; +-(void)updatePreferredDisplayMode:(BOOL)streamActive; + @end diff --git a/Limelight/ViewControllers/StreamFrameViewController.m b/Limelight/ViewControllers/StreamFrameViewController.m index e7a2028..ed54606 100644 --- a/Limelight/ViewControllers/StreamFrameViewController.m +++ b/Limelight/ViewControllers/StreamFrameViewController.m @@ -18,6 +18,18 @@ #include #include +#if TARGET_OS_TV +#import +#import +#import +#endif + +@interface AVDisplayCriteria() +@property(readonly) int videoDynamicRange; +@property(readonly, nonatomic) float refreshRate; +- (id)initWithRefreshRate:(float)arg1 videoDynamicRange:(int)arg2; +@end + @implementation StreamFrameViewController { ControllerSupport *_controllerSupport; StreamManager *_streamMan; @@ -294,6 +306,9 @@ } - (void) returnToMainFrame { + // Reset display mode back to default + [self updatePreferredDisplayMode:NO]; + [_statsUpdateTimer invalidate]; _statsUpdateTimer = nil; @@ -532,6 +547,42 @@ }); } +- (void) updatePreferredDisplayMode:(BOOL)streamActive { +#if TARGET_OS_TV + if (@available(tvOS 11.2, *)) { + UIWindow* window = [[[UIApplication sharedApplication] delegate] window]; + AVDisplayManager* displayManager = [window avDisplayManager]; + + // This logic comes from Kodi and MrMC + if (streamActive) { + int dynamicRange; + + if (LiGetCurrentHostDisplayHdrMode()) { + dynamicRange = 2; // HDR10 + } + else { + dynamicRange = 0; // SDR + } + + AVDisplayCriteria* displayCriteria = [[AVDisplayCriteria alloc] initWithRefreshRate:[_settings.framerate floatValue] + videoDynamicRange:dynamicRange]; + displayManager.preferredDisplayCriteria = displayCriteria; + } + else { + // Switch back to the default display mode + displayManager.preferredDisplayCriteria = nil; + } + } +#endif +} + +- (void) setHdrMode:(bool)enabled { + Log(LOG_I, @"HDR is now: %s", enabled ? "active" : "inactive"); + dispatch_async(dispatch_get_main_queue(), ^{ + [self updatePreferredDisplayMode:YES]; + }); +} + - (void) videoContentShown { [_spinner stopAnimating]; [self.view setBackgroundColor:[UIColor blackColor]]; diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj index 03eb33e..94b2345 100644 --- a/Moonlight.xcodeproj/project.pbxproj +++ b/Moonlight.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ 9896219A23D56E8100211983 /* X1Kit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9896219623D15C7000211983 /* X1Kit.swift */; }; 9897B6A1221260EF00966419 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* Controller.m */; }; 9897B6A62212732C00966419 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = 9897B6A0221260EF00966419 /* Controller.m */; }; + 98B9CE6D27B2144B00B473C4 /* AVKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98B9CE6C27B2144B00B473C4 /* AVKit.framework */; }; 98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AB2E841CAD46840089BB98 /* libmoonlight-common.a */; }; 98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; }; 98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; }; @@ -189,6 +190,7 @@ 9897B6A0221260EF00966419 /* Controller.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = ""; }; 9897B6A32212610800966419 /* Controller.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = ""; }; 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "moonlight-common/moonlight-common.xcodeproj"; sourceTree = ""; }; + 98B9CE6C27B2144B00B473C4 /* AVKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVKit.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS15.2.sdk/System/Library/Frameworks/AVKit.framework; sourceTree = DEVELOPER_DIR; }; 98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryHost.h; path = Database/TemporaryHost.h; sourceTree = ""; }; 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryHost.m; path = Database/TemporaryHost.m; sourceTree = ""; }; 98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporarySettings.h; path = Database/TemporarySettings.h; sourceTree = ""; }; @@ -393,6 +395,7 @@ FB1A67E621324DD600507771 /* libcrypto.a in Frameworks */, FB1A67E721324DD600507771 /* libssl.a in Frameworks */, FB1A67E521324A1F00507771 /* CoreData.framework in Frameworks */, + 98B9CE6D27B2144B00B473C4 /* AVKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -471,6 +474,7 @@ FB290CF019B2C406004C83CF /* Frameworks */ = { isa = PBXGroup; children = ( + 98B9CE6C27B2144B00B473C4 /* AVKit.framework */, 98181BEC2791281100E43572 /* CoreMotion.framework */, 98181BE82791275D00E43572 /* libSDL2.a */, 98181BEA2791278300E43572 /* libSDL2.a */, diff --git a/moonlight-common/moonlight-common-c b/moonlight-common/moonlight-common-c index 6001ece..e62dc56 160000 --- a/moonlight-common/moonlight-common-c +++ b/moonlight-common/moonlight-common-c @@ -1 +1 @@ -Subproject commit 6001ece0b8bfcea6a8122a3e56f48f515e1aaaf5 +Subproject commit e62dc56047b038e5f2a5404b023fec453bf1bf8a