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