blob: 174514ff1872d83d934232aba56a179f34cf34b2 [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 "ARDMainViewController.h"
12
Tze Kwang Chin307a0922016-03-21 13:57:40 -070013#import <AVFoundation/AVFoundation.h>
14
denicija59ee91b2017-06-05 05:48:47 -070015#import "WebRTC/RTCAudioSession.h"
16#import "WebRTC/RTCAudioSessionConfiguration.h"
tkchin9eeb6242016-04-27 01:54:20 -070017#import "WebRTC/RTCDispatcher.h"
18#import "WebRTC/RTCLogging.h"
denicija59ee91b2017-06-05 05:48:47 -070019
Tze Kwang Chin307a0922016-03-21 13:57:40 -070020
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000021#import "ARDAppClient.h"
22#import "ARDMainView.h"
denicija2256e042016-11-09 06:26:18 -080023#import "ARDSettingsModel.h"
denicijad17d5362016-11-02 02:56:09 -070024#import "ARDSettingsViewController.h"
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000025#import "ARDVideoCallViewController.h"
26
denicijad17d5362016-11-02 02:56:09 -070027static NSString *const barButtonImageString = @"ic_settings_black_24dp.png";
denicija6d6762c2016-10-28 04:53:16 -070028
denicija5db450d2017-03-28 08:27:41 -070029// Launch argument to be passed to indicate that the app should start loopback immediatly
30static NSString *const loopbackLaunchProcessArgument = @"loopback";
31
Tze Kwang Chin307a0922016-03-21 13:57:40 -070032@interface ARDMainViewController () <
33 ARDMainViewDelegate,
tkchind2511962016-05-06 18:54:15 -070034 ARDVideoCallViewControllerDelegate,
Tze Kwang Chin307a0922016-03-21 13:57:40 -070035 RTCAudioSessionDelegate>
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000036@end
37
Tze Kwang Chin307a0922016-03-21 13:57:40 -070038@implementation ARDMainViewController {
39 ARDMainView *_mainView;
40 AVAudioPlayer *_audioPlayer;
tkchind2511962016-05-06 18:54:15 -070041 BOOL _useManualAudio;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000042}
43
denicija5db450d2017-03-28 08:27:41 -070044- (void)viewDidLoad {
45 [super viewDidLoad];
46 if ([[[NSProcessInfo processInfo] arguments] containsObject:loopbackLaunchProcessArgument]) {
Anders Carlssone1500582017-06-15 16:05:13 +020047 [self mainView:nil didInputRoom:@"" isLoopback:YES];
denicija5db450d2017-03-28 08:27:41 -070048 }
49}
50
Tze Kwang Chin307a0922016-03-21 13:57:40 -070051- (void)loadView {
denicija6d6762c2016-10-28 04:53:16 -070052 self.title = @"AppRTC Mobile";
Tze Kwang Chin307a0922016-03-21 13:57:40 -070053 _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero];
54 _mainView.delegate = self;
55 self.view = _mainView;
denicija6d6762c2016-10-28 04:53:16 -070056 [self addSettingsBarButton];
Tze Kwang Chin307a0922016-03-21 13:57:40 -070057
tkchind2511962016-05-06 18:54:15 -070058 RTCAudioSessionConfiguration *webRTCConfig =
59 [RTCAudioSessionConfiguration webRTCConfiguration];
60 webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
61 AVAudioSessionCategoryOptionDefaultToSpeaker;
62 [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig];
63
64 RTCAudioSession *session = [RTCAudioSession sharedInstance];
65 [session addDelegate:self];
66
67 [self configureAudioSession];
Tze Kwang Chin307a0922016-03-21 13:57:40 -070068 [self setupAudioPlayer];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000069}
70
denicija6d6762c2016-10-28 04:53:16 -070071- (void)addSettingsBarButton {
72 UIBarButtonItem *settingsButton =
73 [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:barButtonImageString]
74 style:UIBarButtonItemStylePlain
75 target:self
76 action:@selector(showSettings:)];
77 self.navigationItem.rightBarButtonItem = settingsButton;
78}
79
denicija5db450d2017-03-28 08:27:41 -070080+ (NSString *)loopbackRoomString {
81 NSString *loopbackRoomString =
82 [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""];
83 return loopbackRoomString;
84}
85
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000086#pragma mark - ARDMainViewDelegate
87
Anders Carlssone1500582017-06-15 16:05:13 +020088- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room isLoopback:(BOOL)isLoopback {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000089 if (!room.length) {
denicija5db450d2017-03-28 08:27:41 -070090 if (isLoopback) {
91 // If this is a loopback call, allow a generated room name.
92 room = [[self class] loopbackRoomString];
93 } else {
94 [self showAlertWithMessage:@"Missing room name."];
95 return;
96 }
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000097 }
98 // Trim whitespaces.
99 NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
100 NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet];
101
102 // Check that room name is valid.
103 NSError *error = nil;
104 NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive;
105 NSRegularExpression *regex =
106 [NSRegularExpression regularExpressionWithPattern:@"\\w+"
107 options:options
108 error:&error];
109 if (error) {
110 [self showAlertWithMessage:error.localizedDescription];
111 return;
112 }
113 NSRange matchRange =
114 [regex rangeOfFirstMatchInString:trimmedRoom
115 options:0
116 range:NSMakeRange(0, trimmedRoom.length)];
117 if (matchRange.location == NSNotFound ||
118 matchRange.length != trimmedRoom.length) {
119 [self showAlertWithMessage:@"Invalid room name."];
120 return;
121 }
122
Anders Carlssone1500582017-06-15 16:05:13 +0200123 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
124
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700125 RTCAudioSession *session = [RTCAudioSession sharedInstance];
Anders Carlssone1500582017-06-15 16:05:13 +0200126 session.useManualAudio = [settingsModel currentUseManualAudioConfigSettingFromStore];
tkchind2511962016-05-06 18:54:15 -0700127 session.isAudioEnabled = NO;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700128
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000129 // Kick off the video call.
130 ARDVideoCallViewController *videoCallViewController =
haysc913e6452015-10-02 11:44:03 -0700131 [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom
132 isLoopback:isLoopback
tkchind2511962016-05-06 18:54:15 -0700133 delegate:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000134 videoCallViewController.modalTransitionStyle =
135 UIModalTransitionStyleCrossDissolve;
136 [self presentViewController:videoCallViewController
137 animated:YES
138 completion:nil];
139}
140
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700141- (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView {
142 if (mainView.isAudioLoopPlaying) {
143 [_audioPlayer stop];
144 } else {
145 [_audioPlayer play];
146 }
147 mainView.isAudioLoopPlaying = _audioPlayer.playing;
148}
149
tkchind2511962016-05-06 18:54:15 -0700150#pragma mark - ARDVideoCallViewControllerDelegate
151
152- (void)viewControllerDidFinish:(ARDVideoCallViewController *)viewController {
153 if (![viewController isBeingDismissed]) {
154 RTCLog(@"Dismissing VC");
155 [self dismissViewControllerAnimated:YES completion:^{
156 [self restartAudioPlayerIfNeeded];
157 }];
158 }
159 RTCAudioSession *session = [RTCAudioSession sharedInstance];
160 session.isAudioEnabled = NO;
161}
162
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700163#pragma mark - RTCAudioSessionDelegate
164
tkchind2511962016-05-06 18:54:15 -0700165- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700166 // Stop playback on main queue and then configure WebRTC.
167 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain
168 block:^{
169 if (_mainView.isAudioLoopPlaying) {
170 RTCLog(@"Stopping audio loop due to WebRTC start.");
171 [_audioPlayer stop];
172 }
tkchind2511962016-05-06 18:54:15 -0700173 RTCLog(@"Setting isAudioEnabled to YES.");
174 session.isAudioEnabled = YES;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700175 }];
176}
177
tkchind2511962016-05-06 18:54:15 -0700178- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700179 // WebRTC is done with the audio session. Restart playback.
180 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain
181 block:^{
tkchind2511962016-05-06 18:54:15 -0700182 RTCLog(@"audioSessionDidStopPlayOrRecord");
183 [self restartAudioPlayerIfNeeded];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700184 }];
185}
186
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000187#pragma mark - Private
denicija6d6762c2016-10-28 04:53:16 -0700188- (void)showSettings:(id)sender {
denicijad17d5362016-11-02 02:56:09 -0700189 ARDSettingsViewController *settingsController =
denicijab04b5c22016-11-09 04:28:46 -0800190 [[ARDSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped
denicija2256e042016-11-09 06:26:18 -0800191 settingsModel:[[ARDSettingsModel alloc] init]];
192
denicijad17d5362016-11-02 02:56:09 -0700193 UINavigationController *navigationController =
194 [[UINavigationController alloc] initWithRootViewController:settingsController];
195 [self presentViewControllerAsModal:navigationController];
196}
197
198- (void)presentViewControllerAsModal:(UIViewController *)viewController {
199 [self presentViewController:viewController animated:YES completion:nil];
denicija6d6762c2016-10-28 04:53:16 -0700200}
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000201
tkchind2511962016-05-06 18:54:15 -0700202- (void)configureAudioSession {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700203 RTCAudioSessionConfiguration *configuration =
204 [[RTCAudioSessionConfiguration alloc] init];
205 configuration.category = AVAudioSessionCategoryAmbient;
206 configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers;
207 configuration.mode = AVAudioSessionModeDefault;
208
209 RTCAudioSession *session = [RTCAudioSession sharedInstance];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700210 [session lockForConfiguration];
tkchind2511962016-05-06 18:54:15 -0700211 BOOL hasSucceeded = NO;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700212 NSError *error = nil;
tkchind2511962016-05-06 18:54:15 -0700213 if (session.isActive) {
214 hasSucceeded = [session setConfiguration:configuration error:&error];
215 } else {
216 hasSucceeded = [session setConfiguration:configuration
217 active:YES
218 error:&error];
219 }
220 if (!hasSucceeded) {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700221 RTCLogError(@"Error setting configuration: %@", error.localizedDescription);
222 }
223 [session unlockForConfiguration];
224}
225
226- (void)setupAudioPlayer {
227 NSString *audioFilePath =
228 [[NSBundle mainBundle] pathForResource:@"mozart" ofType:@"mp3"];
229 NSURL *audioFileURL = [NSURL URLWithString:audioFilePath];
230 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL
231 error:nil];
232 _audioPlayer.numberOfLoops = -1;
233 _audioPlayer.volume = 1.0;
234 [_audioPlayer prepareToPlay];
235}
236
tkchind2511962016-05-06 18:54:15 -0700237- (void)restartAudioPlayerIfNeeded {
Anders Carlsson30593782017-06-22 14:27:27 +0200238 [self configureAudioSession];
tkchind2511962016-05-06 18:54:15 -0700239 if (_mainView.isAudioLoopPlaying && !self.presentedViewController) {
240 RTCLog(@"Starting audio loop due to WebRTC end.");
tkchind2511962016-05-06 18:54:15 -0700241 [_audioPlayer play];
242 }
243}
244
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000245- (void)showAlertWithMessage:(NSString*)message {
kthelgasonb13237b2017-03-30 04:56:05 -0700246 UIAlertController *alert =
247 [UIAlertController alertControllerWithTitle:nil
248 message:message
249 preferredStyle:UIAlertControllerStyleAlert];
250
251 UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
252 style:UIAlertActionStyleDefault
253 handler:^(UIAlertAction *action){
254 }];
255
256 [alert addAction:defaultAction];
257 [self presentViewController:alert animated:YES completion:nil];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000258}
259
260@end