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 |