| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * 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. | |
| 9 */ | |
| 10 | |
| 11 #import "ARDMainViewController.h" | |
| 12 | |
| 13 #import <AVFoundation/AVFoundation.h> | |
| 14 | |
| 15 #import "WebRTC/RTCDispatcher.h" | |
| 16 #import "WebRTC/RTCLogging.h" | |
| 17 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" | |
| 18 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" | |
| 19 | |
| 20 #import "ARDAppClient.h" | |
| 21 #import "ARDMainView.h" | |
| 22 #import "ARDVideoCallViewController.h" | |
| 23 | |
| 24 @interface ARDMainViewController () < | |
| 25 ARDMainViewDelegate, | |
| 26 ARDVideoCallViewControllerDelegate, | |
| 27 RTCAudioSessionDelegate> | |
| 28 @end | |
| 29 | |
| 30 @implementation ARDMainViewController { | |
| 31 ARDMainView *_mainView; | |
| 32 AVAudioPlayer *_audioPlayer; | |
| 33 BOOL _useManualAudio; | |
| 34 } | |
| 35 | |
| 36 - (void)loadView { | |
| 37 _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero]; | |
| 38 _mainView.delegate = self; | |
| 39 self.view = _mainView; | |
| 40 | |
| 41 RTCAudioSessionConfiguration *webRTCConfig = | |
| 42 [RTCAudioSessionConfiguration webRTCConfiguration]; | |
| 43 webRTCConfig.categoryOptions = webRTCConfig.categoryOptions | | |
| 44 AVAudioSessionCategoryOptionDefaultToSpeaker; | |
| 45 [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig]; | |
| 46 | |
| 47 RTCAudioSession *session = [RTCAudioSession sharedInstance]; | |
| 48 [session addDelegate:self]; | |
| 49 | |
| 50 [self configureAudioSession]; | |
| 51 [self setupAudioPlayer]; | |
| 52 } | |
| 53 | |
| 54 #pragma mark - ARDMainViewDelegate | |
| 55 | |
| 56 - (void)mainView:(ARDMainView *)mainView | |
| 57 didInputRoom:(NSString *)room | |
| 58 isLoopback:(BOOL)isLoopback | |
| 59 isAudioOnly:(BOOL)isAudioOnly | |
| 60 shouldMakeAecDump:(BOOL)shouldMakeAecDump | |
| 61 shouldUseLevelControl:(BOOL)shouldUseLevelControl | |
| 62 useManualAudio:(BOOL)useManualAudio { | |
| 63 if (!room.length) { | |
| 64 [self showAlertWithMessage:@"Missing room name."]; | |
| 65 return; | |
| 66 } | |
| 67 // Trim whitespaces. | |
| 68 NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet]; | |
| 69 NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet]; | |
| 70 | |
| 71 // Check that room name is valid. | |
| 72 NSError *error = nil; | |
| 73 NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive; | |
| 74 NSRegularExpression *regex = | |
| 75 [NSRegularExpression regularExpressionWithPattern:@"\\w+" | |
| 76 options:options | |
| 77 error:&error]; | |
| 78 if (error) { | |
| 79 [self showAlertWithMessage:error.localizedDescription]; | |
| 80 return; | |
| 81 } | |
| 82 NSRange matchRange = | |
| 83 [regex rangeOfFirstMatchInString:trimmedRoom | |
| 84 options:0 | |
| 85 range:NSMakeRange(0, trimmedRoom.length)]; | |
| 86 if (matchRange.location == NSNotFound || | |
| 87 matchRange.length != trimmedRoom.length) { | |
| 88 [self showAlertWithMessage:@"Invalid room name."]; | |
| 89 return; | |
| 90 } | |
| 91 | |
| 92 RTCAudioSession *session = [RTCAudioSession sharedInstance]; | |
| 93 session.useManualAudio = useManualAudio; | |
| 94 session.isAudioEnabled = NO; | |
| 95 | |
| 96 // Kick off the video call. | |
| 97 ARDVideoCallViewController *videoCallViewController = | |
| 98 [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom | |
| 99 isLoopback:isLoopback | |
| 100 isAudioOnly:isAudioOnly | |
| 101 shouldMakeAecDump:shouldMakeAecDump | |
| 102 shouldUseLevelControl:shouldUseLevelControl | |
| 103 delegate:self]; | |
| 104 videoCallViewController.modalTransitionStyle = | |
| 105 UIModalTransitionStyleCrossDissolve; | |
| 106 [self presentViewController:videoCallViewController | |
| 107 animated:YES | |
| 108 completion:nil]; | |
| 109 } | |
| 110 | |
| 111 - (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView { | |
| 112 if (mainView.isAudioLoopPlaying) { | |
| 113 [_audioPlayer stop]; | |
| 114 } else { | |
| 115 [_audioPlayer play]; | |
| 116 } | |
| 117 mainView.isAudioLoopPlaying = _audioPlayer.playing; | |
| 118 } | |
| 119 | |
| 120 #pragma mark - ARDVideoCallViewControllerDelegate | |
| 121 | |
| 122 - (void)viewControllerDidFinish:(ARDVideoCallViewController *)viewController { | |
| 123 if (![viewController isBeingDismissed]) { | |
| 124 RTCLog(@"Dismissing VC"); | |
| 125 [self dismissViewControllerAnimated:YES completion:^{ | |
| 126 [self restartAudioPlayerIfNeeded]; | |
| 127 }]; | |
| 128 } | |
| 129 RTCAudioSession *session = [RTCAudioSession sharedInstance]; | |
| 130 session.isAudioEnabled = NO; | |
| 131 } | |
| 132 | |
| 133 #pragma mark - RTCAudioSessionDelegate | |
| 134 | |
| 135 - (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session { | |
| 136 // Stop playback on main queue and then configure WebRTC. | |
| 137 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain | |
| 138 block:^{ | |
| 139 if (_mainView.isAudioLoopPlaying) { | |
| 140 RTCLog(@"Stopping audio loop due to WebRTC start."); | |
| 141 [_audioPlayer stop]; | |
| 142 } | |
| 143 RTCLog(@"Setting isAudioEnabled to YES."); | |
| 144 session.isAudioEnabled = YES; | |
| 145 }]; | |
| 146 } | |
| 147 | |
| 148 - (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session { | |
| 149 // WebRTC is done with the audio session. Restart playback. | |
| 150 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain | |
| 151 block:^{ | |
| 152 RTCLog(@"audioSessionDidStopPlayOrRecord"); | |
| 153 [self restartAudioPlayerIfNeeded]; | |
| 154 }]; | |
| 155 } | |
| 156 | |
| 157 #pragma mark - Private | |
| 158 | |
| 159 - (void)configureAudioSession { | |
| 160 RTCAudioSessionConfiguration *configuration = | |
| 161 [[RTCAudioSessionConfiguration alloc] init]; | |
| 162 configuration.category = AVAudioSessionCategoryAmbient; | |
| 163 configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers; | |
| 164 configuration.mode = AVAudioSessionModeDefault; | |
| 165 | |
| 166 RTCAudioSession *session = [RTCAudioSession sharedInstance]; | |
| 167 [session lockForConfiguration]; | |
| 168 BOOL hasSucceeded = NO; | |
| 169 NSError *error = nil; | |
| 170 if (session.isActive) { | |
| 171 hasSucceeded = [session setConfiguration:configuration error:&error]; | |
| 172 } else { | |
| 173 hasSucceeded = [session setConfiguration:configuration | |
| 174 active:YES | |
| 175 error:&error]; | |
| 176 } | |
| 177 if (!hasSucceeded) { | |
| 178 RTCLogError(@"Error setting configuration: %@", error.localizedDescription); | |
| 179 } | |
| 180 [session unlockForConfiguration]; | |
| 181 } | |
| 182 | |
| 183 - (void)setupAudioPlayer { | |
| 184 NSString *audioFilePath = | |
| 185 [[NSBundle mainBundle] pathForResource:@"mozart" ofType:@"mp3"]; | |
| 186 NSURL *audioFileURL = [NSURL URLWithString:audioFilePath]; | |
| 187 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL | |
| 188 error:nil]; | |
| 189 _audioPlayer.numberOfLoops = -1; | |
| 190 _audioPlayer.volume = 1.0; | |
| 191 [_audioPlayer prepareToPlay]; | |
| 192 } | |
| 193 | |
| 194 - (void)restartAudioPlayerIfNeeded { | |
| 195 if (_mainView.isAudioLoopPlaying && !self.presentedViewController) { | |
| 196 RTCLog(@"Starting audio loop due to WebRTC end."); | |
| 197 [self configureAudioSession]; | |
| 198 [_audioPlayer play]; | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 - (void)showAlertWithMessage:(NSString*)message { | |
| 203 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil | |
| 204 message:message | |
| 205 delegate:nil | |
| 206 cancelButtonTitle:@"OK" | |
| 207 otherButtonTitles:nil]; | |
| 208 [alertView show]; | |
| 209 } | |
| 210 | |
| 211 @end | |
| OLD | NEW |