OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved. | |
3 * | |
4 * 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. | |
9 */ | |
10 | |
11 #import "APPRTCViewController.h" | |
12 | |
13 #import <AVFoundation/AVFoundation.h> | |
14 | |
15 #import "WebRTC/RTCNSGLVideoView.h" | |
16 #import "WebRTC/RTCVideoTrack.h" | |
17 | |
18 #import "ARDAppClient.h" | |
19 | |
20 static NSUInteger const kContentWidth = 1280; | |
21 static NSUInteger const kContentHeight = 720; | |
22 static NSUInteger const kRoomFieldWidth = 80; | |
23 static NSUInteger const kLogViewHeight = 280; | |
24 static NSUInteger const kPreviewWidth = 490; | |
25 | |
26 @class APPRTCMainView; | |
27 @protocol APPRTCMainViewDelegate | |
28 | |
29 - (void)appRTCMainView:(APPRTCMainView*)mainView | |
30 didEnterRoomId:(NSString*)roomId; | |
31 | |
32 @end | |
33 | |
34 @interface APPRTCMainView : NSView | |
35 | |
36 @property(nonatomic, weak) id<APPRTCMainViewDelegate> delegate; | |
37 @property(nonatomic, readonly) RTCNSGLVideoView* localVideoView; | |
38 @property(nonatomic, readonly) RTCNSGLVideoView* remoteVideoView; | |
39 | |
40 - (void)displayLogMessage:(NSString*)message; | |
41 | |
42 @end | |
43 | |
44 @interface APPRTCMainView () <NSTextFieldDelegate, RTCNSGLVideoViewDelegate> | |
45 @end | |
46 @implementation APPRTCMainView { | |
47 NSScrollView* _scrollView; | |
48 NSTextField* _roomLabel; | |
49 NSTextField* _roomField; | |
50 NSTextView* _logView; | |
51 CGSize _localVideoSize; | |
52 CGSize _remoteVideoSize; | |
53 } | |
54 | |
55 @synthesize delegate = _delegate; | |
56 @synthesize localVideoView = _localVideoView; | |
57 @synthesize remoteVideoView = _remoteVideoView; | |
58 | |
59 + (BOOL)requiresConstraintBasedLayout { | |
60 return YES; | |
61 } | |
62 | |
63 - (instancetype)initWithFrame:(NSRect)frame { | |
64 if (self = [super initWithFrame:frame]) { | |
65 [self setupViews]; | |
66 } | |
67 return self; | |
68 } | |
69 | |
70 - (void)updateConstraints { | |
71 NSParameterAssert( | |
72 _roomField != nil && _scrollView != nil && _remoteVideoView != nil); | |
73 [self removeConstraints:[self constraints]]; | |
74 NSDictionary* viewsDictionary = | |
75 NSDictionaryOfVariableBindings(_roomLabel, | |
76 _roomField, | |
77 _scrollView, | |
78 _remoteVideoView, | |
79 _localVideoView); | |
80 | |
81 NSSize remoteViewSize = [self remoteVideoViewSize]; | |
82 NSDictionary* metrics = @{ | |
83 @"kLogViewHeight" : @(kLogViewHeight), | |
84 @"kPreviewWidth" : @(kPreviewWidth), | |
85 @"kRoomFieldWidth" : @(kRoomFieldWidth), | |
86 @"remoteViewWidth" : @(remoteViewSize.width), | |
87 @"remoteViewHeight" : @(remoteViewSize.height), | |
88 @"localViewHeight" : @(remoteViewSize.height), | |
89 @"scrollViewWidth" : @(kContentWidth - kPreviewWidth), | |
90 }; | |
91 // Declare this separately to avoid compiler warning about splitting string | |
92 // within an NSArray expression. | |
93 NSString* verticalConstraint = | |
94 @"V:|-[_roomLabel]-[_roomField]-[_scrollView(kLogViewHeight)]" | |
95 "-[_remoteVideoView(remoteViewHeight)]-|"; | |
96 NSArray* constraintFormats = @[ | |
97 verticalConstraint, | |
98 @"V:[_localVideoView]-[_remoteVideoView]", | |
99 @"V:[_localVideoView(kLogViewHeight)]", | |
100 @"|-[_roomLabel]", | |
101 @"|-[_roomField(kRoomFieldWidth)]", | |
102 @"|-[_scrollView(scrollViewWidth)]", | |
103 @"[_scrollView]-[_localVideoView]", | |
104 @"|-[_remoteVideoView(remoteViewWidth)]-|", | |
105 @"[_localVideoView(kPreviewWidth)]-|", | |
106 ]; | |
107 for (NSString* constraintFormat in constraintFormats) { | |
108 NSArray* constraints = | |
109 [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat | |
110 options:0 | |
111 metrics:metrics | |
112 views:viewsDictionary]; | |
113 for (NSLayoutConstraint* constraint in constraints) { | |
114 [self addConstraint:constraint]; | |
115 } | |
116 } | |
117 [super updateConstraints]; | |
118 } | |
119 | |
120 - (void)displayLogMessage:(NSString*)message { | |
121 _logView.string = | |
122 [NSString stringWithFormat:@"%@%@\n", _logView.string, message]; | |
123 NSRange range = NSMakeRange([_logView.string length], 0); | |
124 [_logView scrollRangeToVisible:range]; | |
125 } | |
126 | |
127 #pragma mark - NSControl delegate | |
128 | |
129 - (void)controlTextDidEndEditing:(NSNotification*)notification { | |
130 NSDictionary* userInfo = [notification userInfo]; | |
131 NSInteger textMovement = [userInfo[@"NSTextMovement"] intValue]; | |
132 if (textMovement == NSReturnTextMovement) { | |
133 [self.delegate appRTCMainView:self didEnterRoomId:_roomField.stringValue]; | |
134 } | |
135 } | |
136 | |
137 #pragma mark - RTCNSGLVideoViewDelegate | |
138 | |
139 - (void)videoView:(RTCNSGLVideoView*)videoView | |
140 didChangeVideoSize:(NSSize)size { | |
141 if (videoView == _remoteVideoView) { | |
142 _remoteVideoSize = size; | |
143 } else if (videoView == _localVideoView) { | |
144 _localVideoSize = size; | |
145 } else { | |
146 return; | |
147 } | |
148 [self setNeedsUpdateConstraints:YES]; | |
149 } | |
150 | |
151 #pragma mark - Private | |
152 | |
153 - (void)setupViews { | |
154 NSParameterAssert([[self subviews] count] == 0); | |
155 | |
156 _roomLabel = [[NSTextField alloc] initWithFrame:NSZeroRect]; | |
157 [_roomLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
158 [_roomLabel setBezeled:NO]; | |
159 [_roomLabel setDrawsBackground:NO]; | |
160 [_roomLabel setEditable:NO]; | |
161 [_roomLabel setStringValue:@"Enter AppRTC room id:"]; | |
162 [self addSubview:_roomLabel]; | |
163 | |
164 _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect]; | |
165 [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
166 [self addSubview:_roomField]; | |
167 [_roomField setEditable:YES]; | |
168 [_roomField setDelegate:self]; | |
169 | |
170 _logView = [[NSTextView alloc] initWithFrame:NSZeroRect]; | |
171 [_logView setMinSize:NSMakeSize(0, kLogViewHeight)]; | |
172 [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; | |
173 [_logView setVerticallyResizable:YES]; | |
174 [_logView setAutoresizingMask:NSViewWidthSizable]; | |
175 NSTextContainer* textContainer = [_logView textContainer]; | |
176 NSSize containerSize = NSMakeSize(kContentWidth, FLT_MAX); | |
177 [textContainer setContainerSize:containerSize]; | |
178 [textContainer setWidthTracksTextView:YES]; | |
179 [_logView setEditable:NO]; | |
180 | |
181 _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect]; | |
182 [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
183 [_scrollView setHasVerticalScroller:YES]; | |
184 [_scrollView setDocumentView:_logView]; | |
185 [self addSubview:_scrollView]; | |
186 | |
187 NSOpenGLPixelFormatAttribute attributes[] = { | |
188 NSOpenGLPFADoubleBuffer, | |
189 NSOpenGLPFADepthSize, 24, | |
190 NSOpenGLPFAOpenGLProfile, | |
191 NSOpenGLProfileVersion3_2Core, | |
192 0 | |
193 }; | |
194 NSOpenGLPixelFormat* pixelFormat = | |
195 [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; | |
196 _remoteVideoView = [[RTCNSGLVideoView alloc] initWithFrame:NSZeroRect | |
197 pixelFormat:pixelFormat]; | |
198 [_remoteVideoView setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
199 _remoteVideoView.delegate = self; | |
200 [self addSubview:_remoteVideoView]; | |
201 | |
202 _localVideoView = [[RTCNSGLVideoView alloc] initWithFrame:NSZeroRect | |
203 pixelFormat:pixelFormat]; | |
204 [_localVideoView setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
205 _localVideoView.delegate = self; | |
206 [self addSubview:_localVideoView]; | |
207 } | |
208 | |
209 - (NSSize)remoteVideoViewSize { | |
210 NSInteger width = MAX(_remoteVideoSize.width, kContentWidth); | |
211 NSInteger height = (width/16) * 9; | |
212 return NSMakeSize(width, height); | |
213 } | |
214 | |
215 @end | |
216 | |
217 @interface APPRTCViewController () | |
218 <ARDAppClientDelegate, APPRTCMainViewDelegate> | |
219 @property(nonatomic, readonly) APPRTCMainView* mainView; | |
220 @end | |
221 | |
222 @implementation APPRTCViewController { | |
223 ARDAppClient* _client; | |
224 RTCVideoTrack* _localVideoTrack; | |
225 RTCVideoTrack* _remoteVideoTrack; | |
226 } | |
227 | |
228 - (void)dealloc { | |
229 [self disconnect]; | |
230 } | |
231 | |
232 - (void)loadView { | |
233 APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect]; | |
234 [view setTranslatesAutoresizingMaskIntoConstraints:NO]; | |
235 view.delegate = self; | |
236 self.view = view; | |
237 } | |
238 | |
239 - (void)windowWillClose:(NSNotification*)notification { | |
240 [self disconnect]; | |
241 } | |
242 | |
243 #pragma mark - ARDAppClientDelegate | |
244 | |
245 - (void)appClient:(ARDAppClient *)client | |
246 didChangeState:(ARDAppClientState)state { | |
247 switch (state) { | |
248 case kARDAppClientStateConnected: | |
249 NSLog(@"Client connected."); | |
250 break; | |
251 case kARDAppClientStateConnecting: | |
252 NSLog(@"Client connecting."); | |
253 break; | |
254 case kARDAppClientStateDisconnected: | |
255 NSLog(@"Client disconnected."); | |
256 [self resetUI]; | |
257 _client = nil; | |
258 break; | |
259 } | |
260 } | |
261 | |
262 - (void)appClient:(ARDAppClient *)client | |
263 didChangeConnectionState:(RTCIceConnectionState)state { | |
264 } | |
265 | |
266 - (void)appClient:(ARDAppClient *)client | |
267 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack { | |
268 _localVideoTrack = localVideoTrack; | |
269 [_localVideoTrack addRenderer:self.mainView.localVideoView]; | |
270 } | |
271 | |
272 - (void)appClient:(ARDAppClient *)client | |
273 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack { | |
274 _remoteVideoTrack = remoteVideoTrack; | |
275 [_remoteVideoTrack addRenderer:self.mainView.remoteVideoView]; | |
276 } | |
277 | |
278 - (void)appClient:(ARDAppClient *)client | |
279 didError:(NSError *)error { | |
280 [self showAlertWithMessage:[NSString stringWithFormat:@"%@", error]]; | |
281 [self disconnect]; | |
282 } | |
283 | |
284 - (void)appClient:(ARDAppClient *)client | |
285 didGetStats:(NSArray *)stats { | |
286 } | |
287 | |
288 #pragma mark - APPRTCMainViewDelegate | |
289 | |
290 - (void)appRTCMainView:(APPRTCMainView*)mainView | |
291 didEnterRoomId:(NSString*)roomId { | |
292 [_client disconnect]; | |
293 ARDAppClient *client = [[ARDAppClient alloc] initWithDelegate:self]; | |
294 [client connectToRoomWithId:roomId | |
295 isLoopback:NO | |
296 isAudioOnly:NO | |
297 shouldMakeAecDump:NO | |
298 shouldUseLevelControl:NO]; | |
299 _client = client; | |
300 } | |
301 | |
302 #pragma mark - Private | |
303 | |
304 - (APPRTCMainView*)mainView { | |
305 return (APPRTCMainView*)self.view; | |
306 } | |
307 | |
308 - (void)showAlertWithMessage:(NSString*)message { | |
309 NSAlert* alert = [[NSAlert alloc] init]; | |
310 [alert setMessageText:message]; | |
311 [alert runModal]; | |
312 } | |
313 | |
314 - (void)resetUI { | |
315 [_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView]; | |
316 [_localVideoTrack removeRenderer:self.mainView.localVideoView]; | |
317 _remoteVideoTrack = nil; | |
318 _localVideoTrack = nil; | |
319 [self.mainView.remoteVideoView renderFrame:nil]; | |
320 [self.mainView.localVideoView renderFrame:nil]; | |
321 } | |
322 | |
323 - (void)disconnect { | |
324 [self resetUI]; | |
325 [_client disconnect]; | |
326 } | |
327 | |
328 @end | |
OLD | NEW |