OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #import "ARDMainViewController.h" | 11 #import "ARDMainViewController.h" |
12 | 12 |
| 13 #import <AVFoundation/AVFoundation.h> |
| 14 |
| 15 #import "webrtc/base/objc/RTCDispatcher.h" |
| 16 #import "webrtc/base/objc/RTCLogging.h" |
| 17 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" |
| 18 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" |
| 19 |
13 #import "ARDAppClient.h" | 20 #import "ARDAppClient.h" |
14 #import "ARDMainView.h" | 21 #import "ARDMainView.h" |
15 #import "ARDVideoCallViewController.h" | 22 #import "ARDVideoCallViewController.h" |
16 | 23 |
17 @interface ARDMainViewController () <ARDMainViewDelegate> | 24 @interface ARDMainViewController () < |
| 25 ARDMainViewDelegate, |
| 26 RTCAudioSessionDelegate> |
18 @end | 27 @end |
19 | 28 |
20 @implementation ARDMainViewController | 29 @implementation ARDMainViewController { |
| 30 ARDMainView *_mainView; |
| 31 AVAudioPlayer *_audioPlayer; |
| 32 BOOL _shouldDelayAudioConfig; |
| 33 } |
21 | 34 |
22 - (void)loadView { | 35 - (void)loadView { |
23 ARDMainView *mainView = [[ARDMainView alloc] initWithFrame:CGRectZero]; | 36 _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero]; |
24 mainView.delegate = self; | 37 _mainView.delegate = self; |
25 self.view = mainView; | 38 self.view = _mainView; |
26 } | |
27 | 39 |
28 - (void)applicationWillResignActive:(UIApplication *)application { | 40 [self setupAudioSession]; |
29 // Terminate any calls when we aren't active. | 41 [self setupAudioPlayer]; |
30 [self dismissViewControllerAnimated:NO completion:nil]; | |
31 } | 42 } |
32 | 43 |
33 #pragma mark - ARDMainViewDelegate | 44 #pragma mark - ARDMainViewDelegate |
34 | 45 |
35 - (void)mainView:(ARDMainView *)mainView | 46 - (void)mainView:(ARDMainView *)mainView |
36 didInputRoom:(NSString *)room | 47 didInputRoom:(NSString *)room |
37 isLoopback:(BOOL)isLoopback | 48 isLoopback:(BOOL)isLoopback |
38 isAudioOnly:(BOOL)isAudioOnly { | 49 isAudioOnly:(BOOL)isAudioOnly |
| 50 shouldDelayAudioConfig:(BOOL)shouldDelayAudioConfig { |
39 if (!room.length) { | 51 if (!room.length) { |
40 [self showAlertWithMessage:@"Missing room name."]; | 52 [self showAlertWithMessage:@"Missing room name."]; |
41 return; | 53 return; |
42 } | 54 } |
43 // Trim whitespaces. | 55 // Trim whitespaces. |
44 NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet]; | 56 NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet]; |
45 NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet]; | 57 NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet]; |
46 | 58 |
47 // Check that room name is valid. | 59 // Check that room name is valid. |
48 NSError *error = nil; | 60 NSError *error = nil; |
49 NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive; | 61 NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive; |
50 NSRegularExpression *regex = | 62 NSRegularExpression *regex = |
51 [NSRegularExpression regularExpressionWithPattern:@"\\w+" | 63 [NSRegularExpression regularExpressionWithPattern:@"\\w+" |
52 options:options | 64 options:options |
53 error:&error]; | 65 error:&error]; |
54 if (error) { | 66 if (error) { |
55 [self showAlertWithMessage:error.localizedDescription]; | 67 [self showAlertWithMessage:error.localizedDescription]; |
56 return; | 68 return; |
57 } | 69 } |
58 NSRange matchRange = | 70 NSRange matchRange = |
59 [regex rangeOfFirstMatchInString:trimmedRoom | 71 [regex rangeOfFirstMatchInString:trimmedRoom |
60 options:0 | 72 options:0 |
61 range:NSMakeRange(0, trimmedRoom.length)]; | 73 range:NSMakeRange(0, trimmedRoom.length)]; |
62 if (matchRange.location == NSNotFound || | 74 if (matchRange.location == NSNotFound || |
63 matchRange.length != trimmedRoom.length) { | 75 matchRange.length != trimmedRoom.length) { |
64 [self showAlertWithMessage:@"Invalid room name."]; | 76 [self showAlertWithMessage:@"Invalid room name."]; |
65 return; | 77 return; |
66 } | 78 } |
67 | 79 |
| 80 _shouldDelayAudioConfig = shouldDelayAudioConfig; |
| 81 RTCAudioSession *session = [RTCAudioSession sharedInstance]; |
| 82 session.shouldDelayAudioConfiguration = _shouldDelayAudioConfig; |
| 83 |
68 // Kick off the video call. | 84 // Kick off the video call. |
69 ARDVideoCallViewController *videoCallViewController = | 85 ARDVideoCallViewController *videoCallViewController = |
70 [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom | 86 [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom |
71 isLoopback:isLoopback | 87 isLoopback:isLoopback |
72 isAudioOnly:isAudioOnly]; | 88 isAudioOnly:isAudioOnly]; |
73 videoCallViewController.modalTransitionStyle = | 89 videoCallViewController.modalTransitionStyle = |
74 UIModalTransitionStyleCrossDissolve; | 90 UIModalTransitionStyleCrossDissolve; |
75 [self presentViewController:videoCallViewController | 91 [self presentViewController:videoCallViewController |
76 animated:YES | 92 animated:YES |
77 completion:nil]; | 93 completion:nil]; |
78 } | 94 } |
79 | 95 |
| 96 - (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView { |
| 97 if (mainView.isAudioLoopPlaying) { |
| 98 [_audioPlayer stop]; |
| 99 } else { |
| 100 [_audioPlayer play]; |
| 101 } |
| 102 mainView.isAudioLoopPlaying = _audioPlayer.playing; |
| 103 } |
| 104 |
| 105 #pragma mark - RTCAudioSessionDelegate |
| 106 |
| 107 - (void)audioSessionShouldConfigure:(RTCAudioSession *)session { |
| 108 // Won't get called unless audio config is delayed. |
| 109 // Stop playback on main queue and then configure WebRTC. |
| 110 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain |
| 111 block:^{ |
| 112 if (_mainView.isAudioLoopPlaying) { |
| 113 RTCLog(@"Stopping audio loop due to WebRTC start."); |
| 114 [_audioPlayer stop]; |
| 115 } |
| 116 // TODO(tkchin): Shouldn't lock on main queue. Figure out better way to |
| 117 // check audio loop state. |
| 118 [session lockForConfiguration]; |
| 119 [session configureWebRTCSession:nil]; |
| 120 [session unlockForConfiguration]; |
| 121 }]; |
| 122 } |
| 123 |
| 124 - (void)audioSessionShouldUnconfigure:(RTCAudioSession *)session { |
| 125 // Won't get called unless audio config is delayed. |
| 126 [session lockForConfiguration]; |
| 127 [session unconfigureWebRTCSession:nil]; |
| 128 [session unlockForConfiguration]; |
| 129 } |
| 130 |
| 131 - (void)audioSessionDidUnconfigure:(RTCAudioSession *)session { |
| 132 // WebRTC is done with the audio session. Restart playback. |
| 133 [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain |
| 134 block:^{ |
| 135 if (_mainView.isAudioLoopPlaying) { |
| 136 RTCLog(@"Starting audio loop due to WebRTC end."); |
| 137 [_audioPlayer play]; |
| 138 } |
| 139 }]; |
| 140 } |
| 141 |
80 #pragma mark - Private | 142 #pragma mark - Private |
81 | 143 |
| 144 - (void)setupAudioSession { |
| 145 RTCAudioSessionConfiguration *configuration = |
| 146 [[RTCAudioSessionConfiguration alloc] init]; |
| 147 configuration.category = AVAudioSessionCategoryAmbient; |
| 148 configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers; |
| 149 configuration.mode = AVAudioSessionModeDefault; |
| 150 |
| 151 RTCAudioSession *session = [RTCAudioSession sharedInstance]; |
| 152 [session addDelegate:self]; |
| 153 [session lockForConfiguration]; |
| 154 NSError *error = nil; |
| 155 if (![session setConfiguration:configuration active:YES error:&error]) { |
| 156 RTCLogError(@"Error setting configuration: %@", error.localizedDescription); |
| 157 } |
| 158 [session unlockForConfiguration]; |
| 159 } |
| 160 |
| 161 - (void)setupAudioPlayer { |
| 162 NSString *audioFilePath = |
| 163 [[NSBundle mainBundle] pathForResource:@"mozart" ofType:@"mp3"]; |
| 164 NSURL *audioFileURL = [NSURL URLWithString:audioFilePath]; |
| 165 _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL |
| 166 error:nil]; |
| 167 _audioPlayer.numberOfLoops = -1; |
| 168 _audioPlayer.volume = 1.0; |
| 169 [_audioPlayer prepareToPlay]; |
| 170 } |
| 171 |
82 - (void)showAlertWithMessage:(NSString*)message { | 172 - (void)showAlertWithMessage:(NSString*)message { |
83 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil | 173 UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil |
84 message:message | 174 message:message |
85 delegate:nil | 175 delegate:nil |
86 cancelButtonTitle:@"OK" | 176 cancelButtonTitle:@"OK" |
87 otherButtonTitles:nil]; | 177 otherButtonTitles:nil]; |
88 [alertView show]; | 178 [alertView show]; |
89 } | 179 } |
90 | 180 |
91 @end | 181 @end |
OLD | NEW |