blob: 914403619c5abf532825fd186df35ff43750d81a [file] [log] [blame]
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2014 The WebRTC Project Authors. All rights reserved.
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +00003 *
Donald E Curtisa8736442015-08-05 15:48:13 -07004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +00009 */
10
11#import "APPRTCViewController.h"
12
13#import <AVFoundation/AVFoundation.h>
tkchin9eeb6242016-04-27 01:54:20 -070014
15#import "WebRTC/RTCNSGLVideoView.h"
16#import "WebRTC/RTCVideoTrack.h"
hjon79858f82016-03-13 22:08:26 -070017
tkchin@webrtc.org87776a82014-12-09 19:32:35 +000018#import "ARDAppClient.h"
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000019
20static NSUInteger const kContentWidth = 1280;
21static NSUInteger const kContentHeight = 720;
22static NSUInteger const kRoomFieldWidth = 80;
23static NSUInteger const kLogViewHeight = 280;
24
25@class APPRTCMainView;
26@protocol APPRTCMainViewDelegate
27
28- (void)appRTCMainView:(APPRTCMainView*)mainView
29 didEnterRoomId:(NSString*)roomId;
30
31@end
32
33@interface APPRTCMainView : NSView
34
35@property(nonatomic, weak) id<APPRTCMainViewDelegate> delegate;
36@property(nonatomic, readonly) RTCNSGLVideoView* localVideoView;
37@property(nonatomic, readonly) RTCNSGLVideoView* remoteVideoView;
38
39- (void)displayLogMessage:(NSString*)message;
40
41@end
42
43@interface APPRTCMainView () <NSTextFieldDelegate, RTCNSGLVideoViewDelegate>
44@end
45@implementation APPRTCMainView {
46 NSScrollView* _scrollView;
47 NSTextField* _roomLabel;
48 NSTextField* _roomField;
49 NSTextView* _logView;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000050 CGSize _localVideoSize;
51 CGSize _remoteVideoSize;
52}
53
tkchin2ddfdba2016-08-07 21:37:45 -070054@synthesize delegate = _delegate;
55@synthesize localVideoView = _localVideoView;
56@synthesize remoteVideoView = _remoteVideoView;
57
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000058+ (BOOL)requiresConstraintBasedLayout {
59 return YES;
60}
61
62- (instancetype)initWithFrame:(NSRect)frame {
63 if (self = [super initWithFrame:frame]) {
64 [self setupViews];
65 }
66 return self;
67}
68
69- (void)updateConstraints {
70 NSParameterAssert(
71 _roomField != nil && _scrollView != nil && _remoteVideoView != nil);
72 [self removeConstraints:[self constraints]];
73 NSDictionary* viewsDictionary =
74 NSDictionaryOfVariableBindings(_roomLabel,
75 _roomField,
76 _scrollView,
77 _remoteVideoView);
78
79 NSSize remoteViewSize = [self remoteVideoViewSize];
80 NSDictionary* metrics = @{
81 @"kLogViewHeight" : @(kLogViewHeight),
82 @"kRoomFieldWidth" : @(kRoomFieldWidth),
83 @"remoteViewWidth" : @(remoteViewSize.width),
84 @"remoteViewHeight" : @(remoteViewSize.height),
85 };
86 // Declare this separately to avoid compiler warning about splitting string
87 // within an NSArray expression.
88 NSString* verticalConstraint =
89 @"V:|-[_roomLabel]-[_roomField]-[_scrollView(kLogViewHeight)]"
90 "-[_remoteVideoView(remoteViewHeight)]-|";
91 NSArray* constraintFormats = @[
92 verticalConstraint,
93 @"|-[_roomLabel]",
94 @"|-[_roomField(kRoomFieldWidth)]",
95 @"|-[_scrollView(remoteViewWidth)]-|",
96 @"|-[_remoteVideoView(remoteViewWidth)]-|",
97 ];
98 for (NSString* constraintFormat in constraintFormats) {
99 NSArray* constraints =
100 [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat
101 options:0
102 metrics:metrics
103 views:viewsDictionary];
104 for (NSLayoutConstraint* constraint in constraints) {
105 [self addConstraint:constraint];
106 }
107 }
108 [super updateConstraints];
109}
110
111- (void)displayLogMessage:(NSString*)message {
112 _logView.string =
113 [NSString stringWithFormat:@"%@%@\n", _logView.string, message];
114 NSRange range = NSMakeRange([_logView.string length], 0);
115 [_logView scrollRangeToVisible:range];
116}
117
118#pragma mark - NSControl delegate
119
120- (void)controlTextDidEndEditing:(NSNotification*)notification {
121 NSDictionary* userInfo = [notification userInfo];
122 NSInteger textMovement = [userInfo[@"NSTextMovement"] intValue];
123 if (textMovement == NSReturnTextMovement) {
124 [self.delegate appRTCMainView:self didEnterRoomId:_roomField.stringValue];
125 }
126}
127
128#pragma mark - RTCNSGLVideoViewDelegate
129
130- (void)videoView:(RTCNSGLVideoView*)videoView
131 didChangeVideoSize:(NSSize)size {
132 if (videoView == _remoteVideoView) {
133 _remoteVideoSize = size;
134 } else if (videoView == _localVideoView) {
135 _localVideoSize = size;
136 } else {
137 return;
138 }
139 [self setNeedsUpdateConstraints:YES];
140}
141
142#pragma mark - Private
143
144- (void)setupViews {
145 NSParameterAssert([[self subviews] count] == 0);
146
147 _roomLabel = [[NSTextField alloc] initWithFrame:NSZeroRect];
148 [_roomLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
149 [_roomLabel setBezeled:NO];
150 [_roomLabel setDrawsBackground:NO];
151 [_roomLabel setEditable:NO];
152 [_roomLabel setStringValue:@"Enter AppRTC room id:"];
153 [self addSubview:_roomLabel];
154
155 _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect];
156 [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO];
157 [self addSubview:_roomField];
158 [_roomField setEditable:YES];
159 [_roomField setDelegate:self];
160
161 _logView = [[NSTextView alloc] initWithFrame:NSZeroRect];
162 [_logView setMinSize:NSMakeSize(0, kLogViewHeight)];
163 [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
164 [_logView setVerticallyResizable:YES];
165 [_logView setAutoresizingMask:NSViewWidthSizable];
166 NSTextContainer* textContainer = [_logView textContainer];
167 NSSize containerSize = NSMakeSize(kContentWidth, FLT_MAX);
168 [textContainer setContainerSize:containerSize];
169 [textContainer setWidthTracksTextView:YES];
170 [_logView setEditable:NO];
171
172 _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
173 [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
174 [_scrollView setHasVerticalScroller:YES];
175 [_scrollView setDocumentView:_logView];
176 [self addSubview:_scrollView];
177
178 NSOpenGLPixelFormatAttribute attributes[] = {
179 NSOpenGLPFADoubleBuffer,
180 NSOpenGLPFADepthSize, 24,
181 NSOpenGLPFAOpenGLProfile,
182 NSOpenGLProfileVersion3_2Core,
183 0
184 };
185 NSOpenGLPixelFormat* pixelFormat =
186 [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
187 _remoteVideoView = [[RTCNSGLVideoView alloc] initWithFrame:NSZeroRect
188 pixelFormat:pixelFormat];
189 [_remoteVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
190 _remoteVideoView.delegate = self;
191 [self addSubview:_remoteVideoView];
192
193 // TODO(tkchin): create local video view.
194 // https://code.google.com/p/webrtc/issues/detail?id=3417.
195}
196
197- (NSSize)remoteVideoViewSize {
198 if (_remoteVideoSize.width > 0 && _remoteVideoSize.height > 0) {
199 return _remoteVideoSize;
200 } else {
201 return NSMakeSize(kContentWidth, kContentHeight);
202 }
203}
204
205- (NSSize)localVideoViewSize {
206 return NSZeroSize;
207}
208
209@end
210
211@interface APPRTCViewController ()
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000212 <ARDAppClientDelegate, APPRTCMainViewDelegate>
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000213@property(nonatomic, readonly) APPRTCMainView* mainView;
214@end
215
216@implementation APPRTCViewController {
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000217 ARDAppClient* _client;
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000218 RTCVideoTrack* _localVideoTrack;
219 RTCVideoTrack* _remoteVideoTrack;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000220}
221
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000222- (void)dealloc {
223 [self disconnect];
224}
225
226- (void)loadView {
227 APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect];
228 [view setTranslatesAutoresizingMaskIntoConstraints:NO];
229 view.delegate = self;
230 self.view = view;
231}
232
233- (void)windowWillClose:(NSNotification*)notification {
234 [self disconnect];
235}
236
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000237#pragma mark - ARDAppClientDelegate
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000238
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000239- (void)appClient:(ARDAppClient *)client
240 didChangeState:(ARDAppClientState)state {
241 switch (state) {
242 case kARDAppClientStateConnected:
243 NSLog(@"Client connected.");
244 break;
245 case kARDAppClientStateConnecting:
246 NSLog(@"Client connecting.");
247 break;
248 case kARDAppClientStateDisconnected:
249 NSLog(@"Client disconnected.");
250 [self resetUI];
251 _client = nil;
252 break;
253 }
254}
255
256- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -0700257 didChangeConnectionState:(RTCIceConnectionState)state {
tkchin@webrtc.org3a63a3c2015-01-06 07:21:34 +0000258}
259
260- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000261 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000262 _localVideoTrack = localVideoTrack;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000263}
264
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000265- (void)appClient:(ARDAppClient *)client
266 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000267 _remoteVideoTrack = remoteVideoTrack;
268 [_remoteVideoTrack addRenderer:self.mainView.remoteVideoView];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000269}
270
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000271- (void)appClient:(ARDAppClient *)client
272 didError:(NSError *)error {
273 [self showAlertWithMessage:[NSString stringWithFormat:@"%@", error]];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000274 [self disconnect];
275}
276
Zeke Chind3325802015-08-14 11:00:02 -0700277- (void)appClient:(ARDAppClient *)client
278 didGetStats:(NSArray *)stats {
279}
280
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000281#pragma mark - APPRTCMainViewDelegate
282
283- (void)appRTCMainView:(APPRTCMainView*)mainView
284 didEnterRoomId:(NSString*)roomId {
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000285 [_client disconnect];
286 ARDAppClient *client = [[ARDAppClient alloc] initWithDelegate:self];
haysc913e6452015-10-02 11:44:03 -0700287 [client connectToRoomWithId:roomId isLoopback:NO isAudioOnly:NO];
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000288 _client = client;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000289}
290
291#pragma mark - Private
292
293- (APPRTCMainView*)mainView {
294 return (APPRTCMainView*)self.view;
295}
296
297- (void)showAlertWithMessage:(NSString*)message {
298 NSAlert* alert = [[NSAlert alloc] init];
299 [alert setMessageText:message];
300 [alert runModal];
301}
302
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000303- (void)resetUI {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000304 [_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView];
305 _remoteVideoTrack = nil;
306 [self.mainView.remoteVideoView renderFrame:nil];
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000307}
308
309- (void)disconnect {
310 [self resetUI];
311 [_client disconnect];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000312}
313
314@end