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