blob: b8786773038954f9c61aafd463fe2f876fcc5445 [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/base/objc/RTCDispatcher.h"
14#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
15
hjon79858f82016-03-13 22:08:26 -070016#import "webrtc/api/objc/RTCAVFoundationVideoSource.h"
17#import "webrtc/base/objc/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;
37
haysc913e6452015-10-02 11:44:03 -070038- (instancetype)initForRoom:(NSString *)room
39 isLoopback:(BOOL)isLoopback
40 isAudioOnly:(BOOL)isAudioOnly {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000041 if (self = [super init]) {
42 _client = [[ARDAppClient alloc] initWithDelegate:self];
haysc913e6452015-10-02 11:44:03 -070043 [_client connectToRoomWithId:room
44 isLoopback:isLoopback
45 isAudioOnly:isAudioOnly];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000046 }
47 return self;
48}
49
50- (void)loadView {
51 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
52 _videoCallView.delegate = self;
53 _videoCallView.statusLabel.text =
hjon79858f82016-03-13 22:08:26 -070054 [self statusTextForState:RTCIceConnectionStateNew];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000055 self.view = _videoCallView;
56}
57
58#pragma mark - ARDAppClientDelegate
59
60- (void)appClient:(ARDAppClient *)client
61 didChangeState:(ARDAppClientState)state {
62 switch (state) {
63 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070064 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000065 break;
66 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070067 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000068 break;
69 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070070 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000071 [self hangup];
72 break;
73 }
74}
75
76- (void)appClient:(ARDAppClient *)client
hjon79858f82016-03-13 22:08:26 -070077 didChangeConnectionState:(RTCIceConnectionState)state {
78 RTCLog(@"ICE state changed: %ld", (long)state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000079 __weak ARDVideoCallViewController *weakSelf = self;
80 dispatch_async(dispatch_get_main_queue(), ^{
81 ARDVideoCallViewController *strongSelf = weakSelf;
82 strongSelf.videoCallView.statusLabel.text =
83 [strongSelf statusTextForState:state];
84 });
85}
86
87- (void)appClient:(ARDAppClient *)client
88 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -070089 self.localVideoTrack = localVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000090}
91
92- (void)appClient:(ARDAppClient *)client
93 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -070094 self.remoteVideoTrack = remoteVideoTrack;
95 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000096}
97
98- (void)appClient:(ARDAppClient *)client
Zeke Chind3325802015-08-14 11:00:02 -070099 didGetStats:(NSArray *)stats {
100 _videoCallView.statsView.stats = stats;
101 [_videoCallView setNeedsLayout];
102}
103
104- (void)appClient:(ARDAppClient *)client
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000105 didError:(NSError *)error {
106 NSString *message =
107 [NSString stringWithFormat:@"%@", error.localizedDescription];
108 [self showAlertWithMessage:message];
109 [self hangup];
110}
111
112#pragma mark - ARDVideoCallViewDelegate
113
114- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
115 [self hangup];
116}
117
Zeke Chin57cc74e2015-05-05 07:52:31 -0700118- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
119 // TODO(tkchin): Rate limit this so you can't tap continously on it.
120 // Probably through an animation.
121 [self switchCamera];
122}
123
tkchin0ce3bf92016-03-12 16:52:04 -0800124- (void)videoCallViewDidChangeRoute:(ARDVideoCallView *)view {
125 AVAudioSessionPortOverride override = AVAudioSessionPortOverrideNone;
126 if (_portOverride == AVAudioSessionPortOverrideNone) {
127 override = AVAudioSessionPortOverrideSpeaker;
128 }
129 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeAudioSession
130 block:^{
131 RTCAudioSession *session = [RTCAudioSession sharedInstance];
132 [session lockForConfiguration];
133 NSError *error = nil;
134 if ([session overrideOutputAudioPort:override error:&error]) {
135 _portOverride = override;
136 } else {
137 RTCLogError(@"Error overriding output port: %@",
138 error.localizedDescription);
139 }
140 [session unlockForConfiguration];
141 }];
142}
143
Zeke Chind3325802015-08-14 11:00:02 -0700144- (void)videoCallViewDidEnableStats:(ARDVideoCallView *)view {
145 _client.shouldGetStats = YES;
146 _videoCallView.statsView.hidden = NO;
147}
148
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000149#pragma mark - Private
150
Zeke Chin57cc74e2015-05-05 07:52:31 -0700151- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
152 if (_localVideoTrack == localVideoTrack) {
153 return;
154 }
Zeke Chin57cc74e2015-05-05 07:52:31 -0700155 _localVideoTrack = nil;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700156 _localVideoTrack = localVideoTrack;
hayscedd8fef2015-12-08 11:08:39 -0800157 RTCAVFoundationVideoSource *source = nil;
158 if ([localVideoTrack.source
159 isKindOfClass:[RTCAVFoundationVideoSource class]]) {
160 source = (RTCAVFoundationVideoSource*)localVideoTrack.source;
161 }
162 _videoCallView.localVideoView.captureSession = source.captureSession;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700163}
164
165- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
166 if (_remoteVideoTrack == remoteVideoTrack) {
167 return;
168 }
hayscedd8fef2015-12-08 11:08:39 -0800169 [_remoteVideoTrack removeRenderer:_videoCallView.remoteVideoView];
Zeke Chin57cc74e2015-05-05 07:52:31 -0700170 _remoteVideoTrack = nil;
171 [_videoCallView.remoteVideoView renderFrame:nil];
172 _remoteVideoTrack = remoteVideoTrack;
173 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
174}
175
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000176- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700177 self.remoteVideoTrack = nil;
178 self.localVideoTrack = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000179 [_client disconnect];
Jon Hjelle2f65ac12015-06-12 11:33:45 -0700180 if (![self isBeingDismissed]) {
181 [self.presentingViewController dismissViewControllerAnimated:YES
182 completion:nil];
183 }
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000184}
185
Zeke Chin57cc74e2015-05-05 07:52:31 -0700186- (void)switchCamera {
187 RTCVideoSource* source = self.localVideoTrack.source;
188 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
189 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
190 avSource.useBackCamera = !avSource.useBackCamera;
Zeke Chin57cc74e2015-05-05 07:52:31 -0700191 }
192}
193
hjon79858f82016-03-13 22:08:26 -0700194- (NSString *)statusTextForState:(RTCIceConnectionState)state {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000195 switch (state) {
hjon79858f82016-03-13 22:08:26 -0700196 case RTCIceConnectionStateNew:
197 case RTCIceConnectionStateChecking:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000198 return @"Connecting...";
hjon79858f82016-03-13 22:08:26 -0700199 case RTCIceConnectionStateConnected:
200 case RTCIceConnectionStateCompleted:
201 case RTCIceConnectionStateFailed:
202 case RTCIceConnectionStateDisconnected:
203 case RTCIceConnectionStateClosed:
hjon8bbbf2c2016-03-14 13:15:44 -0700204 case RTCIceConnectionStateCount:
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000205 return nil;
206 }
207}
208
209- (void)showAlertWithMessage:(NSString*)message {
210 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
211 message:message
212 delegate:nil
213 cancelButtonTitle:@"OK"
214 otherButtonTitles:nil];
215 [alertView show];
216}
217
218@end