blob: fae3f7b8aa7267c6db45bef262ed9b3560c6b20d [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
Anders Carlsson7bca8ca2018-08-30 09:30:29 +020015#import <WebRTC/RTCAudioSession.h>
16#import <WebRTC/RTCAudioSessionConfiguration.h>
17#import <WebRTC/RTCDispatcher.h>
18#import <WebRTC/RTCLogging.h>
Tze Kwang Chin307a0922016-03-21 13:57:40 -070019
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000020#import "ARDAppClient.h"
21#import "ARDMainView.h"
denicija2256e042016-11-09 06:26:18 -080022#import "ARDSettingsModel.h"
denicijad17d5362016-11-02 02:56:09 -070023#import "ARDSettingsViewController.h"
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000024#import "ARDVideoCallViewController.h"
25
denicijad17d5362016-11-02 02:56:09 -070026static NSString *const barButtonImageString = @"ic_settings_black_24dp.png";
denicija6d6762c2016-10-28 04:53:16 -070027
denicija5db450d2017-03-28 08:27:41 -070028// Launch argument to be passed to indicate that the app should start loopback immediatly
29static NSString *const loopbackLaunchProcessArgument = @"loopback";
30
Tze Kwang Chin307a0922016-03-21 13:57:40 -070031@interface ARDMainViewController () <
32 ARDMainViewDelegate,
tkchind2511962016-05-06 18:54:15 -070033 ARDVideoCallViewControllerDelegate,
Tze Kwang Chin307a0922016-03-21 13:57:40 -070034 RTCAudioSessionDelegate>
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000035@end
36
Tze Kwang Chin307a0922016-03-21 13:57:40 -070037@implementation ARDMainViewController {
38 ARDMainView *_mainView;
39 AVAudioPlayer *_audioPlayer;
tkchind2511962016-05-06 18:54:15 -070040 BOOL _useManualAudio;
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000041}
42
denicija5db450d2017-03-28 08:27:41 -070043- (void)viewDidLoad {
44 [super viewDidLoad];
45 if ([[[NSProcessInfo processInfo] arguments] containsObject:loopbackLaunchProcessArgument]) {
Anders Carlssone1500582017-06-15 16:05:13 +020046 [self mainView:nil didInputRoom:@"" isLoopback:YES];
denicija5db450d2017-03-28 08:27:41 -070047 }
48}
49
Tze Kwang Chin307a0922016-03-21 13:57:40 -070050- (void)loadView {
denicija6d6762c2016-10-28 04:53:16 -070051 self.title = @"AppRTC Mobile";
Tze Kwang Chin307a0922016-03-21 13:57:40 -070052 _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero];
53 _mainView.delegate = self;
54 self.view = _mainView;
denicija6d6762c2016-10-28 04:53:16 -070055 [self addSettingsBarButton];
Tze Kwang Chin307a0922016-03-21 13:57:40 -070056
tkchind2511962016-05-06 18:54:15 -070057 RTCAudioSessionConfiguration *webRTCConfig =
58 [RTCAudioSessionConfiguration webRTCConfiguration];
59 webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
60 AVAudioSessionCategoryOptionDefaultToSpeaker;
61 [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig];
62
63 RTCAudioSession *session = [RTCAudioSession sharedInstance];
64 [session addDelegate:self];
65
66 [self configureAudioSession];
Tze Kwang Chin307a0922016-03-21 13:57:40 -070067 [self setupAudioPlayer];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000068}
69
denicija6d6762c2016-10-28 04:53:16 -070070- (void)addSettingsBarButton {
71 UIBarButtonItem *settingsButton =
72 [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:barButtonImageString]
73 style:UIBarButtonItemStylePlain
74 target:self
75 action:@selector(showSettings:)];
76 self.navigationItem.rightBarButtonItem = settingsButton;
77}
78
denicija5db450d2017-03-28 08:27:41 -070079+ (NSString *)loopbackRoomString {
80 NSString *loopbackRoomString =
81 [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""];
82 return loopbackRoomString;
83}
84
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000085#pragma mark - ARDMainViewDelegate
86
Anders Carlssone1500582017-06-15 16:05:13 +020087- (void)mainView:(ARDMainView *)mainView didInputRoom:(NSString *)room isLoopback:(BOOL)isLoopback {
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000088 if (!room.length) {
denicija5db450d2017-03-28 08:27:41 -070089 if (isLoopback) {
90 // If this is a loopback call, allow a generated room name.
91 room = [[self class] loopbackRoomString];
92 } else {
93 [self showAlertWithMessage:@"Missing room name."];
94 return;
95 }
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +000096 }
97 // Trim whitespaces.
98 NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
99 NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet];
100
101 // Check that room name is valid.
102 NSError *error = nil;
103 NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive;
104 NSRegularExpression *regex =
105 [NSRegularExpression regularExpressionWithPattern:@"\\w+"
106 options:options
107 error:&error];
108 if (error) {
109 [self showAlertWithMessage:error.localizedDescription];
110 return;
111 }
112 NSRange matchRange =
113 [regex rangeOfFirstMatchInString:trimmedRoom
114 options:0
115 range:NSMakeRange(0, trimmedRoom.length)];
116 if (matchRange.location == NSNotFound ||
117 matchRange.length != trimmedRoom.length) {
118 [self showAlertWithMessage:@"Invalid room name."];
119 return;
120 }
121
Anders Carlssone1500582017-06-15 16:05:13 +0200122 ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
123
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700124 RTCAudioSession *session = [RTCAudioSession sharedInstance];
Anders Carlssone1500582017-06-15 16:05:13 +0200125 session.useManualAudio = [settingsModel currentUseManualAudioConfigSettingFromStore];
tkchind2511962016-05-06 18:54:15 -0700126 session.isAudioEnabled = NO;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700127
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000128 // Kick off the video call.
129 ARDVideoCallViewController *videoCallViewController =
haysc913e6452015-10-02 11:44:03 -0700130 [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom
131 isLoopback:isLoopback
tkchind2511962016-05-06 18:54:15 -0700132 delegate:self];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000133 videoCallViewController.modalTransitionStyle =
134 UIModalTransitionStyleCrossDissolve;
135 [self presentViewController:videoCallViewController
136 animated:YES
137 completion:nil];
138}
139
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700140- (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView {
141 if (mainView.isAudioLoopPlaying) {
142 [_audioPlayer stop];
143 } else {
144 [_audioPlayer play];
145 }
146 mainView.isAudioLoopPlaying = _audioPlayer.playing;
147}
148
tkchind2511962016-05-06 18:54:15 -0700149#pragma mark - ARDVideoCallViewControllerDelegate
150
151- (void)viewControllerDidFinish:(ARDVideoCallViewController *)viewController {
152 if (![viewController isBeingDismissed]) {
153 RTCLog(@"Dismissing VC");
154 [self dismissViewControllerAnimated:YES completion:^{
155 [self restartAudioPlayerIfNeeded];
156 }];
157 }
158 RTCAudioSession *session = [RTCAudioSession sharedInstance];
159 session.isAudioEnabled = NO;
160}
161
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700162#pragma mark - RTCAudioSessionDelegate
163
tkchind2511962016-05-06 18:54:15 -0700164- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700165 // Stop playback on main queue and then configure WebRTC.
166 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain
167 block:^{
168 if (_mainView.isAudioLoopPlaying) {
169 RTCLog(@"Stopping audio loop due to WebRTC start.");
170 [_audioPlayer stop];
171 }
tkchind2511962016-05-06 18:54:15 -0700172 RTCLog(@"Setting isAudioEnabled to YES.");
173 session.isAudioEnabled = YES;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700174 }];
175}
176
tkchind2511962016-05-06 18:54:15 -0700177- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700178 // WebRTC is done with the audio session. Restart playback.
179 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain
180 block:^{
tkchind2511962016-05-06 18:54:15 -0700181 RTCLog(@"audioSessionDidStopPlayOrRecord");
182 [self restartAudioPlayerIfNeeded];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700183 }];
184}
185
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000186#pragma mark - Private
denicija6d6762c2016-10-28 04:53:16 -0700187- (void)showSettings:(id)sender {
denicijad17d5362016-11-02 02:56:09 -0700188 ARDSettingsViewController *settingsController =
denicijab04b5c22016-11-09 04:28:46 -0800189 [[ARDSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped
denicija2256e042016-11-09 06:26:18 -0800190 settingsModel:[[ARDSettingsModel alloc] init]];
191
denicijad17d5362016-11-02 02:56:09 -0700192 UINavigationController *navigationController =
193 [[UINavigationController alloc] initWithRootViewController:settingsController];
194 [self presentViewControllerAsModal:navigationController];
195}
196
197- (void)presentViewControllerAsModal:(UIViewController *)viewController {
198 [self presentViewController:viewController animated:YES completion:nil];
denicija6d6762c2016-10-28 04:53:16 -0700199}
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000200
tkchind2511962016-05-06 18:54:15 -0700201- (void)configureAudioSession {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700202 RTCAudioSessionConfiguration *configuration =
203 [[RTCAudioSessionConfiguration alloc] init];
204 configuration.category = AVAudioSessionCategoryAmbient;
205 configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers;
206 configuration.mode = AVAudioSessionModeDefault;
207
208 RTCAudioSession *session = [RTCAudioSession sharedInstance];
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700209 [session lockForConfiguration];
tkchind2511962016-05-06 18:54:15 -0700210 BOOL hasSucceeded = NO;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700211 NSError *error = nil;
tkchind2511962016-05-06 18:54:15 -0700212 if (session.isActive) {
213 hasSucceeded = [session setConfiguration:configuration error:&error];
214 } else {
215 hasSucceeded = [session setConfiguration:configuration
216 active:YES
217 error:&error];
218 }
219 if (!hasSucceeded) {
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700220 RTCLogError(@"Error setting configuration: %@", error.localizedDescription);
221 }
222 [session unlockForConfiguration];
223}
224
225- (void)setupAudioPlayer {
226 NSString *audioFilePath =
227 [[NSBundle mainBundle] pathForResource:@"mozart" ofType:@"mp3"];
228 NSURL *audioFileURL = [NSURL URLWithString:audioFilePath];
229 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL
230 error:nil];
231 _audioPlayer.numberOfLoops = -1;
232 _audioPlayer.volume = 1.0;
233 [_audioPlayer prepareToPlay];
234}
235
tkchind2511962016-05-06 18:54:15 -0700236- (void)restartAudioPlayerIfNeeded {
Anders Carlsson30593782017-06-22 14:27:27 +0200237 [self configureAudioSession];
tkchind2511962016-05-06 18:54:15 -0700238 if (_mainView.isAudioLoopPlaying && !self.presentedViewController) {
239 RTCLog(@"Starting audio loop due to WebRTC end.");
tkchind2511962016-05-06 18:54:15 -0700240 [_audioPlayer play];
241 }
242}
243
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000244- (void)showAlertWithMessage:(NSString*)message {
kthelgasonb13237b2017-03-30 04:56:05 -0700245 UIAlertController *alert =
246 [UIAlertController alertControllerWithTitle:nil
247 message:message
248 preferredStyle:UIAlertControllerStyleAlert];
249
250 UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK"
251 style:UIAlertActionStyleDefault
252 handler:^(UIAlertAction *action){
253 }];
254
255 [alert addAction:defaultAction];
256 [self presentViewController:alert animated:YES completion:nil];
tkchin@webrtc.orgef2a5dd2015-01-15 22:38:21 +0000257}
258
259@end