blob: d919d75b114b075574c7560183e45048f57deef3 [file] [log] [blame]
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2015 Google Inc.
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#import "ARDVideoCallViewController.h"
29
Zeke Chin57cc74e2015-05-05 07:52:31 -070030#import "RTCAVFoundationVideoSource.h"
tkchinc3f46a92015-07-23 12:50:55 -070031#import "RTCLogging.h"
Zeke Chin57cc74e2015-05-05 07:52:31 -070032
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000033#import "ARDAppClient.h"
34#import "ARDVideoCallView.h"
35
36@interface ARDVideoCallViewController () <ARDAppClientDelegate,
37 ARDVideoCallViewDelegate>
Zeke Chin57cc74e2015-05-05 07:52:31 -070038@property(nonatomic, strong) RTCVideoTrack *localVideoTrack;
39@property(nonatomic, strong) RTCVideoTrack *remoteVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000040@property(nonatomic, readonly) ARDVideoCallView *videoCallView;
41@end
42
43@implementation ARDVideoCallViewController {
44 ARDAppClient *_client;
45 RTCVideoTrack *_remoteVideoTrack;
46 RTCVideoTrack *_localVideoTrack;
47}
48
49@synthesize videoCallView = _videoCallView;
50
51- (instancetype)initForRoom:(NSString *)room {
52 if (self = [super init]) {
53 _client = [[ARDAppClient alloc] initWithDelegate:self];
54 [_client connectToRoomWithId:room options:nil];
55 }
56 return self;
57}
58
59- (void)loadView {
60 _videoCallView = [[ARDVideoCallView alloc] initWithFrame:CGRectZero];
61 _videoCallView.delegate = self;
62 _videoCallView.statusLabel.text =
63 [self statusTextForState:RTCICEConnectionNew];
64 self.view = _videoCallView;
65}
66
67#pragma mark - ARDAppClientDelegate
68
69- (void)appClient:(ARDAppClient *)client
70 didChangeState:(ARDAppClientState)state {
71 switch (state) {
72 case kARDAppClientStateConnected:
tkchinc3f46a92015-07-23 12:50:55 -070073 RTCLog(@"Client connected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000074 break;
75 case kARDAppClientStateConnecting:
tkchinc3f46a92015-07-23 12:50:55 -070076 RTCLog(@"Client connecting.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000077 break;
78 case kARDAppClientStateDisconnected:
tkchinc3f46a92015-07-23 12:50:55 -070079 RTCLog(@"Client disconnected.");
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000080 [self hangup];
81 break;
82 }
83}
84
85- (void)appClient:(ARDAppClient *)client
86 didChangeConnectionState:(RTCICEConnectionState)state {
tkchinc3f46a92015-07-23 12:50:55 -070087 RTCLog(@"ICE state changed: %d", state);
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000088 __weak ARDVideoCallViewController *weakSelf = self;
89 dispatch_async(dispatch_get_main_queue(), ^{
90 ARDVideoCallViewController *strongSelf = weakSelf;
91 strongSelf.videoCallView.statusLabel.text =
92 [strongSelf statusTextForState:state];
93 });
94}
95
96- (void)appClient:(ARDAppClient *)client
97 didReceiveLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -070098 self.localVideoTrack = localVideoTrack;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000099}
100
101- (void)appClient:(ARDAppClient *)client
102 didReceiveRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700103 self.remoteVideoTrack = remoteVideoTrack;
104 _videoCallView.statusLabel.hidden = YES;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000105}
106
107- (void)appClient:(ARDAppClient *)client
108 didError:(NSError *)error {
109 NSString *message =
110 [NSString stringWithFormat:@"%@", error.localizedDescription];
111 [self showAlertWithMessage:message];
112 [self hangup];
113}
114
115#pragma mark - ARDVideoCallViewDelegate
116
117- (void)videoCallViewDidHangup:(ARDVideoCallView *)view {
118 [self hangup];
119}
120
Zeke Chin57cc74e2015-05-05 07:52:31 -0700121- (void)videoCallViewDidSwitchCamera:(ARDVideoCallView *)view {
122 // TODO(tkchin): Rate limit this so you can't tap continously on it.
123 // Probably through an animation.
124 [self switchCamera];
125}
126
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000127#pragma mark - Private
128
Zeke Chin57cc74e2015-05-05 07:52:31 -0700129- (void)setLocalVideoTrack:(RTCVideoTrack *)localVideoTrack {
130 if (_localVideoTrack == localVideoTrack) {
131 return;
132 }
133 [_localVideoTrack removeRenderer:_videoCallView.localVideoView];
134 _localVideoTrack = nil;
135 [_videoCallView.localVideoView renderFrame:nil];
136 _localVideoTrack = localVideoTrack;
137 [_localVideoTrack addRenderer:_videoCallView.localVideoView];
138}
139
140- (void)setRemoteVideoTrack:(RTCVideoTrack *)remoteVideoTrack {
141 if (_remoteVideoTrack == remoteVideoTrack) {
142 return;
143 }
144 [_remoteVideoTrack removeRenderer:_videoCallView.localVideoView];
145 _remoteVideoTrack = nil;
146 [_videoCallView.remoteVideoView renderFrame:nil];
147 _remoteVideoTrack = remoteVideoTrack;
148 [_remoteVideoTrack addRenderer:_videoCallView.remoteVideoView];
149}
150
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000151- (void)hangup {
Zeke Chin57cc74e2015-05-05 07:52:31 -0700152 self.remoteVideoTrack = nil;
153 self.localVideoTrack = nil;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000154 [_client disconnect];
Jon Hjelle2f65ac12015-06-12 11:33:45 -0700155 if (![self isBeingDismissed]) {
156 [self.presentingViewController dismissViewControllerAnimated:YES
157 completion:nil];
158 }
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000159}
160
Zeke Chin57cc74e2015-05-05 07:52:31 -0700161- (void)switchCamera {
162 RTCVideoSource* source = self.localVideoTrack.source;
163 if ([source isKindOfClass:[RTCAVFoundationVideoSource class]]) {
164 RTCAVFoundationVideoSource* avSource = (RTCAVFoundationVideoSource*)source;
165 avSource.useBackCamera = !avSource.useBackCamera;
166 _videoCallView.localVideoView.transform = avSource.useBackCamera ?
167 CGAffineTransformIdentity : CGAffineTransformMakeScale(-1, 1);
168 }
169}
170
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000171- (NSString *)statusTextForState:(RTCICEConnectionState)state {
172 switch (state) {
173 case RTCICEConnectionNew:
174 case RTCICEConnectionChecking:
175 return @"Connecting...";
176 case RTCICEConnectionConnected:
177 case RTCICEConnectionCompleted:
178 case RTCICEConnectionFailed:
179 case RTCICEConnectionDisconnected:
180 case RTCICEConnectionClosed:
181 return nil;
182 }
183}
184
185- (void)showAlertWithMessage:(NSString*)message {
186 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil
187 message:message
188 delegate:nil
189 cancelButtonTitle:@"OK"
190 otherButtonTitles:nil];
191 [alertView show];
192}
193
194@end