mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-02-16 10:31:02 +00:00
Create stream view hierarchy programmatically
This commit is contained in:
@@ -30,8 +30,6 @@
|
||||
@interface StreamView : UIView <X1KitMouseDelegate, UITextFieldDelegate, UIPointerInteractionDelegate>
|
||||
#endif
|
||||
|
||||
@property (nonatomic, retain) IBOutlet UITextField* keyInputField;
|
||||
|
||||
- (void) setupStreamView:(ControllerSupport*)controllerSupport
|
||||
swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate
|
||||
interactionDelegate:(id<UserInteractionDelegate>)interactionDelegate
|
||||
|
||||
@@ -19,6 +19,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
@implementation StreamView {
|
||||
OnScreenControls* onScreenControls;
|
||||
|
||||
UITextField* keyInputField;
|
||||
BOOL isInputingText;
|
||||
|
||||
float streamAspectRatio;
|
||||
@@ -51,6 +52,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
|
||||
TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
|
||||
|
||||
keyInputField = [[UITextField alloc] initWithFrame:CGRectZero];
|
||||
[self addSubview:keyInputField];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
// tvOS requires RelativeTouchHandler to manage Apple Remote input
|
||||
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
||||
@@ -164,18 +168,18 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||
if ([[event allTouches] count] == 3) {
|
||||
if (isInputingText) {
|
||||
Log(LOG_D, @"Closing the keyboard");
|
||||
[_keyInputField resignFirstResponder];
|
||||
[keyInputField resignFirstResponder];
|
||||
isInputingText = false;
|
||||
} else {
|
||||
Log(LOG_D, @"Opening the keyboard");
|
||||
// Prepare the textbox used to capture keyboard events.
|
||||
_keyInputField.delegate = self;
|
||||
_keyInputField.text = @"0";
|
||||
[_keyInputField becomeFirstResponder];
|
||||
[_keyInputField addTarget:self action:@selector(onKeyboardPressed:) forControlEvents:UIControlEventEditingChanged];
|
||||
keyInputField.delegate = self;
|
||||
keyInputField.text = @"0";
|
||||
[keyInputField becomeFirstResponder];
|
||||
[keyInputField addTarget:self action:@selector(onKeyboardPressed:) forControlEvents:UIControlEventEditingChanged];
|
||||
|
||||
// Undo causes issues for our state management, so turn it off
|
||||
[_keyInputField.undoManager disableUndoRegistration];
|
||||
[keyInputField.undoManager disableUndoRegistration];
|
||||
|
||||
isInputingText = true;
|
||||
}
|
||||
|
||||
@@ -19,19 +19,6 @@ typedef struct {
|
||||
int networkDroppedFrames;
|
||||
} video_stats_t;
|
||||
|
||||
@protocol ConnectionCallbacks <NSObject>
|
||||
|
||||
- (void) connectionStarted;
|
||||
- (void) connectionTerminated:(int)errorCode;
|
||||
- (void) stageStarting:(const char*)stageName;
|
||||
- (void) stageComplete:(const char*)stageName;
|
||||
- (void) stageFailed:(const char*)stageName withError:(int)errorCode portTestFlags:(int)portTestFlags;
|
||||
- (void) launchFailed:(NSString*)message;
|
||||
- (void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor;
|
||||
- (void) connectionStatusUpdate:(int)status;
|
||||
|
||||
@end
|
||||
|
||||
@interface Connection : NSOperation <NSStreamDelegate>
|
||||
|
||||
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks;
|
||||
|
||||
21
Limelight/Stream/ConnectionCallbacks.h
Normal file
21
Limelight/Stream/ConnectionCallbacks.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// ConnectionCallbacks.h
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Cameron Gutman on 11/1/20.
|
||||
// Copyright © 2020 Moonlight Game Streaming Project. All rights reserved.
|
||||
//
|
||||
|
||||
@protocol ConnectionCallbacks <NSObject>
|
||||
|
||||
- (void) connectionStarted;
|
||||
- (void) connectionTerminated:(int)errorCode;
|
||||
- (void) stageStarting:(const char*)stageName;
|
||||
- (void) stageComplete:(const char*)stageName;
|
||||
- (void) stageFailed:(const char*)stageName withError:(int)errorCode portTestFlags:(int)portTestFlags;
|
||||
- (void) launchFailed:(NSString*)message;
|
||||
- (void) rumble:(unsigned short)controllerNumber lowFreqMotor:(unsigned short)lowFreqMotor highFreqMotor:(unsigned short)highFreqMotor;
|
||||
- (void) connectionStatusUpdate:(int)status;
|
||||
- (void) videoContentShown;
|
||||
|
||||
@end
|
||||
@@ -84,7 +84,7 @@
|
||||
|
||||
// Initializing the renderer must be done on the main thread
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc] initWithView:self->_renderView];
|
||||
VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc] initWithView:self->_renderView callbacks:self->_callbacks];
|
||||
self->_connection = [[Connection alloc] initWithConfig:self->_config renderer:renderer connectionCallbacks:self->_callbacks];
|
||||
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||
[opQueue addOperation:self->_connection];
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
@import AVFoundation;
|
||||
|
||||
#import "ConnectionCallbacks.h"
|
||||
|
||||
@interface VideoDecoderRenderer : NSObject
|
||||
|
||||
- (id)initWithView:(UIView*)view;
|
||||
- (id)initWithView:(UIView*)view callbacks:(id<ConnectionCallbacks>)callbacks;
|
||||
|
||||
- (void)setupWithVideoFormat:(int)videoFormat refreshRate:(int)refreshRate;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
@implementation VideoDecoderRenderer {
|
||||
StreamView* _view;
|
||||
id<ConnectionCallbacks> _callbacks;
|
||||
|
||||
AVSampleBufferDisplayLayer* displayLayer;
|
||||
Boolean waitingForSps, waitingForPps, waitingForVps;
|
||||
@@ -61,11 +62,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithView:(StreamView*)view
|
||||
- (id)initWithView:(StreamView*)view callbacks:(id<ConnectionCallbacks>)callbacks
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
_view = view;
|
||||
_callbacks = callbacks;
|
||||
|
||||
[self reinitializeDisplayLayer];
|
||||
|
||||
@@ -371,6 +373,9 @@
|
||||
if ([self isNalReferencePicture:nalType]) {
|
||||
// Ensure the layer is visible now
|
||||
self->displayLayer.hidden = NO;
|
||||
|
||||
// Tell our parent VC to hide the progress indicator
|
||||
[self->_callbacks videoContentShown];
|
||||
}
|
||||
|
||||
// Dereference the buffers
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
#else
|
||||
@interface StreamFrameViewController : UIViewController <ConnectionCallbacks, EdgeDetectionDelegate, InputPresenceDelegate, UserInteractionDelegate>
|
||||
#endif
|
||||
@property (strong, nonatomic) IBOutlet UILabel *stageLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *tipLabel;
|
||||
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
|
||||
@property (nonatomic) StreamConfiguration* streamConfig;
|
||||
|
||||
@end
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
UITapGestureRecognizer *_menuGestureRecognizer;
|
||||
UITapGestureRecognizer *_menuDoubleTapGestureRecognizer;
|
||||
UITextView *_overlayView;
|
||||
UILabel *_stageLabel;
|
||||
UILabel *_tipLabel;
|
||||
UIActivityIndicatorView *_spinner;
|
||||
StreamView *_streamView;
|
||||
BOOL _userIsInteracting;
|
||||
}
|
||||
@@ -54,17 +57,31 @@
|
||||
|
||||
[self.navigationController setNavigationBarHidden:YES animated:YES];
|
||||
|
||||
[self.stageLabel setText:[NSString stringWithFormat:@"Starting %@...", self.streamConfig.appName]];
|
||||
[self.stageLabel sizeToFit];
|
||||
self.stageLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.stageLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
|
||||
self.spinner.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2 - self.stageLabel.frame.size.height - self.spinner.frame.size.height);
|
||||
[UIApplication sharedApplication].idleTimerDisabled = YES;
|
||||
|
||||
_stageLabel = [[UILabel alloc] init];
|
||||
[_stageLabel setUserInteractionEnabled:NO];
|
||||
[_stageLabel setText:[NSString stringWithFormat:@"Starting %@...", self.streamConfig.appName]];
|
||||
[_stageLabel sizeToFit];
|
||||
_stageLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_stageLabel.textColor = [UIColor whiteColor];
|
||||
_stageLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
|
||||
|
||||
_spinner = [[UIActivityIndicatorView alloc] init];
|
||||
[_spinner setUserInteractionEnabled:NO];
|
||||
#if TARGET_OS_TV
|
||||
[_spinner setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhiteLarge];
|
||||
#else
|
||||
[_spinner setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleWhite];
|
||||
#endif
|
||||
[_spinner sizeToFit];
|
||||
[_spinner startAnimating];
|
||||
_spinner.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2 - _stageLabel.frame.size.height - _spinner.frame.size.height);
|
||||
|
||||
_controllerSupport = [[ControllerSupport alloc] initWithConfig:self.streamConfig presenceDelegate:self];
|
||||
_inactivityTimer = nil;
|
||||
|
||||
_streamView = (StreamView*)self.view;
|
||||
_streamView = [[StreamView alloc] initWithFrame:self.view.frame];
|
||||
[_streamView setupStreamView:_controllerSupport swipeDelegate:self interactionDelegate:self config:self.streamConfig];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
@@ -82,18 +99,23 @@
|
||||
[self.view addGestureRecognizer:_menuDoubleTapGestureRecognizer];
|
||||
#endif
|
||||
|
||||
|
||||
_tipLabel = [[UILabel alloc] init];
|
||||
[_tipLabel setUserInteractionEnabled:NO];
|
||||
|
||||
#if TARGET_OS_TV
|
||||
[self.tipLabel setText:@"Tip: Double tap the Menu button to disconnect from your PC"];
|
||||
[_tipLabel setText:@"Tip: Double tap the Menu button to disconnect from your PC"];
|
||||
#else
|
||||
[self.tipLabel setText:@"Tip: Swipe from the left edge to disconnect from your PC"];
|
||||
[_tipLabel setText:@"Tip: Swipe from the left edge to disconnect from your PC"];
|
||||
#endif
|
||||
|
||||
[self.tipLabel sizeToFit];
|
||||
self.tipLabel.textAlignment = NSTextAlignmentCenter;
|
||||
self.tipLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height * 0.9);
|
||||
[_tipLabel sizeToFit];
|
||||
_tipLabel.textColor = [UIColor whiteColor];
|
||||
_tipLabel.textAlignment = NSTextAlignmentCenter;
|
||||
_tipLabel.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height * 0.9);
|
||||
|
||||
_streamMan = [[StreamManager alloc] initWithConfig:self.streamConfig
|
||||
renderView:self.view
|
||||
renderView:_streamView
|
||||
connectionCallbacks:self];
|
||||
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||
[opQueue addOperation:_streamMan];
|
||||
@@ -112,6 +134,11 @@
|
||||
selector: @selector(applicationDidEnterBackground:)
|
||||
name: UIApplicationDidEnterBackgroundNotification
|
||||
object: nil];
|
||||
|
||||
[self.view addSubview:_streamView];
|
||||
[self.view addSubview:_stageLabel];
|
||||
[self.view addSubview:_spinner];
|
||||
[self.view addSubview:_tipLabel];
|
||||
}
|
||||
|
||||
- (void)willMoveToParentViewController:(UIViewController *)parent {
|
||||
@@ -244,8 +271,8 @@
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// Leave the spinner spinning until it's obscured by
|
||||
// the first frame of video.
|
||||
self.stageLabel.hidden = YES;
|
||||
self.tipLabel.hidden = YES;
|
||||
self->_stageLabel.hidden = YES;
|
||||
self->_tipLabel.hidden = YES;
|
||||
|
||||
[self->_streamView showOnScreenControls];
|
||||
|
||||
@@ -318,9 +345,9 @@
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
|
||||
NSString* titleCase = [[[lowerCase substringToIndex:1] uppercaseString] stringByAppendingString:[lowerCase substringFromIndex:1]];
|
||||
[self.stageLabel setText:titleCase];
|
||||
[self.stageLabel sizeToFit];
|
||||
self.stageLabel.center = CGPointMake(self.view.frame.size.width / 2, self.stageLabel.center.y);
|
||||
[self->_stageLabel setText:titleCase];
|
||||
[self->_stageLabel sizeToFit];
|
||||
self->_stageLabel.center = CGPointMake(self.view.frame.size.width / 2, self->_stageLabel.center.y);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -404,6 +431,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (void) videoContentShown {
|
||||
[_spinner stopAnimating];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
|
||||
Reference in New Issue
Block a user