| Index: webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.m | 
| diff --git a/webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.m b/webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.m | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..e392168dee61b3e2dee72a224c593cad3fc3862e | 
| --- /dev/null | 
| +++ b/webrtc/examples/objc/AppRTCDemo/ios/ARDMainViewController.m | 
| @@ -0,0 +1,211 @@ | 
| +/* | 
| + *  Copyright 2015 The WebRTC Project Authors. All rights reserved. | 
| + * | 
| + *  Use of this source code is governed by a BSD-style license | 
| + *  that can be found in the LICENSE file in the root of the source | 
| + *  tree. An additional intellectual property rights grant can be found | 
| + *  in the file PATENTS.  All contributing project authors may | 
| + *  be found in the AUTHORS file in the root of the source tree. | 
| + */ | 
| + | 
| +#import "ARDMainViewController.h" | 
| + | 
| +#import <AVFoundation/AVFoundation.h> | 
| + | 
| +#import "WebRTC/RTCDispatcher.h" | 
| +#import "WebRTC/RTCLogging.h" | 
| +#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" | 
| +#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" | 
| + | 
| +#import "ARDAppClient.h" | 
| +#import "ARDMainView.h" | 
| +#import "ARDVideoCallViewController.h" | 
| + | 
| +@interface ARDMainViewController () < | 
| +    ARDMainViewDelegate, | 
| +    ARDVideoCallViewControllerDelegate, | 
| +    RTCAudioSessionDelegate> | 
| +@end | 
| + | 
| +@implementation ARDMainViewController { | 
| +  ARDMainView *_mainView; | 
| +  AVAudioPlayer *_audioPlayer; | 
| +  BOOL _useManualAudio; | 
| +} | 
| + | 
| +- (void)loadView { | 
| +  _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero]; | 
| +  _mainView.delegate = self; | 
| +  self.view = _mainView; | 
| + | 
| +  RTCAudioSessionConfiguration *webRTCConfig = | 
| +      [RTCAudioSessionConfiguration webRTCConfiguration]; | 
| +  webRTCConfig.categoryOptions = webRTCConfig.categoryOptions | | 
| +      AVAudioSessionCategoryOptionDefaultToSpeaker; | 
| +  [RTCAudioSessionConfiguration setWebRTCConfiguration:webRTCConfig]; | 
| + | 
| +  RTCAudioSession *session = [RTCAudioSession sharedInstance]; | 
| +  [session addDelegate:self]; | 
| + | 
| +  [self configureAudioSession]; | 
| +  [self setupAudioPlayer]; | 
| +} | 
| + | 
| +#pragma mark - ARDMainViewDelegate | 
| + | 
| +- (void)mainView:(ARDMainView *)mainView | 
| +             didInputRoom:(NSString *)room | 
| +               isLoopback:(BOOL)isLoopback | 
| +              isAudioOnly:(BOOL)isAudioOnly | 
| +        shouldMakeAecDump:(BOOL)shouldMakeAecDump | 
| +    shouldUseLevelControl:(BOOL)shouldUseLevelControl | 
| +           useManualAudio:(BOOL)useManualAudio { | 
| +  if (!room.length) { | 
| +    [self showAlertWithMessage:@"Missing room name."]; | 
| +    return; | 
| +  } | 
| +  // Trim whitespaces. | 
| +  NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet]; | 
| +  NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet]; | 
| + | 
| +  // Check that room name is valid. | 
| +  NSError *error = nil; | 
| +  NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive; | 
| +  NSRegularExpression *regex = | 
| +      [NSRegularExpression regularExpressionWithPattern:@"\\w+" | 
| +                                                options:options | 
| +                                                  error:&error]; | 
| +  if (error) { | 
| +    [self showAlertWithMessage:error.localizedDescription]; | 
| +    return; | 
| +  } | 
| +  NSRange matchRange = | 
| +      [regex rangeOfFirstMatchInString:trimmedRoom | 
| +                               options:0 | 
| +                                 range:NSMakeRange(0, trimmedRoom.length)]; | 
| +  if (matchRange.location == NSNotFound || | 
| +      matchRange.length != trimmedRoom.length) { | 
| +    [self showAlertWithMessage:@"Invalid room name."]; | 
| +    return; | 
| +  } | 
| + | 
| +  RTCAudioSession *session = [RTCAudioSession sharedInstance]; | 
| +  session.useManualAudio = useManualAudio; | 
| +  session.isAudioEnabled = NO; | 
| + | 
| +  // Kick off the video call. | 
| +  ARDVideoCallViewController *videoCallViewController = | 
| +      [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom | 
| +                                           isLoopback:isLoopback | 
| +                                          isAudioOnly:isAudioOnly | 
| +                                    shouldMakeAecDump:shouldMakeAecDump | 
| +                                shouldUseLevelControl:shouldUseLevelControl | 
| +                                             delegate:self]; | 
| +  videoCallViewController.modalTransitionStyle = | 
| +      UIModalTransitionStyleCrossDissolve; | 
| +  [self presentViewController:videoCallViewController | 
| +                     animated:YES | 
| +                   completion:nil]; | 
| +} | 
| + | 
| +- (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView { | 
| +  if (mainView.isAudioLoopPlaying) { | 
| +    [_audioPlayer stop]; | 
| +  } else { | 
| +    [_audioPlayer play]; | 
| +  } | 
| +  mainView.isAudioLoopPlaying = _audioPlayer.playing; | 
| +} | 
| + | 
| +#pragma mark - ARDVideoCallViewControllerDelegate | 
| + | 
| +- (void)viewControllerDidFinish:(ARDVideoCallViewController *)viewController { | 
| +  if (![viewController isBeingDismissed]) { | 
| +    RTCLog(@"Dismissing VC"); | 
| +    [self dismissViewControllerAnimated:YES completion:^{ | 
| +      [self restartAudioPlayerIfNeeded]; | 
| +    }]; | 
| +  } | 
| +  RTCAudioSession *session = [RTCAudioSession sharedInstance]; | 
| +  session.isAudioEnabled = NO; | 
| +} | 
| + | 
| +#pragma mark - RTCAudioSessionDelegate | 
| + | 
| +- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session { | 
| +  // Stop playback on main queue and then configure WebRTC. | 
| +  [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain | 
| +                               block:^{ | 
| +    if (_mainView.isAudioLoopPlaying) { | 
| +      RTCLog(@"Stopping audio loop due to WebRTC start."); | 
| +      [_audioPlayer stop]; | 
| +    } | 
| +    RTCLog(@"Setting isAudioEnabled to YES."); | 
| +    session.isAudioEnabled = YES; | 
| +  }]; | 
| +} | 
| + | 
| +- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session { | 
| +  // WebRTC is done with the audio session. Restart playback. | 
| +  [RTCDispatcher dispatchAsyncOnType:RTCDispatcherTypeMain | 
| +                               block:^{ | 
| +    RTCLog(@"audioSessionDidStopPlayOrRecord"); | 
| +    [self restartAudioPlayerIfNeeded]; | 
| +  }]; | 
| +} | 
| + | 
| +#pragma mark - Private | 
| + | 
| +- (void)configureAudioSession { | 
| +  RTCAudioSessionConfiguration *configuration = | 
| +      [[RTCAudioSessionConfiguration alloc] init]; | 
| +  configuration.category = AVAudioSessionCategoryAmbient; | 
| +  configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers; | 
| +  configuration.mode = AVAudioSessionModeDefault; | 
| + | 
| +  RTCAudioSession *session = [RTCAudioSession sharedInstance]; | 
| +  [session lockForConfiguration]; | 
| +  BOOL hasSucceeded = NO; | 
| +  NSError *error = nil; | 
| +  if (session.isActive) { | 
| +    hasSucceeded = [session setConfiguration:configuration error:&error]; | 
| +  } else { | 
| +    hasSucceeded = [session setConfiguration:configuration | 
| +                                      active:YES | 
| +                                       error:&error]; | 
| +  } | 
| +  if (!hasSucceeded) { | 
| +    RTCLogError(@"Error setting configuration: %@", error.localizedDescription); | 
| +  } | 
| +  [session unlockForConfiguration]; | 
| +} | 
| + | 
| +- (void)setupAudioPlayer { | 
| +  NSString *audioFilePath = | 
| +      [[NSBundle mainBundle] pathForResource:@"mozart" ofType:@"mp3"]; | 
| +  NSURL *audioFileURL = [NSURL URLWithString:audioFilePath]; | 
| +  _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL | 
| +                                                        error:nil]; | 
| +  _audioPlayer.numberOfLoops = -1; | 
| +  _audioPlayer.volume = 1.0; | 
| +  [_audioPlayer prepareToPlay]; | 
| +} | 
| + | 
| +- (void)restartAudioPlayerIfNeeded { | 
| +  if (_mainView.isAudioLoopPlaying && !self.presentedViewController) { | 
| +    RTCLog(@"Starting audio loop due to WebRTC end."); | 
| +    [self configureAudioSession]; | 
| +    [_audioPlayer play]; | 
| +  } | 
| +} | 
| + | 
| +- (void)showAlertWithMessage:(NSString*)message { | 
| +  UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:nil | 
| +                                                      message:message | 
| +                                                     delegate:nil | 
| +                                            cancelButtonTitle:@"OK" | 
| +                                            otherButtonTitles:nil]; | 
| +  [alertView show]; | 
| +} | 
| + | 
| +@end | 
|  |