Skip to content

Commit 17a6d93

Browse files
committed
Slightly tweaked version of moonlight-stream#411 - external display support
1 parent da47035 commit 17a6d93

2 files changed

Lines changed: 89 additions & 9 deletions

File tree

Limelight/Stream/VideoDecoderRenderer.m

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,14 @@ - (id)initWithView:(StreamView*)view callbacks:(id<ConnectionCallbacks>)callback
8989
parameterSetBuffers = [[NSMutableArray alloc] init];
9090

9191
[self reinitializeDisplayLayer];
92-
92+
[[NSNotificationCenter defaultCenter] addObserver:self
93+
selector:@selector(reinitializeDisplayLayer)
94+
name:@"ScreenConnected"
95+
object:nil];
96+
[[NSNotificationCenter defaultCenter] addObserver:self
97+
selector:@selector(reinitializeDisplayLayer)
98+
name:@"ScreenDisconnected"
99+
object:nil];
93100
return self;
94101
}
95102

Limelight/ViewControllers/StreamFrameViewController.m

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ @implementation StreamFrameViewController {
4747
UIScrollView *_scrollView;
4848
BOOL _userIsInteracting;
4949
CGSize _keyboardSize;
50-
50+
UIWindow *_extWindow;
51+
UIView *_renderView;
52+
UIWindow *_deviceWindow;
53+
5154
#if !TARGET_OS_TV
5255
UIScreenEdgePanGestureRecognizer *_exitSwipeRecognizer;
5356
#endif
@@ -56,7 +59,30 @@ @implementation StreamFrameViewController {
5659
- (void)viewDidAppear:(BOOL)animated
5760
{
5861
[super viewDidAppear:animated];
59-
62+
63+
_deviceWindow = self.view.window;
64+
65+
if (UIScreen.screens.count > 1) {
66+
[self prepExtScreen:UIScreen.screens.lastObject];
67+
}
68+
else {
69+
dispatch_async(dispatch_get_main_queue(), ^{
70+
[self.view insertSubview:self->_renderView atIndex:0];
71+
});
72+
}
73+
74+
// check to see if external screen is connected/disconnected
75+
76+
[[NSNotificationCenter defaultCenter] addObserver: self
77+
selector: @selector(extScreenDidConnect:)
78+
name: UIScreenDidConnectNotification
79+
object: nil];
80+
81+
[[NSNotificationCenter defaultCenter] addObserver: self
82+
selector: @selector(extScreenDidDisconnect:)
83+
name: UIScreenDidDisconnectNotification
84+
object: nil];
85+
6086
#if !TARGET_OS_TV
6187
[[self revealViewController] setPrimaryViewController:self];
6288
#endif
@@ -106,7 +132,10 @@ - (void)viewDidLoad
106132

107133
_controllerSupport = [[ControllerSupport alloc] initWithConfig:self.streamConfig delegate:self];
108134
_inactivityTimer = nil;
109-
135+
136+
_renderView = (StreamView*)[[UIView alloc] initWithFrame:self.view.frame];
137+
_renderView.bounds = _streamView.bounds;
138+
110139
_streamView = [[StreamView alloc] initWithFrame:self.view.frame];
111140
[_streamView setupStreamView:_controllerSupport interactionDelegate:self config:self.streamConfig];
112141

@@ -152,7 +181,7 @@ - (void)viewDidLoad
152181
_tipLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height * 0.9);
153182

154183
_streamMan = [[StreamManager alloc] initWithConfig:self.streamConfig
155-
renderView:_streamView
184+
renderView:_renderView
156185
connectionCallbacks:self];
157186
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
158187
[opQueue addOperation:_streamMan];
@@ -313,6 +342,51 @@ - (void) returnToMainFrame {
313342
_statsUpdateTimer = nil;
314343

315344
[self.navigationController popToRootViewControllerAnimated:YES];
345+
_extWindow = nil;
346+
}
347+
348+
// External Screen connected
349+
- (void)extScreenDidConnect:(NSNotification *)notification {
350+
Log(LOG_I, @"External Screen Connected");
351+
dispatch_async(dispatch_get_main_queue(), ^{
352+
[self prepExtScreen:notification.object];
353+
});
354+
}
355+
356+
// External Screen disconnected
357+
- (void)extScreenDidDisconnect:(NSNotification *)notification {
358+
Log(LOG_I, @"External Screen Disconnected");
359+
if(UIScreen.screens.count < 2)
360+
{
361+
dispatch_async(dispatch_get_main_queue(), ^{
362+
[self removeExtScreen];
363+
});
364+
}
365+
}
366+
367+
// Prepare Screen
368+
- (void)prepExtScreen:(UIScreen*)extScreen {
369+
Log(LOG_I, @"Preparing External Screen");
370+
CGRect frame = extScreen.bounds;
371+
extScreen.overscanCompensation = 3;
372+
_extWindow = [[UIWindow alloc] initWithFrame:frame];
373+
_extWindow.screen = extScreen;
374+
_renderView.bounds = frame;
375+
_renderView.frame = frame;
376+
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
377+
[nc postNotificationName:@"ScreenConnected" object:self];
378+
[_extWindow addSubview:_renderView];
379+
_extWindow.hidden = NO;
380+
}
381+
382+
- (void)removeExtScreen {
383+
Log(LOG_I, @"Removing External Screen");
384+
_extWindow.hidden = YES;
385+
_renderView.bounds = _deviceWindow.bounds;
386+
_renderView.frame = _deviceWindow.frame;
387+
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
388+
[nc postNotificationName:@"ScreenDisconnected" object:self];
389+
[self.view insertSubview:_renderView atIndex:0];
316390
}
317391

318392
// This will fire if the user opens control center or gets a low battery message
@@ -370,13 +444,12 @@ - (void)edgeSwiped {
370444
- (void) connectionStarted {
371445
Log(LOG_I, @"Connection started");
372446
dispatch_async(dispatch_get_main_queue(), ^{
373-
// Leave the spinner spinning until it's obscured by
374-
// the first frame of video.
375447
self->_stageLabel.hidden = YES;
376448
self->_tipLabel.hidden = YES;
377449

378450
[self->_streamView showOnScreenControls];
379-
451+
//self.spinner.hidden = YES;
452+
380453
[self->_controllerSupport connectionEstablished];
381454

382455
if (self->_settings.statsOverlay) {
@@ -471,8 +544,8 @@ - (void)connectionTerminated:(int)errorCode {
471544
}
472545

473546
- (void) stageStarting:(const char*)stageName {
474-
Log(LOG_I, @"Starting %s", stageName);
475547
dispatch_async(dispatch_get_main_queue(), ^{
548+
Log(LOG_I, @"Starting %s", stageName);
476549
NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
477550
NSString* titleCase = [[[lowerCase substringToIndex:1] uppercaseString] stringByAppendingString:[lowerCase substringFromIndex:1]];
478551
[self->_stageLabel setText:titleCase];

0 commit comments

Comments
 (0)