From 647915fb9574231e7cb3461009c8a51e0f570b5a Mon Sep 17 00:00:00 2001 From: denicija Date: Thu, 20 Oct 2016 01:46:41 -0700 Subject: [PATCH] Add loopback option and improve UX of AppRTCMobile for Mac. CL introduces changes in the layout of the mac demo app. Bellow are the listed changes * The label above the room field is removed and that text is shown in the text field's placeholder. * Size of the window is decreased to accomodate smaller resolutions * The local view is shown on top of remote view in 3/rd of it's size * The log view is bellow the remote view and shows client status messages as well as some simple usage instructions. * Loopback functionality is added * Start call button added for improved usability Note: This file was not following our internal ObjC style guidelines i.e NSString *a - right NSString* a - wrong However I've decided to submit the changes and to follow the current style. I'll submit a bug to update the style in separate CL BUG=webrtc:6496 Review-Url: https://codereview.webrtc.org/2396333002 Cr-Commit-Position: refs/heads/master@{#14692} --- .../AppRTCMobile/mac/APPRTCViewController.m | 223 ++++++++++++------ 1 file changed, 151 insertions(+), 72 deletions(-) diff --git a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m index 710b8a5ea4..353e105c1d 100644 --- a/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m @@ -17,17 +17,17 @@ #import "ARDAppClient.h" -static NSUInteger const kContentWidth = 1280; -static NSUInteger const kContentHeight = 720; -static NSUInteger const kRoomFieldWidth = 80; -static NSUInteger const kLogViewHeight = 280; -static NSUInteger const kPreviewWidth = 490; +static NSUInteger const kContentWidth = 900; +static NSUInteger const kRoomFieldWidth = 200; +static NSUInteger const kActionItemHeight = 30; +static NSUInteger const kBottomViewHeight = 200; @class APPRTCMainView; @protocol APPRTCMainViewDelegate - (void)appRTCMainView:(APPRTCMainView*)mainView - didEnterRoomId:(NSString*)roomId; + didEnterRoomId:(NSString*)roomId + loopback:(BOOL)isLoopback; @end @@ -45,7 +45,9 @@ static NSUInteger const kPreviewWidth = 490; @end @implementation APPRTCMainView { NSScrollView* _scrollView; - NSTextField* _roomLabel; + NSView* _actionItemsView; + NSButton* _connectButton; + NSButton* _loopbackButton; NSTextField* _roomField; NSTextView* _logView; CGSize _localVideoSize; @@ -56,10 +58,16 @@ static NSUInteger const kPreviewWidth = 490; @synthesize localVideoView = _localVideoView; @synthesize remoteVideoView = _remoteVideoView; -+ (BOOL)requiresConstraintBasedLayout { - return YES; + +- (void)displayLogMessage:(NSString *)message { + _logView.string = + [NSString stringWithFormat:@"%@%@\n", _logView.string, message]; + NSRange range = NSMakeRange(_logView.string.length, 0); + [_logView scrollRangeToVisible:range]; } +#pragma mark - Private + - (instancetype)initWithFrame:(NSRect)frame { if (self = [super initWithFrame:frame]) { [self setupViews]; @@ -67,71 +75,103 @@ static NSUInteger const kPreviewWidth = 490; return self; } ++ (BOOL)requiresConstraintBasedLayout { + return YES; +} + - (void)updateConstraints { NSParameterAssert( - _roomField != nil && _scrollView != nil && _remoteVideoView != nil); + _roomField != nil && + _scrollView != nil && + _remoteVideoView != nil && + _localVideoView != nil && + _actionItemsView!= nil && + _connectButton != nil && + _loopbackButton != nil); + [self removeConstraints:[self constraints]]; NSDictionary* viewsDictionary = - NSDictionaryOfVariableBindings(_roomLabel, - _roomField, + NSDictionaryOfVariableBindings(_roomField, _scrollView, _remoteVideoView, - _localVideoView); + _localVideoView, + _actionItemsView, + _connectButton, + _loopbackButton); NSSize remoteViewSize = [self remoteVideoViewSize]; NSDictionary* metrics = @{ - @"kLogViewHeight" : @(kLogViewHeight), - @"kPreviewWidth" : @(kPreviewWidth), - @"kRoomFieldWidth" : @(kRoomFieldWidth), @"remoteViewWidth" : @(remoteViewSize.width), @"remoteViewHeight" : @(remoteViewSize.height), - @"localViewHeight" : @(remoteViewSize.height), - @"scrollViewWidth" : @(kContentWidth - kPreviewWidth), + @"kBottomViewHeight" : @(kBottomViewHeight), + @"localViewHeight" : @(remoteViewSize.height / 3), + @"localViewWidth" : @(remoteViewSize.width / 3), + @"kRoomFieldWidth" : @(kRoomFieldWidth), + @"kActionItemHeight" : @(kActionItemHeight) }; // Declare this separately to avoid compiler warning about splitting string // within an NSArray expression. - NSString* verticalConstraint = - @"V:|-[_roomLabel]-[_roomField]-[_scrollView(kLogViewHeight)]" - "-[_remoteVideoView(remoteViewHeight)]-|"; + NSString* verticalConstraintLeft = + @"V:|-[_remoteVideoView(remoteViewHeight)]-[_scrollView(kBottomViewHeight)]-|"; + NSString* verticalConstraintRight = + @"V:|-[_remoteVideoView(remoteViewHeight)]-[_actionItemsView(kBottomViewHeight)]-|"; NSArray* constraintFormats = @[ - verticalConstraint, - @"V:[_localVideoView]-[_remoteVideoView]", - @"V:[_localVideoView(kLogViewHeight)]", - @"|-[_roomLabel]", - @"|-[_roomField(kRoomFieldWidth)]", - @"|-[_scrollView(scrollViewWidth)]", - @"[_scrollView]-[_localVideoView]", - @"|-[_remoteVideoView(remoteViewWidth)]-|", - @"[_localVideoView(kPreviewWidth)]-|", + verticalConstraintLeft, + verticalConstraintRight, + @"H:|-[_remoteVideoView(remoteViewWidth)]-|", + @"V:|-[_localVideoView(localViewHeight)]", + @"H:|-[_localVideoView(localViewWidth)]", + @"H:|-[_scrollView(==_actionItemsView)]-[_actionItemsView]-|" ]; - for (NSString* constraintFormat in constraintFormats) { - NSArray* constraints = - [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat - options:0 - metrics:metrics - views:viewsDictionary]; - for (NSLayoutConstraint* constraint in constraints) { - [self addConstraint:constraint]; - } - } + + NSArray* actionItemsConstraints = @[ + @"H:|-[_roomField(kRoomFieldWidth)]-[_loopbackButton(kRoomFieldWidth)]", + @"H:|-[_connectButton(kRoomFieldWidth)]", + @"V:|-[_roomField(kActionItemHeight)]-[_connectButton(kActionItemHeight)]", + @"V:|-[_loopbackButton(kActionItemHeight)]", + ]; + + [APPRTCMainView addConstraints:constraintFormats + toView:self + viewsDictionary:viewsDictionary + metrics:metrics]; + [APPRTCMainView addConstraints:actionItemsConstraints + toView:_actionItemsView + viewsDictionary:viewsDictionary + metrics:metrics]; [super updateConstraints]; } -- (void)displayLogMessage:(NSString*)message { - _logView.string = - [NSString stringWithFormat:@"%@%@\n", _logView.string, message]; - NSRange range = NSMakeRange([_logView.string length], 0); - [_logView scrollRangeToVisible:range]; +#pragma mark - Constraints helper + ++ (void)addConstraints:(NSArray*)constraints toView:(NSView*)view + viewsDictionary:(NSDictionary*)viewsDictionary + metrics:(NSDictionary*)metrics { + for (NSString* constraintFormat in constraints) { + NSArray* constraints = + [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat + options:0 + metrics:metrics + views:viewsDictionary]; + for (NSLayoutConstraint* constraint in constraints) { + [view addConstraint:constraint]; + } + } } -#pragma mark - NSControl delegate +#pragma mark - Control actions -- (void)controlTextDidEndEditing:(NSNotification*)notification { - NSDictionary* userInfo = [notification userInfo]; - NSInteger textMovement = [userInfo[@"NSTextMovement"] intValue]; - if (textMovement == NSReturnTextMovement) { - [self.delegate appRTCMainView:self didEnterRoomId:_roomField.stringValue]; +- (void)startCall:(id)sender { + NSString* roomString = _roomField.stringValue; + // Generate room id for loopback options. + if (_loopbackButton.intValue && [roomString isEqualToString:@""]) { + roomString = [NSUUID UUID].UUIDString; + roomString = [roomString stringByReplacingOccurrencesOfString:@"-" withString:@""]; } + + [self.delegate appRTCMainView:self + didEnterRoomId:roomString + loopback:_loopbackButton.intValue]; } #pragma mark - RTCNSGLVideoViewDelegate @@ -145,6 +185,7 @@ static NSUInteger const kPreviewWidth = 490; } else { return; } + [self setNeedsUpdateConstraints:YES]; } @@ -153,22 +194,8 @@ static NSUInteger const kPreviewWidth = 490; - (void)setupViews { NSParameterAssert([[self subviews] count] == 0); - _roomLabel = [[NSTextField alloc] initWithFrame:NSZeroRect]; - [_roomLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; - [_roomLabel setBezeled:NO]; - [_roomLabel setDrawsBackground:NO]; - [_roomLabel setEditable:NO]; - [_roomLabel setStringValue:@"Enter AppRTC room id:"]; - [self addSubview:_roomLabel]; - - _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect]; - [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO]; - [self addSubview:_roomField]; - [_roomField setEditable:YES]; - [_roomField setDelegate:self]; - _logView = [[NSTextView alloc] initWithFrame:NSZeroRect]; - [_logView setMinSize:NSMakeSize(0, kLogViewHeight)]; + [_logView setMinSize:NSMakeSize(0, kBottomViewHeight)]; [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; [_logView setVerticallyResizable:YES]; [_logView setAutoresizingMask:NSViewWidthSizable]; @@ -178,6 +205,8 @@ static NSUInteger const kPreviewWidth = 490; [textContainer setWidthTracksTextView:YES]; [_logView setEditable:NO]; + [self setupActionItemsView]; + _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect]; [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO]; [_scrollView setHasVerticalScroller:YES]; @@ -206,8 +235,37 @@ static NSUInteger const kPreviewWidth = 490; [self addSubview:_localVideoView]; } +- (void)setupActionItemsView { + _actionItemsView = [[NSView alloc] initWithFrame:NSZeroRect]; + [_actionItemsView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self addSubview:_actionItemsView]; + + _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect]; + [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO]; + _roomField.placeholderString = @"Enter AppRTC room id"; + [_actionItemsView addSubview:_roomField]; + [_roomField setEditable:YES]; + + _connectButton = [[NSButton alloc] initWithFrame:NSZeroRect]; + [_connectButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + _connectButton.title = @"Start call"; + _connectButton.bezelStyle = NSRoundedBezelStyle; + _connectButton.target = self; + _connectButton.action = @selector(startCall:); + [_actionItemsView addSubview:_connectButton]; + + _loopbackButton = [[NSButton alloc] initWithFrame:NSZeroRect]; + [_loopbackButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + _loopbackButton.title = @"Loopback"; + [_loopbackButton setButtonType:NSSwitchButton]; + [_actionItemsView addSubview:_loopbackButton]; +} + - (NSSize)remoteVideoViewSize { - NSInteger width = MAX(_remoteVideoSize.width, kContentWidth); + if (!_remoteVideoView.bounds.size.width) { + return NSMakeSize(kContentWidth, 0); + } + NSInteger width = MAX(_remoteVideoView.bounds.size.width, kContentWidth); NSInteger height = (width/16) * 9; return NSMakeSize(width, height); } @@ -229,6 +287,11 @@ static NSUInteger const kPreviewWidth = 490; [self disconnect]; } +- (void)viewDidAppear { + [super viewDidAppear]; + [self displayUsageInstructions]; +} + - (void)loadView { APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect]; [view setTranslatesAutoresizingMaskIntoConstraints:NO]; @@ -240,19 +303,28 @@ static NSUInteger const kPreviewWidth = 490; [self disconnect]; } +#pragma mark - Usage + +- (void)displayUsageInstructions { + [self.mainView displayLogMessage: + @"To start call:\n" + @"• Enter AppRTC room id (not neccessary for loopback)\n" + @"• Start call"]; +} + #pragma mark - ARDAppClientDelegate - (void)appClient:(ARDAppClient *)client didChangeState:(ARDAppClientState)state { switch (state) { case kARDAppClientStateConnected: - NSLog(@"Client connected."); + [self.mainView displayLogMessage:@"Client connected."]; break; case kARDAppClientStateConnecting: - NSLog(@"Client connecting."); + [self.mainView displayLogMessage:@"Client connecting."]; break; case kARDAppClientStateDisconnected: - NSLog(@"Client disconnected."); + [self.mainView displayLogMessage:@"Client disconnected."]; [self resetUI]; _client = nil; break; @@ -288,11 +360,18 @@ static NSUInteger const kPreviewWidth = 490; #pragma mark - APPRTCMainViewDelegate - (void)appRTCMainView:(APPRTCMainView*)mainView - didEnterRoomId:(NSString*)roomId { + didEnterRoomId:(NSString*)roomId + loopback:(BOOL)isLoopback { + + if ([roomId isEqualToString:@""]) { + [self.mainView displayLogMessage:@"Missing room id"]; + return; + } + [_client disconnect]; ARDAppClient *client = [[ARDAppClient alloc] initWithDelegate:self]; [client connectToRoomWithId:roomId - isLoopback:NO + isLoopback:isLoopback isAudioOnly:NO shouldMakeAecDump:NO shouldUseLevelControl:NO];