blob: aa9ea2113d3ceaaba2b776495eb38cff23f4fcd5 [file] [log] [blame]
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00001/*
Donald E Curtisa8736442015-08-05 15:48:13 -07002 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +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.orgef2a5dd2015-01-15 22:38:21 +00009 */
10
11#import "ARDVideoCallViewController.h"
12
tkchin0ce3bf92016-03-12 16:52:04 -080013#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
14
tkchin9eeb6242016-04-27 01:54:20 -070015#import "WebRTC/RTCAVFoundationVideoSource.h"
16#import "WebRTC/RTCDispatcher.h"
17#import "WebRTC/RTCLogging.h"
Zeke Chin57cc74e2015-05-05 07:52:31 -070018
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000019#import "ARDAppClient.h"
20#import "ARDVideoCallView.h"
21
22@interface ARDVideoCallViewController () <ARDAppClientDelegate,
23 ARDVideoCallViewDelegate>
Zeke Chin57cc74e2015-05-05 07:52:31 -070024@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
25@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000026@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
27@end
28
29@implementation ARDVideoCallViewController {
30 ARDAppClient *_client;
31 RTCVideoTrack *_remoteVideoTrack;
32 RTCVideoTrack *_localVideoTrack;
tkchin0ce3bf92016-03-12 16:52:04 -080033 AVAudioSessionPortOverride _portOverride;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000034}
35
36@synthesize videoCallView = _videoCallView;
tkchind2511962016-05-06 18:54:15 -070037@synthesize delegate = _delegate;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000038
haysc913e6452015-10-02 11:44:03 -070039- (instancetype)initForRoom:(NSString *)room
40 isLoopback:(BOOL)isLoopback
tkchind2511962016-05-06 18:54:15 -070041 isAudioOnly:(BOOL)isAudioOnly
peah5085b0c2016-08-25 22:15:14 -070042 shouldMakeAecDump:(BOOL)shouldMakeAecDump
tkchinab1293a2016-08-30 12:35:05 -070043 shouldUseLevelControl:(BOOL)shouldUseLevelControl
tkchind2511962016-05-06 18:54:15 -070044 delegate:(id<ARDVideoCallViewControllerDelegate>)delegate {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000045 if (self = [super init]) {
tkchind2511962016-05-06 18:54:15 -070046 _delegate = delegate;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000047 _client = [[ARDAppClient alloc] initWithDelegate:self];
haysc913e6452015-10-02 11:44:03 -070048 [_client connectToRoomWithId:room
49 isLoopback:isLoopback
peah5085b0c2016-08-25 22:15:14 -070050 isAudioOnly:isAudioOnly
tkchinab1293a2016-08-30 12:35:05 -070051 shouldMakeAecDump:shouldMakeAecDump
52 shouldUseLevelControl:shouldUseLevelControl];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000053 }
54 return self;
55}
56
57- (void)loadView {
58 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
59 _videoCallView.delegate = self;
60 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070061 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000062 self.view = _videoCallView;
63}
64
65#pragma mark - ARDAppClientDelegate
66
67- (void)appClient:(ARDAppClient *)client
68 didChangeState:(ARDAppClientState)state {
69 switch (state) {
70 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070071 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000072 break;
73 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070074 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000075 break;
76 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070077 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000078 [self hangup];
79 break;
80 }
81}
82
83- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070084 didChangeConnectionState:(RTCIceConnectionState)state {
85 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000086 __weak ARDVideoCallViewController *weakSelf = self;
87 dispatch_async(dispatch_get_main_queue(), ^{
88 ARDVideoCallViewController *strongSelf = weakSelf;
89 strongSelf.videoCallView.statusLabel.text =
90 [strongSelf statusTextForState:state];
91 });
92}
93
94- (void)appClient:(ARDAppClient *)client
95 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -070096 self.localVideoTrack = localVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000097}
98
99- (void)appClient:(ARDAppClient *)client
100 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700101 self.remoteVideoTrack = remoteVideoTrack;
102 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000103}
104
105- (void)appClient:(ARDAppClient *)client
Zeke Chind3325802015-08-14 11:00:02 -0700106 didGetStats:(NSArray *)stats {
107 _videoCallView.statsView.stats = stats;
108 [_videoCallView setNeedsLayout];
109}
110
111- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000112 didError:(NSError *)error {
113 NSString *message =
114 [NSString stringWithFormat:@"%@", error.localizedDescription];
115 [self showAlertWithMessage:message];
116 [self hangup];
117}
118
119#pragma mark - ARDVideoCallViewDelegate
120
121- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
122 [self hangup];
123}
124
Zeke Chin57cc74e2015-05-05 07:52:31 -0700125- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
126 // TODO(tkchin): Rate limit this so you can't tap continously on it.
127 // Probably through an animation.
128 [self switchCamera];
129}
130
tkchin0ce3bf92016-03-12 16:52:04 -0800131- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
132 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
133 if (_portOverride == AVAudioSessionPortOverrideNone) {
134 override = AVAudioSessionPortOverrideSpeaker;
135 }
136 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
137 block:^{
138 RTCAudioSession *session = [RTCAudioSession sharedInstance];
139 [session lockForConfiguration];
140 NSError *error = nil;
141 if ([session overrideOutputAudioPort:override error:&error]) {
142 _portOverride = override;
143 } else {
144 RTCLogError(@"Error overriding output port: %@",
145 error.localizedDescription);
146 }
147 [session unlockForConfiguration];
148 }];
149}
150
Zeke Chind3325802015-08-14 11:00:02 -0700151- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
152 _client.shouldGetStats = YES;
153 _videoCallView.statsView.hidden = NO;
154}
155
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000156#pragma mark - Private
157
Zeke Chin57cc74e2015-05-05 07:52:31 -0700158- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
159 if (_localVideoTrack == localVideoTrack) {
160 return;
161 }
Zeke Chin57cc74e2015-05-05 07:52:31 -0700162 _localVideoTrack = nil;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700163 _localVideoTrack = localVideoTrack;
hayscedd8fef2015-12-08 11:08:39 -0800164 RTCAVFoundationVideoSource *source = nil;
165 if ([localVideoTrack.source
166 isKindOfClass:[RTCAVFoundationVideoSource class]]) {
167 source = (RTCAVFoundationVideoSource*)localVideoTrack.source;
168 }
169 _videoCallView.localVideoView.captureSession = source.captureSession;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700170}
171
172- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
173 if (_remoteVideoTrack == remoteVideoTrack) {
174 return;
175 }
hayscedd8fef2015-12-08 11:08:39 -0800176 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700177 _remoteVideoTrack = nil;
178 [_videoCallView.remoteVideoView renderFrame:nil];
179 _remoteVideoTrack = remoteVideoTrack;
180 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
181}
182
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000183- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700184 self.remoteVideoTrack = nil;
185 self.localVideoTrack = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000186 [_client disconnect];
tkchind2511962016-05-06 18:54:15 -0700187 [_delegate viewControllerDidFinish:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000188}
189
Zeke Chin57cc74e2015-05-05 07:52:31 -0700190- (void)switchCamera {
191 RTCVideoSource* source = self.localVideoTrack.source;
192 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
193 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
194 avSource.useBackCamera = !avSource.useBackCamera;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700195 }
196}
197
hjon79858f82016-03-13 22:08:26 -0700198- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000199 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700200 case RTCIceConnectionStateNew:
201 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000202 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700203 case RTCIceConnectionStateConnected:
204 case RTCIceConnectionStateCompleted:
205 case RTCIceConnectionStateFailed:
206 case RTCIceConnectionStateDisconnected:
207 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700208 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000209 return nil;
210 }
211}
212
213- (void)showAlertWithMessage:(NSString*)message {
214 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
215 message:message
216 delegate:nil
217 cancelButtonTitle:@"OK"
218 otherButtonTitles:nil];
219 [alertView show];
220}
221
222@end