xref: /aosp_15_r20/external/webrtc/examples/objc/AppRTCMobile/mac/APPRTCViewController.m (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker/*
2*d9f75844SAndroid Build Coastguard Worker *  Copyright 2014 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker#import "APPRTCViewController.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker#import <AVFoundation/AVFoundation.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker#import "sdk/objc/api/peerconnection/RTCVideoTrack.h"
16*d9f75844SAndroid Build Coastguard Worker#import "sdk/objc/components/renderer/metal/RTCMTLNSVideoView.h"
17*d9f75844SAndroid Build Coastguard Worker#import "sdk/objc/components/renderer/opengl/RTCNSGLVideoView.h"
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker#import "ARDAppClient.h"
20*d9f75844SAndroid Build Coastguard Worker#import "ARDCaptureController.h"
21*d9f75844SAndroid Build Coastguard Worker#import "ARDSettingsModel.h"
22*d9f75844SAndroid Build Coastguard Worker
23*d9f75844SAndroid Build Coastguard Workerstatic NSUInteger const kContentWidth = 900;
24*d9f75844SAndroid Build Coastguard Workerstatic NSUInteger const kRoomFieldWidth = 200;
25*d9f75844SAndroid Build Coastguard Workerstatic NSUInteger const kActionItemHeight = 30;
26*d9f75844SAndroid Build Coastguard Workerstatic NSUInteger const kBottomViewHeight = 200;
27*d9f75844SAndroid Build Coastguard Worker
28*d9f75844SAndroid Build Coastguard Worker@class APPRTCMainView;
29*d9f75844SAndroid Build Coastguard Worker@protocol APPRTCMainViewDelegate
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker- (void)appRTCMainView:(APPRTCMainView*)mainView
32*d9f75844SAndroid Build Coastguard Worker        didEnterRoomId:(NSString*)roomId
33*d9f75844SAndroid Build Coastguard Worker              loopback:(BOOL)isLoopback;
34*d9f75844SAndroid Build Coastguard Worker
35*d9f75844SAndroid Build Coastguard Worker@end
36*d9f75844SAndroid Build Coastguard Worker
37*d9f75844SAndroid Build Coastguard Worker@interface APPRTCMainView : NSView
38*d9f75844SAndroid Build Coastguard Worker
39*d9f75844SAndroid Build Coastguard Worker@property(nonatomic, weak) id<APPRTCMainViewDelegate> delegate;
40*d9f75844SAndroid Build Coastguard Worker@property(nonatomic, readonly) NSView<RTC_OBJC_TYPE(RTCVideoRenderer)>* localVideoView;
41*d9f75844SAndroid Build Coastguard Worker@property(nonatomic, readonly) NSView<RTC_OBJC_TYPE(RTCVideoRenderer)>* remoteVideoView;
42*d9f75844SAndroid Build Coastguard Worker@property(nonatomic, readonly) NSTextView* logView;
43*d9f75844SAndroid Build Coastguard Worker
44*d9f75844SAndroid Build Coastguard Worker- (void)displayLogMessage:(NSString*)message;
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker@end
47*d9f75844SAndroid Build Coastguard Worker
48*d9f75844SAndroid Build Coastguard Worker@interface APPRTCMainView () <NSTextFieldDelegate, RTC_OBJC_TYPE (RTCNSGLVideoViewDelegate)>
49*d9f75844SAndroid Build Coastguard Worker@end
50*d9f75844SAndroid Build Coastguard Worker@implementation APPRTCMainView  {
51*d9f75844SAndroid Build Coastguard Worker  NSScrollView* _scrollView;
52*d9f75844SAndroid Build Coastguard Worker  NSView* _actionItemsView;
53*d9f75844SAndroid Build Coastguard Worker  NSButton* _connectButton;
54*d9f75844SAndroid Build Coastguard Worker  NSButton* _loopbackButton;
55*d9f75844SAndroid Build Coastguard Worker  NSTextField* _roomField;
56*d9f75844SAndroid Build Coastguard Worker  CGSize _localVideoSize;
57*d9f75844SAndroid Build Coastguard Worker  CGSize _remoteVideoSize;
58*d9f75844SAndroid Build Coastguard Worker}
59*d9f75844SAndroid Build Coastguard Worker
60*d9f75844SAndroid Build Coastguard Worker@synthesize delegate = _delegate;
61*d9f75844SAndroid Build Coastguard Worker@synthesize localVideoView = _localVideoView;
62*d9f75844SAndroid Build Coastguard Worker@synthesize remoteVideoView = _remoteVideoView;
63*d9f75844SAndroid Build Coastguard Worker@synthesize logView = _logView;
64*d9f75844SAndroid Build Coastguard Worker
65*d9f75844SAndroid Build Coastguard Worker- (void)displayLogMessage:(NSString *)message {
66*d9f75844SAndroid Build Coastguard Worker  dispatch_async(dispatch_get_main_queue(), ^{
67*d9f75844SAndroid Build Coastguard Worker    self.logView.string = [NSString stringWithFormat:@"%@%@\n", self.logView.string, message];
68*d9f75844SAndroid Build Coastguard Worker    NSRange range = NSMakeRange(self.logView.string.length, 0);
69*d9f75844SAndroid Build Coastguard Worker    [self.logView scrollRangeToVisible:range];
70*d9f75844SAndroid Build Coastguard Worker  });
71*d9f75844SAndroid Build Coastguard Worker}
72*d9f75844SAndroid Build Coastguard Worker
73*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
74*d9f75844SAndroid Build Coastguard Worker
75*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithFrame:(NSRect)frame {
76*d9f75844SAndroid Build Coastguard Worker  if (self = [super initWithFrame:frame]) {
77*d9f75844SAndroid Build Coastguard Worker    [self setupViews];
78*d9f75844SAndroid Build Coastguard Worker  }
79*d9f75844SAndroid Build Coastguard Worker  return self;
80*d9f75844SAndroid Build Coastguard Worker}
81*d9f75844SAndroid Build Coastguard Worker
82*d9f75844SAndroid Build Coastguard Worker+ (BOOL)requiresConstraintBasedLayout {
83*d9f75844SAndroid Build Coastguard Worker  return YES;
84*d9f75844SAndroid Build Coastguard Worker}
85*d9f75844SAndroid Build Coastguard Worker
86*d9f75844SAndroid Build Coastguard Worker- (void)updateConstraints {
87*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert(
88*d9f75844SAndroid Build Coastguard Worker      _roomField != nil &&
89*d9f75844SAndroid Build Coastguard Worker      _scrollView != nil &&
90*d9f75844SAndroid Build Coastguard Worker      _remoteVideoView != nil &&
91*d9f75844SAndroid Build Coastguard Worker      _localVideoView != nil &&
92*d9f75844SAndroid Build Coastguard Worker      _actionItemsView!= nil &&
93*d9f75844SAndroid Build Coastguard Worker      _connectButton != nil &&
94*d9f75844SAndroid Build Coastguard Worker      _loopbackButton != nil);
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker  [self removeConstraints:[self constraints]];
97*d9f75844SAndroid Build Coastguard Worker  NSDictionary* viewsDictionary =
98*d9f75844SAndroid Build Coastguard Worker      NSDictionaryOfVariableBindings(_roomField,
99*d9f75844SAndroid Build Coastguard Worker                                     _scrollView,
100*d9f75844SAndroid Build Coastguard Worker                                     _remoteVideoView,
101*d9f75844SAndroid Build Coastguard Worker                                     _localVideoView,
102*d9f75844SAndroid Build Coastguard Worker                                     _actionItemsView,
103*d9f75844SAndroid Build Coastguard Worker                                     _connectButton,
104*d9f75844SAndroid Build Coastguard Worker                                     _loopbackButton);
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker  NSSize remoteViewSize = [self remoteVideoViewSize];
107*d9f75844SAndroid Build Coastguard Worker  NSDictionary* metrics = @{
108*d9f75844SAndroid Build Coastguard Worker    @"remoteViewWidth" : @(remoteViewSize.width),
109*d9f75844SAndroid Build Coastguard Worker    @"remoteViewHeight" : @(remoteViewSize.height),
110*d9f75844SAndroid Build Coastguard Worker    @"kBottomViewHeight" : @(kBottomViewHeight),
111*d9f75844SAndroid Build Coastguard Worker    @"localViewHeight" : @(remoteViewSize.height / 3),
112*d9f75844SAndroid Build Coastguard Worker    @"localViewWidth" : @(remoteViewSize.width / 3),
113*d9f75844SAndroid Build Coastguard Worker    @"kRoomFieldWidth" : @(kRoomFieldWidth),
114*d9f75844SAndroid Build Coastguard Worker    @"kActionItemHeight" : @(kActionItemHeight)
115*d9f75844SAndroid Build Coastguard Worker  };
116*d9f75844SAndroid Build Coastguard Worker  // Declare this separately to avoid compiler warning about splitting string
117*d9f75844SAndroid Build Coastguard Worker  // within an NSArray expression.
118*d9f75844SAndroid Build Coastguard Worker  NSString* verticalConstraintLeft =
119*d9f75844SAndroid Build Coastguard Worker      @"V:|-[_remoteVideoView(remoteViewHeight)]-[_scrollView(kBottomViewHeight)]-|";
120*d9f75844SAndroid Build Coastguard Worker  NSString* verticalConstraintRight =
121*d9f75844SAndroid Build Coastguard Worker      @"V:|-[_remoteVideoView(remoteViewHeight)]-[_actionItemsView(kBottomViewHeight)]-|";
122*d9f75844SAndroid Build Coastguard Worker  NSArray* constraintFormats = @[
123*d9f75844SAndroid Build Coastguard Worker      verticalConstraintLeft,
124*d9f75844SAndroid Build Coastguard Worker      verticalConstraintRight,
125*d9f75844SAndroid Build Coastguard Worker      @"H:|-[_remoteVideoView(remoteViewWidth)]-|",
126*d9f75844SAndroid Build Coastguard Worker      @"V:|-[_localVideoView(localViewHeight)]",
127*d9f75844SAndroid Build Coastguard Worker      @"H:|-[_localVideoView(localViewWidth)]",
128*d9f75844SAndroid Build Coastguard Worker      @"H:|-[_scrollView(==_actionItemsView)]-[_actionItemsView]-|"
129*d9f75844SAndroid Build Coastguard Worker  ];
130*d9f75844SAndroid Build Coastguard Worker
131*d9f75844SAndroid Build Coastguard Worker  NSArray* actionItemsConstraints = @[
132*d9f75844SAndroid Build Coastguard Worker      @"H:|-[_roomField(kRoomFieldWidth)]-[_loopbackButton(kRoomFieldWidth)]",
133*d9f75844SAndroid Build Coastguard Worker      @"H:|-[_connectButton(kRoomFieldWidth)]",
134*d9f75844SAndroid Build Coastguard Worker      @"V:|-[_roomField(kActionItemHeight)]-[_connectButton(kActionItemHeight)]",
135*d9f75844SAndroid Build Coastguard Worker      @"V:|-[_loopbackButton(kActionItemHeight)]",
136*d9f75844SAndroid Build Coastguard Worker      ];
137*d9f75844SAndroid Build Coastguard Worker
138*d9f75844SAndroid Build Coastguard Worker  [APPRTCMainView addConstraints:constraintFormats
139*d9f75844SAndroid Build Coastguard Worker                          toView:self
140*d9f75844SAndroid Build Coastguard Worker                 viewsDictionary:viewsDictionary
141*d9f75844SAndroid Build Coastguard Worker                         metrics:metrics];
142*d9f75844SAndroid Build Coastguard Worker  [APPRTCMainView addConstraints:actionItemsConstraints
143*d9f75844SAndroid Build Coastguard Worker                          toView:_actionItemsView
144*d9f75844SAndroid Build Coastguard Worker                 viewsDictionary:viewsDictionary
145*d9f75844SAndroid Build Coastguard Worker                         metrics:metrics];
146*d9f75844SAndroid Build Coastguard Worker  [super updateConstraints];
147*d9f75844SAndroid Build Coastguard Worker}
148*d9f75844SAndroid Build Coastguard Worker
149*d9f75844SAndroid Build Coastguard Worker#pragma mark - Constraints helper
150*d9f75844SAndroid Build Coastguard Worker
151*d9f75844SAndroid Build Coastguard Worker+ (void)addConstraints:(NSArray*)constraints toView:(NSView*)view
152*d9f75844SAndroid Build Coastguard Worker       viewsDictionary:(NSDictionary*)viewsDictionary
153*d9f75844SAndroid Build Coastguard Worker               metrics:(NSDictionary*)metrics {
154*d9f75844SAndroid Build Coastguard Worker  for (NSString* constraintFormat in constraints) {
155*d9f75844SAndroid Build Coastguard Worker    NSArray* constraints =
156*d9f75844SAndroid Build Coastguard Worker    [NSLayoutConstraint constraintsWithVisualFormat:constraintFormat
157*d9f75844SAndroid Build Coastguard Worker                                            options:0
158*d9f75844SAndroid Build Coastguard Worker                                            metrics:metrics
159*d9f75844SAndroid Build Coastguard Worker                                              views:viewsDictionary];
160*d9f75844SAndroid Build Coastguard Worker    for (NSLayoutConstraint* constraint in constraints) {
161*d9f75844SAndroid Build Coastguard Worker      [view addConstraint:constraint];
162*d9f75844SAndroid Build Coastguard Worker    }
163*d9f75844SAndroid Build Coastguard Worker  }
164*d9f75844SAndroid Build Coastguard Worker}
165*d9f75844SAndroid Build Coastguard Worker
166*d9f75844SAndroid Build Coastguard Worker#pragma mark - Control actions
167*d9f75844SAndroid Build Coastguard Worker
168*d9f75844SAndroid Build Coastguard Worker- (void)startCall:(id)sender {
169*d9f75844SAndroid Build Coastguard Worker  NSString* roomString = _roomField.stringValue;
170*d9f75844SAndroid Build Coastguard Worker  // Generate room id for loopback options.
171*d9f75844SAndroid Build Coastguard Worker  if (_loopbackButton.intValue && [roomString isEqualToString:@""]) {
172*d9f75844SAndroid Build Coastguard Worker    roomString = [NSUUID UUID].UUIDString;
173*d9f75844SAndroid Build Coastguard Worker    roomString = [roomString stringByReplacingOccurrencesOfString:@"-" withString:@""];
174*d9f75844SAndroid Build Coastguard Worker  }
175*d9f75844SAndroid Build Coastguard Worker  [self.delegate appRTCMainView:self
176*d9f75844SAndroid Build Coastguard Worker                 didEnterRoomId:roomString
177*d9f75844SAndroid Build Coastguard Worker                       loopback:_loopbackButton.intValue];
178*d9f75844SAndroid Build Coastguard Worker  [self setNeedsUpdateConstraints:YES];
179*d9f75844SAndroid Build Coastguard Worker}
180*d9f75844SAndroid Build Coastguard Worker
181*d9f75844SAndroid Build Coastguard Worker#pragma mark - RTC_OBJC_TYPE(RTCNSGLVideoViewDelegate)
182*d9f75844SAndroid Build Coastguard Worker
183*d9f75844SAndroid Build Coastguard Worker- (void)videoView:(RTC_OBJC_TYPE(RTCNSGLVideoView) *)videoView didChangeVideoSize:(NSSize)size {
184*d9f75844SAndroid Build Coastguard Worker  if (videoView == _remoteVideoView) {
185*d9f75844SAndroid Build Coastguard Worker    _remoteVideoSize = size;
186*d9f75844SAndroid Build Coastguard Worker  } else if (videoView == _localVideoView) {
187*d9f75844SAndroid Build Coastguard Worker    _localVideoSize = size;
188*d9f75844SAndroid Build Coastguard Worker  } else {
189*d9f75844SAndroid Build Coastguard Worker    return;
190*d9f75844SAndroid Build Coastguard Worker  }
191*d9f75844SAndroid Build Coastguard Worker
192*d9f75844SAndroid Build Coastguard Worker  [self setNeedsUpdateConstraints:YES];
193*d9f75844SAndroid Build Coastguard Worker}
194*d9f75844SAndroid Build Coastguard Worker
195*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
196*d9f75844SAndroid Build Coastguard Worker
197*d9f75844SAndroid Build Coastguard Worker- (void)setupViews {
198*d9f75844SAndroid Build Coastguard Worker  NSParameterAssert([[self subviews] count] == 0);
199*d9f75844SAndroid Build Coastguard Worker
200*d9f75844SAndroid Build Coastguard Worker  _logView = [[NSTextView alloc] initWithFrame:NSZeroRect];
201*d9f75844SAndroid Build Coastguard Worker  [_logView setMinSize:NSMakeSize(0, kBottomViewHeight)];
202*d9f75844SAndroid Build Coastguard Worker  [_logView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
203*d9f75844SAndroid Build Coastguard Worker  [_logView setVerticallyResizable:YES];
204*d9f75844SAndroid Build Coastguard Worker  [_logView setAutoresizingMask:NSViewWidthSizable];
205*d9f75844SAndroid Build Coastguard Worker  NSTextContainer* textContainer = [_logView textContainer];
206*d9f75844SAndroid Build Coastguard Worker  NSSize containerSize = NSMakeSize(kContentWidth, FLT_MAX);
207*d9f75844SAndroid Build Coastguard Worker  [textContainer setContainerSize:containerSize];
208*d9f75844SAndroid Build Coastguard Worker  [textContainer setWidthTracksTextView:YES];
209*d9f75844SAndroid Build Coastguard Worker  [_logView setEditable:NO];
210*d9f75844SAndroid Build Coastguard Worker
211*d9f75844SAndroid Build Coastguard Worker  [self setupActionItemsView];
212*d9f75844SAndroid Build Coastguard Worker
213*d9f75844SAndroid Build Coastguard Worker  _scrollView = [[NSScrollView alloc] initWithFrame:NSZeroRect];
214*d9f75844SAndroid Build Coastguard Worker  [_scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
215*d9f75844SAndroid Build Coastguard Worker  [_scrollView setHasVerticalScroller:YES];
216*d9f75844SAndroid Build Coastguard Worker  [_scrollView setDocumentView:_logView];
217*d9f75844SAndroid Build Coastguard Worker  [self addSubview:_scrollView];
218*d9f75844SAndroid Build Coastguard Worker
219*d9f75844SAndroid Build Coastguard Worker// NOTE (daniela): Ignoring Clang diagonstic here.
220*d9f75844SAndroid Build Coastguard Worker// We're performing run time check to make sure class is available on runtime.
221*d9f75844SAndroid Build Coastguard Worker// If not we're providing sensible default.
222*d9f75844SAndroid Build Coastguard Worker#pragma clang diagnostic push
223*d9f75844SAndroid Build Coastguard Worker#pragma clang diagnostic ignored "-Wpartial-availability"
224*d9f75844SAndroid Build Coastguard Worker  if ([RTC_OBJC_TYPE(RTCMTLNSVideoView) class] &&
225*d9f75844SAndroid Build Coastguard Worker      [RTC_OBJC_TYPE(RTCMTLNSVideoView) isMetalAvailable]) {
226*d9f75844SAndroid Build Coastguard Worker    _remoteVideoView = [[RTC_OBJC_TYPE(RTCMTLNSVideoView) alloc] initWithFrame:NSZeroRect];
227*d9f75844SAndroid Build Coastguard Worker    _localVideoView = [[RTC_OBJC_TYPE(RTCMTLNSVideoView) alloc] initWithFrame:NSZeroRect];
228*d9f75844SAndroid Build Coastguard Worker  }
229*d9f75844SAndroid Build Coastguard Worker#pragma clang diagnostic pop
230*d9f75844SAndroid Build Coastguard Worker  if (_remoteVideoView == nil) {
231*d9f75844SAndroid Build Coastguard Worker    NSOpenGLPixelFormatAttribute attributes[] = {
232*d9f75844SAndroid Build Coastguard Worker      NSOpenGLPFADoubleBuffer,
233*d9f75844SAndroid Build Coastguard Worker      NSOpenGLPFADepthSize, 24,
234*d9f75844SAndroid Build Coastguard Worker      NSOpenGLPFAOpenGLProfile,
235*d9f75844SAndroid Build Coastguard Worker      NSOpenGLProfileVersion3_2Core,
236*d9f75844SAndroid Build Coastguard Worker      0
237*d9f75844SAndroid Build Coastguard Worker    };
238*d9f75844SAndroid Build Coastguard Worker    NSOpenGLPixelFormat* pixelFormat =
239*d9f75844SAndroid Build Coastguard Worker    [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
240*d9f75844SAndroid Build Coastguard Worker
241*d9f75844SAndroid Build Coastguard Worker    RTC_OBJC_TYPE(RTCNSGLVideoView)* remote =
242*d9f75844SAndroid Build Coastguard Worker        [[RTC_OBJC_TYPE(RTCNSGLVideoView) alloc] initWithFrame:NSZeroRect pixelFormat:pixelFormat];
243*d9f75844SAndroid Build Coastguard Worker    remote.delegate = self;
244*d9f75844SAndroid Build Coastguard Worker    _remoteVideoView = remote;
245*d9f75844SAndroid Build Coastguard Worker
246*d9f75844SAndroid Build Coastguard Worker    RTC_OBJC_TYPE(RTCNSGLVideoView)* local =
247*d9f75844SAndroid Build Coastguard Worker        [[RTC_OBJC_TYPE(RTCNSGLVideoView) alloc] initWithFrame:NSZeroRect pixelFormat:pixelFormat];
248*d9f75844SAndroid Build Coastguard Worker    local.delegate = self;
249*d9f75844SAndroid Build Coastguard Worker    _localVideoView = local;
250*d9f75844SAndroid Build Coastguard Worker  }
251*d9f75844SAndroid Build Coastguard Worker
252*d9f75844SAndroid Build Coastguard Worker  [_remoteVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
253*d9f75844SAndroid Build Coastguard Worker  [self addSubview:_remoteVideoView];
254*d9f75844SAndroid Build Coastguard Worker  [_localVideoView setTranslatesAutoresizingMaskIntoConstraints:NO];
255*d9f75844SAndroid Build Coastguard Worker  [self addSubview:_localVideoView];
256*d9f75844SAndroid Build Coastguard Worker}
257*d9f75844SAndroid Build Coastguard Worker
258*d9f75844SAndroid Build Coastguard Worker- (void)setupActionItemsView {
259*d9f75844SAndroid Build Coastguard Worker  _actionItemsView = [[NSView alloc] initWithFrame:NSZeroRect];
260*d9f75844SAndroid Build Coastguard Worker  [_actionItemsView setTranslatesAutoresizingMaskIntoConstraints:NO];
261*d9f75844SAndroid Build Coastguard Worker  [self addSubview:_actionItemsView];
262*d9f75844SAndroid Build Coastguard Worker
263*d9f75844SAndroid Build Coastguard Worker  _roomField = [[NSTextField alloc] initWithFrame:NSZeroRect];
264*d9f75844SAndroid Build Coastguard Worker  [_roomField setTranslatesAutoresizingMaskIntoConstraints:NO];
265*d9f75844SAndroid Build Coastguard Worker  [[_roomField cell] setPlaceholderString: @"Enter AppRTC room id"];
266*d9f75844SAndroid Build Coastguard Worker  [_actionItemsView addSubview:_roomField];
267*d9f75844SAndroid Build Coastguard Worker  [_roomField setEditable:YES];
268*d9f75844SAndroid Build Coastguard Worker
269*d9f75844SAndroid Build Coastguard Worker  _connectButton = [[NSButton alloc] initWithFrame:NSZeroRect];
270*d9f75844SAndroid Build Coastguard Worker  [_connectButton setTranslatesAutoresizingMaskIntoConstraints:NO];
271*d9f75844SAndroid Build Coastguard Worker  _connectButton.title = @"Start call";
272*d9f75844SAndroid Build Coastguard Worker  _connectButton.bezelStyle = NSRoundedBezelStyle;
273*d9f75844SAndroid Build Coastguard Worker  _connectButton.target = self;
274*d9f75844SAndroid Build Coastguard Worker  _connectButton.action = @selector(startCall:);
275*d9f75844SAndroid Build Coastguard Worker  [_actionItemsView addSubview:_connectButton];
276*d9f75844SAndroid Build Coastguard Worker
277*d9f75844SAndroid Build Coastguard Worker  _loopbackButton = [[NSButton alloc] initWithFrame:NSZeroRect];
278*d9f75844SAndroid Build Coastguard Worker  [_loopbackButton setTranslatesAutoresizingMaskIntoConstraints:NO];
279*d9f75844SAndroid Build Coastguard Worker  _loopbackButton.title = @"Loopback";
280*d9f75844SAndroid Build Coastguard Worker  [_loopbackButton setButtonType:NSSwitchButton];
281*d9f75844SAndroid Build Coastguard Worker  [_actionItemsView addSubview:_loopbackButton];
282*d9f75844SAndroid Build Coastguard Worker}
283*d9f75844SAndroid Build Coastguard Worker
284*d9f75844SAndroid Build Coastguard Worker- (NSSize)remoteVideoViewSize {
285*d9f75844SAndroid Build Coastguard Worker  if (!_remoteVideoView.bounds.size.width) {
286*d9f75844SAndroid Build Coastguard Worker    return NSMakeSize(kContentWidth, 0);
287*d9f75844SAndroid Build Coastguard Worker  }
288*d9f75844SAndroid Build Coastguard Worker  NSInteger width = MAX(_remoteVideoView.bounds.size.width, kContentWidth);
289*d9f75844SAndroid Build Coastguard Worker  NSInteger height = (width/16) * 9;
290*d9f75844SAndroid Build Coastguard Worker  return NSMakeSize(width, height);
291*d9f75844SAndroid Build Coastguard Worker}
292*d9f75844SAndroid Build Coastguard Worker
293*d9f75844SAndroid Build Coastguard Worker@end
294*d9f75844SAndroid Build Coastguard Worker
295*d9f75844SAndroid Build Coastguard Worker@interface APPRTCViewController ()
296*d9f75844SAndroid Build Coastguard Worker    <ARDAppClientDelegate, APPRTCMainViewDelegate>
297*d9f75844SAndroid Build Coastguard Worker@property(nonatomic, readonly) APPRTCMainView* mainView;
298*d9f75844SAndroid Build Coastguard Worker@end
299*d9f75844SAndroid Build Coastguard Worker
300*d9f75844SAndroid Build Coastguard Worker@implementation APPRTCViewController {
301*d9f75844SAndroid Build Coastguard Worker  ARDAppClient* _client;
302*d9f75844SAndroid Build Coastguard Worker  RTC_OBJC_TYPE(RTCVideoTrack) * _localVideoTrack;
303*d9f75844SAndroid Build Coastguard Worker  RTC_OBJC_TYPE(RTCVideoTrack) * _remoteVideoTrack;
304*d9f75844SAndroid Build Coastguard Worker  ARDCaptureController* _captureController;
305*d9f75844SAndroid Build Coastguard Worker}
306*d9f75844SAndroid Build Coastguard Worker
307*d9f75844SAndroid Build Coastguard Worker- (void)dealloc {
308*d9f75844SAndroid Build Coastguard Worker  [self disconnect];
309*d9f75844SAndroid Build Coastguard Worker}
310*d9f75844SAndroid Build Coastguard Worker
311*d9f75844SAndroid Build Coastguard Worker- (void)viewDidAppear {
312*d9f75844SAndroid Build Coastguard Worker  [super viewDidAppear];
313*d9f75844SAndroid Build Coastguard Worker  [self displayUsageInstructions];
314*d9f75844SAndroid Build Coastguard Worker}
315*d9f75844SAndroid Build Coastguard Worker
316*d9f75844SAndroid Build Coastguard Worker- (void)loadView {
317*d9f75844SAndroid Build Coastguard Worker  APPRTCMainView* view = [[APPRTCMainView alloc] initWithFrame:NSZeroRect];
318*d9f75844SAndroid Build Coastguard Worker  [view setTranslatesAutoresizingMaskIntoConstraints:NO];
319*d9f75844SAndroid Build Coastguard Worker  view.delegate = self;
320*d9f75844SAndroid Build Coastguard Worker  self.view = view;
321*d9f75844SAndroid Build Coastguard Worker}
322*d9f75844SAndroid Build Coastguard Worker
323*d9f75844SAndroid Build Coastguard Worker- (void)windowWillClose:(NSNotification*)notification {
324*d9f75844SAndroid Build Coastguard Worker  [self disconnect];
325*d9f75844SAndroid Build Coastguard Worker}
326*d9f75844SAndroid Build Coastguard Worker
327*d9f75844SAndroid Build Coastguard Worker#pragma mark - Usage
328*d9f75844SAndroid Build Coastguard Worker
329*d9f75844SAndroid Build Coastguard Worker- (void)displayUsageInstructions {
330*d9f75844SAndroid Build Coastguard Worker  [self.mainView displayLogMessage:
331*d9f75844SAndroid Build Coastguard Worker   @"To start call:\n"
332*d9f75844SAndroid Build Coastguard Worker   @"• Enter AppRTC room id (not neccessary for loopback)\n"
333*d9f75844SAndroid Build Coastguard Worker   @"• Start call"];
334*d9f75844SAndroid Build Coastguard Worker}
335*d9f75844SAndroid Build Coastguard Worker
336*d9f75844SAndroid Build Coastguard Worker#pragma mark - ARDAppClientDelegate
337*d9f75844SAndroid Build Coastguard Worker
338*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient *)client
339*d9f75844SAndroid Build Coastguard Worker    didChangeState:(ARDAppClientState)state {
340*d9f75844SAndroid Build Coastguard Worker  switch (state) {
341*d9f75844SAndroid Build Coastguard Worker    case kARDAppClientStateConnected:
342*d9f75844SAndroid Build Coastguard Worker      [self.mainView displayLogMessage:@"Client connected."];
343*d9f75844SAndroid Build Coastguard Worker      break;
344*d9f75844SAndroid Build Coastguard Worker    case kARDAppClientStateConnecting:
345*d9f75844SAndroid Build Coastguard Worker      [self.mainView displayLogMessage:@"Client connecting."];
346*d9f75844SAndroid Build Coastguard Worker      break;
347*d9f75844SAndroid Build Coastguard Worker    case kARDAppClientStateDisconnected:
348*d9f75844SAndroid Build Coastguard Worker      [self.mainView displayLogMessage:@"Client disconnected."];
349*d9f75844SAndroid Build Coastguard Worker      [self resetUI];
350*d9f75844SAndroid Build Coastguard Worker      _client = nil;
351*d9f75844SAndroid Build Coastguard Worker      break;
352*d9f75844SAndroid Build Coastguard Worker  }
353*d9f75844SAndroid Build Coastguard Worker}
354*d9f75844SAndroid Build Coastguard Worker
355*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient *)client
356*d9f75844SAndroid Build Coastguard Worker    didChangeConnectionState:(RTCIceConnectionState)state {
357*d9f75844SAndroid Build Coastguard Worker}
358*d9f75844SAndroid Build Coastguard Worker
359*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient*)client
360*d9f75844SAndroid Build Coastguard Worker    didCreateLocalCapturer:(RTC_OBJC_TYPE(RTCCameraVideoCapturer) *)localCapturer {
361*d9f75844SAndroid Build Coastguard Worker  _captureController =
362*d9f75844SAndroid Build Coastguard Worker      [[ARDCaptureController alloc] initWithCapturer:localCapturer
363*d9f75844SAndroid Build Coastguard Worker                                            settings:[[ARDSettingsModel alloc] init]];
364*d9f75844SAndroid Build Coastguard Worker  [_captureController startCapture];
365*d9f75844SAndroid Build Coastguard Worker}
366*d9f75844SAndroid Build Coastguard Worker
367*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient*)client
368*d9f75844SAndroid Build Coastguard Worker    didReceiveLocalVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)localVideoTrack {
369*d9f75844SAndroid Build Coastguard Worker  _localVideoTrack = localVideoTrack;
370*d9f75844SAndroid Build Coastguard Worker  [_localVideoTrack addRenderer:self.mainView.localVideoView];
371*d9f75844SAndroid Build Coastguard Worker}
372*d9f75844SAndroid Build Coastguard Worker
373*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient*)client
374*d9f75844SAndroid Build Coastguard Worker    didReceiveRemoteVideoTrack:(RTC_OBJC_TYPE(RTCVideoTrack) *)remoteVideoTrack {
375*d9f75844SAndroid Build Coastguard Worker  _remoteVideoTrack = remoteVideoTrack;
376*d9f75844SAndroid Build Coastguard Worker  [_remoteVideoTrack addRenderer:self.mainView.remoteVideoView];
377*d9f75844SAndroid Build Coastguard Worker}
378*d9f75844SAndroid Build Coastguard Worker
379*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient *)client
380*d9f75844SAndroid Build Coastguard Worker         didError:(NSError *)error {
381*d9f75844SAndroid Build Coastguard Worker  [self showAlertWithMessage:[NSString stringWithFormat:@"%@", error]];
382*d9f75844SAndroid Build Coastguard Worker  [self disconnect];
383*d9f75844SAndroid Build Coastguard Worker}
384*d9f75844SAndroid Build Coastguard Worker
385*d9f75844SAndroid Build Coastguard Worker- (void)appClient:(ARDAppClient *)client
386*d9f75844SAndroid Build Coastguard Worker      didGetStats:(NSArray *)stats {
387*d9f75844SAndroid Build Coastguard Worker}
388*d9f75844SAndroid Build Coastguard Worker
389*d9f75844SAndroid Build Coastguard Worker#pragma mark - APPRTCMainViewDelegate
390*d9f75844SAndroid Build Coastguard Worker
391*d9f75844SAndroid Build Coastguard Worker- (void)appRTCMainView:(APPRTCMainView*)mainView
392*d9f75844SAndroid Build Coastguard Worker        didEnterRoomId:(NSString*)roomId
393*d9f75844SAndroid Build Coastguard Worker              loopback:(BOOL)isLoopback {
394*d9f75844SAndroid Build Coastguard Worker
395*d9f75844SAndroid Build Coastguard Worker  if ([roomId isEqualToString:@""]) {
396*d9f75844SAndroid Build Coastguard Worker    [self.mainView displayLogMessage:@"Missing room id"];
397*d9f75844SAndroid Build Coastguard Worker    return;
398*d9f75844SAndroid Build Coastguard Worker  }
399*d9f75844SAndroid Build Coastguard Worker
400*d9f75844SAndroid Build Coastguard Worker  [self disconnect];
401*d9f75844SAndroid Build Coastguard Worker  ARDAppClient* client = [[ARDAppClient alloc] initWithDelegate:self];
402*d9f75844SAndroid Build Coastguard Worker  [client connectToRoomWithId:roomId
403*d9f75844SAndroid Build Coastguard Worker                     settings:[[ARDSettingsModel alloc] init]  // Use default settings.
404*d9f75844SAndroid Build Coastguard Worker                   isLoopback:isLoopback];
405*d9f75844SAndroid Build Coastguard Worker  _client = client;
406*d9f75844SAndroid Build Coastguard Worker}
407*d9f75844SAndroid Build Coastguard Worker
408*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
409*d9f75844SAndroid Build Coastguard Worker
410*d9f75844SAndroid Build Coastguard Worker- (APPRTCMainView*)mainView {
411*d9f75844SAndroid Build Coastguard Worker  return (APPRTCMainView*)self.view;
412*d9f75844SAndroid Build Coastguard Worker}
413*d9f75844SAndroid Build Coastguard Worker
414*d9f75844SAndroid Build Coastguard Worker- (void)showAlertWithMessage:(NSString*)message {
415*d9f75844SAndroid Build Coastguard Worker  dispatch_async(dispatch_get_main_queue(), ^{
416*d9f75844SAndroid Build Coastguard Worker    NSAlert* alert = [[NSAlert alloc] init];
417*d9f75844SAndroid Build Coastguard Worker    [alert setMessageText:message];
418*d9f75844SAndroid Build Coastguard Worker    [alert runModal];
419*d9f75844SAndroid Build Coastguard Worker  });
420*d9f75844SAndroid Build Coastguard Worker}
421*d9f75844SAndroid Build Coastguard Worker
422*d9f75844SAndroid Build Coastguard Worker- (void)resetUI {
423*d9f75844SAndroid Build Coastguard Worker  [_remoteVideoTrack removeRenderer:self.mainView.remoteVideoView];
424*d9f75844SAndroid Build Coastguard Worker  [_localVideoTrack removeRenderer:self.mainView.localVideoView];
425*d9f75844SAndroid Build Coastguard Worker  _remoteVideoTrack = nil;
426*d9f75844SAndroid Build Coastguard Worker  _localVideoTrack = nil;
427*d9f75844SAndroid Build Coastguard Worker  [self.mainView.remoteVideoView renderFrame:nil];
428*d9f75844SAndroid Build Coastguard Worker  [self.mainView.localVideoView renderFrame:nil];
429*d9f75844SAndroid Build Coastguard Worker}
430*d9f75844SAndroid Build Coastguard Worker
431*d9f75844SAndroid Build Coastguard Worker- (void)disconnect {
432*d9f75844SAndroid Build Coastguard Worker  [self resetUI];
433*d9f75844SAndroid Build Coastguard Worker  [_captureController stopCapture];
434*d9f75844SAndroid Build Coastguard Worker  _captureController = nil;
435*d9f75844SAndroid Build Coastguard Worker  [_client disconnect];
436*d9f75844SAndroid Build Coastguard Worker}
437*d9f75844SAndroid Build Coastguard Worker
438*d9f75844SAndroid Build Coastguard Worker@end
439