blob: dec41eadebdd30013077e7460fa8353f784cec55 [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>
tkchin@webrtc.org87776a82014-12-09 19:32:35 +000014#import "ARDAppClient.h"
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000015#import "RTCNSGLVideoView.h"
tkchin@webrtc.org81257442014-11-04 23:06:15 +000016#import "RTCVideoTrack.h"
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +000017
18static NSUInteger const kContentWidth = 1280;
19static NSUInteger const kContentHeight = 720;
20static NSUInteger const kRoomFieldWidth = 80;
21static NSUInteger const kLogViewHeight = 280;
22
23@class APPRTCMainView;
24@protocol APPRTCMainViewDelegate
25
26- (void)appRTCMainView:(APPRTCMainView*)mainView
27 didEnterRoomId:(NSString*)roomId;
28
29@end
30
31@interface APPRTCMainView : NSView
32
33@property(nonatomic, weak) id<APPRTCMainViewDelegate> delegate;
34@property(nonatomic, readonly) RTCNSGLVideoView* localVideoView;
35@property(nonatomic, readonly) RTCNSGLVideoView* remoteVideoView;
36
37- (void)displayLogMessage:(NSString*)message;
38
39@end
40
41@interface APPRTCMainView () <NSTextFieldDelegate, RTCNSGLVideoViewDelegate>
42@end
43@implementation APPRTCMainView {
44 NSScrollView* _scrollView;
45 NSTextField* _roomLabel;
46 NSTextField* _roomField;
47 NSTextView* _logView;
48 RTCNSGLVideoView* _localVideoView;
49 RTCNSGLVideoView* _remoteVideoView;
50 CGSize _localVideoSize;
51 CGSize _remoteVideoSize;
52}
53
54+ (BOOL)requiresConstraintBasedLayout {
55 return YES;
56}
57
58- (instancetype)initWithFrame:(NSRect)frame {
59 if (self = [super initWithFrame:frame]) {
60 [self setupViews];
61 }
62 return self;
63}
64
65- (void)updateConstraints {
66 NSParameterAssert(
67 _roomField != nil && _scrollView != nil && _remoteVideoView != nil);
68 [self removeConstraints:[self constraints]];
69 NSDictionary* viewsDictionary =
70 NSDictionaryOfVariableBindings(_roomLabel,
71 _roomField,
72 _scrollView,
73 _remoteVideoView);
74
75 NSSize remoteViewSize = [self remoteVideoViewSize];
76 NSDictionary* metrics = @{
77 @"kLogViewHeight" : @(kLogViewHeight),
78 @"kRoomFieldWidth" : @(kRoomFieldWidth),
79 @"remoteViewWidth" : @(remoteViewSize.width),
80 @"remoteViewHeight" : @(remoteViewSize.height),
81 };
82 // Declare this separately to avoid compiler warning about splitting string
83 // within an NSArray expression.
84 NSString* verticalConstraint =
85 @"V:|-[_roomLabel]-[_roomField]-[_scrollView(kLogViewHeight)]"
86 "-[_remoteVideoView(remoteViewHeight)]-|";
87 NSArray* constraintFormats = @[
88 verticalConstraint,
89 @"|-[_roomLabel]",
90 @"|-[_roomField(kRoomFieldWidth)]",
91 @"|-[_scrollView(remoteViewWidth)]-|",
92 @"|-[_remoteVideoView(remoteViewWidth)]-|",
93 ];
94 for (NSString* constraintFormat in constraintFormats) {
95 NSArray* constraints =
96 [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat
97 options:0
98 metrics:metrics
99 views:viewsDictionary];
100 for (NSLayoutConstraint* constraint in constraints) {
101 [self addConstraint:constraint];
102 }
103 }
104 [super updateConstraints];
105}
106
107- (void)displayLogMessage:(NSString*)message {
108 _logView.string =
109 [NSString stringWithFormat:@"%@%@\n", _logView.string, message];
110 NSRange range = NSMakeRange([_logView.string length], 0);
111 [_logView scrollRangeToVisible:range];
112}
113
114#pragma mark - NSControl delegate
115
116- (void)controlTextDidEndEditing:(NSNotification*)notification {
117 NSDictionary* userInfo = [notification userInfo];
118 NSInteger textMovement = [userInfo[@"NSTextMovement"] intValue];
119 if (textMovement == NSReturnTextMovement) {
120 [self.delegate appRTCMainView:self didEnterRoomId:_roomField.stringValue];
121 }
122}
123
124#pragma mark - RTCNSGLVideoViewDelegate
125
126- (void)videoView:(RTCNSGLVideoView*)videoView
127 didChangeVideoSize:(NSSize)size {
128 if (videoView == _remoteVideoView) {
129 _remoteVideoSize = size;
130 } else if (videoView == _localVideoView) {
131 _localVideoSize = size;
132 } else {
133 return;
134 }
135 [self setNeedsUpdateConstraints:YES];
136}
137
138#pragma mark - Private
139
140- (void)setupViews {
141 NSParameterAssert([[self subviews] count] == 0);
142
143 _roomLabel = [[NSTextField alloc] initWithFrame:NSZeroRect];
144 [_roomLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
145 [_roomLabel setBezeled:NO];
146 [_roomLabel setDrawsBackground:NO];
147 [_roomLabel setEditable:NO];
148 [_roomLabel setStringValue:@"Enter AppRTC room id:"];
149 [self addSubview:_roomLabel];
150
151 _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect];
152 [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO];
153 [self addSubview:_roomField];
154 [_roomField setEditable:YES];
155 [_roomField setDelegate:self];
156
157 _logView = [[NSTextView alloc] initWithFrame:NSZeroRect];
158 [_logView setMinSize:NSMakeSize(0, kLogViewHeight)];
159 [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
160 [_logView setVerticallyResizable:YES];
161 [_logView setAutoresizingMask:NSViewWidthSizable];
162 NSTextContainer* textContainer = [_logView textContainer];
163 NSSize containerSize = NSMakeSize(kContentWidth, FLT_MAX);
164 [textContainer setContainerSize:containerSize];
165 [textContainer setWidthTracksTextView:YES];
166 [_logView setEditable:NO];
167
168 _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
169 [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
170 [_scrollView setHasVerticalScroller:YES];
171 [_scrollView setDocumentView:_logView];
172 [self addSubview:_scrollView];
173
174 NSOpenGLPixelFormatAttribute attributes[] = {
175 NSOpenGLPFADoubleBuffer,
176 NSOpenGLPFADepthSize, 24,
177 NSOpenGLPFAOpenGLProfile,
178 NSOpenGLProfileVersion3_2Core,
179 0
180 };
181 NSOpenGLPixelFormat* pixelFormat =
182 [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
183 _remoteVideoView = [[RTCNSGLVideoView alloc] initWithFrame:NSZeroRect
184 pixelFormat:pixelFormat];
185 [_remoteVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
186 _remoteVideoView.delegate = self;
187 [self addSubview:_remoteVideoView];
188
189 // TODO(tkchin): create local video view.
190 // https://code.google.com/p/webrtc/issues/detail?id=3417.
191}
192
193- (NSSize)remoteVideoViewSize {
194 if (_remoteVideoSize.width > 0 && _remoteVideoSize.height > 0) {
195 return _remoteVideoSize;
196 } else {
197 return NSMakeSize(kContentWidth, kContentHeight);
198 }
199}
200
201- (NSSize)localVideoViewSize {
202 return NSZeroSize;
203}
204
205@end
206
207@interface APPRTCViewController ()
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000208 <ARDAppClientDelegate, APPRTCMainViewDelegate>
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000209@property(nonatomic, readonly) APPRTCMainView* mainView;
210@end
211
212@implementation APPRTCViewController {
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000213 ARDAppClient* _client;
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000214 RTCVideoTrack* _localVideoTrack;
215 RTCVideoTrack* _remoteVideoTrack;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000216}
217
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000218- (void)dealloc {
219 [self disconnect];
220}
221
222- (void)loadView {
223 APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect];
224 [view setTranslatesAutoresizingMaskIntoConstraints:NO];
225 view.delegate = self;
226 self.view = view;
227}
228
229- (void)windowWillClose:(NSNotification*)notification {
230 [self disconnect];
231}
232
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000233#pragma mark - ARDAppClientDelegate
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000234
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000235- (void)appClient:(ARDAppClient *)client
236 didChangeState:(ARDAppClientState)state {
237 switch (state) {
238 case kARDAppClientStateConnected:
239 NSLog(@"Client connected.");
240 break;
241 case kARDAppClientStateConnecting:
242 NSLog(@"Client connecting.");
243 break;
244 case kARDAppClientStateDisconnected:
245 NSLog(@"Client disconnected.");
246 [self resetUI];
247 _client = nil;
248 break;
249 }
250}
251
252- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.org3a63a3c2015-01-06 07:21:34 +0000253 didChangeConnectionState:(RTCICEConnectionState)state {
254}
255
256- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000257 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000258 _localVideoTrack = localVideoTrack;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000259}
260
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000261- (void)appClient:(ARDAppClient *)client
262 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000263 _remoteVideoTrack = remoteVideoTrack;
264 [_remoteVideoTrack addRenderer:self.mainView.remoteVideoView];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000265}
266
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000267- (void)appClient:(ARDAppClient *)client
268 didError:(NSError *)error {
269 [self showAlertWithMessage:[NSString stringWithFormat:@"%@", error]];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000270 [self disconnect];
271}
272
Zeke Chind3325802015-08-14 11:00:02 -0700273- (void)appClient:(ARDAppClient *)client
274 didGetStats:(NSArray *)stats {
275}
276
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000277#pragma mark - APPRTCMainViewDelegate
278
279- (void)appRTCMainView:(APPRTCMainView*)mainView
280 didEnterRoomId:(NSString*)roomId {
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000281 [_client disconnect];
282 ARDAppClient *client = [[ARDAppClient alloc] initWithDelegate:self];
283 [client connectToRoomWithId:roomId options:nil];
284 _client = client;
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000285}
286
287#pragma mark - Private
288
289- (APPRTCMainView*)mainView {
290 return (APPRTCMainView*)self.view;
291}
292
293- (void)showAlertWithMessage:(NSString*)message {
294 NSAlert* alert = [[NSAlert alloc] init];
295 [alert setMessageText:message];
296 [alert runModal];
297}
298
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000299- (void)resetUI {
tkchin@webrtc.org81257442014-11-04 23:06:15 +0000300 [_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView];
301 _remoteVideoTrack = nil;
302 [self.mainView.remoteVideoView renderFrame:nil];
tkchin@webrtc.org87776a82014-12-09 19:32:35 +0000303}
304
305- (void)disconnect {
306 [self resetUI];
307 [_client disconnect];
tkchin@webrtc.orgacca6752014-05-30 22:26:06 +0000308}
309
310@end