tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ARDMainViewController.m (10055B)


      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 "sdk/objc/base/RTCLogging.h"
     16 #import "sdk/objc/components/audio/RTCAudioSession.h"
     17 #import "sdk/objc/components/audio/RTCAudioSessionConfiguration.h"
     18 #import "sdk/objc/helpers/RTCDispatcher.h"
     19 
     20 #import "ARDAppClient.h"
     21 #import "ARDMainView.h"
     22 #import "ARDSettingsModel.h"
     23 #import "ARDSettingsViewController.h"
     24 #import "ARDVideoCallViewController.h"
     25 
     26 static NSString *const barButtonImageString = @"ic_settings_black_24dp.png";
     27 
     28 // Launch argument to be passed to indicate that the app should start loopback
     29 // immediatly
     30 static NSString *const loopbackLaunchProcessArgument = @"loopback";
     31 
     32 @interface ARDMainViewController () <ARDMainViewDelegate,
     33                                     ARDVideoCallViewControllerDelegate,
     34                                     RTC_OBJC_TYPE (RTCAudioSessionDelegate)>
     35 @property(nonatomic, strong) ARDMainView *mainView;
     36 @property(nonatomic, strong) AVAudioPlayer *audioPlayer;
     37 @end
     38 
     39 @implementation ARDMainViewController {
     40  BOOL _useManualAudio;
     41 }
     42 
     43 @synthesize mainView = _mainView;
     44 @synthesize audioPlayer = _audioPlayer;
     45 
     46 - (void)viewDidLoad {
     47  [super viewDidLoad];
     48  if ([[[NSProcessInfo processInfo] arguments]
     49          containsObject:loopbackLaunchProcessArgument]) {
     50    [self mainView:nil didInputRoom:@"" isLoopback:YES];
     51  }
     52 }
     53 
     54 - (void)loadView {
     55  self.title = @"AppRTC Mobile";
     56  _mainView = [[ARDMainView alloc] initWithFrame:CGRectZero];
     57  _mainView.delegate = self;
     58  self.view = _mainView;
     59  [self addSettingsBarButton];
     60 
     61  RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *webRTCConfig =
     62      [RTC_OBJC_TYPE(RTCAudioSessionConfiguration) webRTCConfiguration];
     63  webRTCConfig.categoryOptions = webRTCConfig.categoryOptions |
     64      AVAudioSessionCategoryOptionDefaultToSpeaker;
     65  [RTC_OBJC_TYPE(RTCAudioSessionConfiguration)
     66      setWebRTCConfiguration:webRTCConfig];
     67 
     68  RTC_OBJC_TYPE(RTCAudioSession) *session =
     69      [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
     70  [session addDelegate:self];
     71 
     72  [self configureAudioSession];
     73  [self setupAudioPlayer];
     74 }
     75 
     76 - (void)addSettingsBarButton {
     77  UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc]
     78      initWithImage:[UIImage imageNamed:barButtonImageString]
     79              style:UIBarButtonItemStylePlain
     80             target:self
     81             action:@selector(showSettings:)];
     82  self.navigationItem.rightBarButtonItem = settingsButton;
     83 }
     84 
     85 + (NSString *)loopbackRoomString {
     86  NSString *loopbackRoomString =
     87      [[NSUUID UUID].UUIDString stringByReplacingOccurrencesOfString:@"-"
     88                                                          withString:@""];
     89  return loopbackRoomString;
     90 }
     91 
     92 #pragma mark - ARDMainViewDelegate
     93 
     94 - (void)mainView:(ARDMainView *)mainView
     95    didInputRoom:(NSString *)room
     96      isLoopback:(BOOL)isLoopback {
     97  if (!room.length) {
     98    if (isLoopback) {
     99      // If this is a loopback call, allow a generated room name.
    100      room = [[self class] loopbackRoomString];
    101    } else {
    102      [self showAlertWithMessage:@"Missing room name."];
    103      return;
    104    }
    105  }
    106  // Trim whitespaces.
    107  NSCharacterSet *whitespaceSet = [NSCharacterSet whitespaceCharacterSet];
    108  NSString *trimmedRoom = [room stringByTrimmingCharactersInSet:whitespaceSet];
    109 
    110  // Check that room name is valid.
    111  NSError *error = nil;
    112  NSRegularExpressionOptions options = NSRegularExpressionCaseInsensitive;
    113  NSRegularExpression *regex =
    114      [NSRegularExpression regularExpressionWithPattern:@"\\w+"
    115                                                options:options
    116                                                  error:&error];
    117  if (error) {
    118    [self showAlertWithMessage:error.localizedDescription];
    119    return;
    120  }
    121  NSRange matchRange =
    122      [regex rangeOfFirstMatchInString:trimmedRoom
    123                               options:0
    124                                 range:NSMakeRange(0, trimmedRoom.length)];
    125  if (matchRange.location == NSNotFound ||
    126      matchRange.length != trimmedRoom.length) {
    127    [self showAlertWithMessage:@"Invalid room name."];
    128    return;
    129  }
    130 
    131  ARDSettingsModel *settingsModel = [[ARDSettingsModel alloc] init];
    132 
    133  RTC_OBJC_TYPE(RTCAudioSession) *session =
    134      [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
    135  session.useManualAudio =
    136      [settingsModel currentUseManualAudioConfigSettingFromStore];
    137  session.isAudioEnabled = NO;
    138 
    139  // Kick off the video call.
    140  ARDVideoCallViewController *videoCallViewController =
    141      [[ARDVideoCallViewController alloc] initForRoom:trimmedRoom
    142                                           isLoopback:isLoopback
    143                                             delegate:self];
    144  videoCallViewController.modalTransitionStyle =
    145      UIModalTransitionStyleCrossDissolve;
    146  videoCallViewController.modalPresentationStyle =
    147      UIModalPresentationFullScreen;
    148  [self presentViewController:videoCallViewController
    149                     animated:YES
    150                   completion:nil];
    151 }
    152 
    153 - (void)mainViewDidToggleAudioLoop:(ARDMainView *)mainView {
    154  if (mainView.isAudioLoopPlaying) {
    155    [_audioPlayer stop];
    156  } else {
    157    [_audioPlayer play];
    158  }
    159  mainView.isAudioLoopPlaying = _audioPlayer.playing;
    160 }
    161 
    162 #pragma mark - ARDVideoCallViewControllerDelegate
    163 
    164 - (void)viewControllerDidFinish:(ARDVideoCallViewController *)viewController {
    165  if (![viewController isBeingDismissed]) {
    166    RTCLog(@"Dismissing VC");
    167    [self dismissViewControllerAnimated:YES
    168                             completion:^{
    169                               [self restartAudioPlayerIfNeeded];
    170                             }];
    171  }
    172  RTC_OBJC_TYPE(RTCAudioSession) *session =
    173      [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
    174  session.isAudioEnabled = NO;
    175 }
    176 
    177 #pragma mark - RTC_OBJC_TYPE(RTCAudioSessionDelegate)
    178 
    179 - (void)audioSessionDidStartPlayOrRecord:
    180    (RTC_OBJC_TYPE(RTCAudioSession) *)session {
    181  // Stop playback on main queue and then configure WebRTC.
    182  [RTC_OBJC_TYPE(RTCDispatcher)
    183      dispatchAsyncOnType:RTCDispatcherTypeMain
    184                    block:^{
    185                      if (self.mainView.isAudioLoopPlaying) {
    186                        RTCLog(@"Stopping audio loop due to WebRTC start.");
    187                        [self.audioPlayer stop];
    188                      }
    189                      RTCLog(@"Setting isAudioEnabled to YES.");
    190                      session.isAudioEnabled = YES;
    191                    }];
    192 }
    193 
    194 - (void)audioSessionDidStopPlayOrRecord:
    195    (RTC_OBJC_TYPE(RTCAudioSession) *)session {
    196  // WebRTC is done with the audio session. Restart playback.
    197  [RTC_OBJC_TYPE(RTCDispatcher)
    198      dispatchAsyncOnType:RTCDispatcherTypeMain
    199                    block:^{
    200                      RTCLog(@"audioSessionDidStopPlayOrRecord");
    201                      [self restartAudioPlayerIfNeeded];
    202                    }];
    203 }
    204 
    205 #pragma mark - Private
    206 - (void)showSettings:(id)sender {
    207  ARDSettingsViewController *settingsController =
    208      [[ARDSettingsViewController alloc]
    209          initWithStyle:UITableViewStyleGrouped
    210          settingsModel:[[ARDSettingsModel alloc] init]];
    211 
    212  UINavigationController *navigationController = [[UINavigationController alloc]
    213      initWithRootViewController:settingsController];
    214  [self presentViewControllerAsModal:navigationController];
    215 }
    216 
    217 - (void)presentViewControllerAsModal:(UIViewController *)viewController {
    218  [self presentViewController:viewController animated:YES completion:nil];
    219 }
    220 
    221 - (void)configureAudioSession {
    222  RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *configuration =
    223      [[RTC_OBJC_TYPE(RTCAudioSessionConfiguration) alloc] init];
    224  configuration.category = AVAudioSessionCategoryAmbient;
    225  configuration.categoryOptions = AVAudioSessionCategoryOptionDuckOthers;
    226  configuration.mode = AVAudioSessionModeDefault;
    227 
    228  RTC_OBJC_TYPE(RTCAudioSession) *session =
    229      [RTC_OBJC_TYPE(RTCAudioSession) sharedInstance];
    230  [session lockForConfiguration];
    231  BOOL hasSucceeded = NO;
    232  NSError *error = nil;
    233  if (session.isActive) {
    234    hasSucceeded = [session setConfiguration:configuration error:&error];
    235  } else {
    236    hasSucceeded = [session setConfiguration:configuration
    237                                      active:YES
    238                                       error:&error];
    239  }
    240  if (!hasSucceeded) {
    241    RTCLogError(@"Error setting configuration: %@", error.localizedDescription);
    242  }
    243  [session unlockForConfiguration];
    244 }
    245 
    246 - (void)setupAudioPlayer {
    247  NSString *audioFilePath = [[NSBundle mainBundle] pathForResource:@"mozart"
    248                                                            ofType:@"mp3"];
    249  NSURL *audioFileURL = [NSURL URLWithString:audioFilePath];
    250  _audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioFileURL
    251                                                        error:nil];
    252  _audioPlayer.numberOfLoops = -1;
    253  _audioPlayer.volume = 1.0;
    254  [_audioPlayer prepareToPlay];
    255 }
    256 
    257 - (void)restartAudioPlayerIfNeeded {
    258  [self configureAudioSession];
    259  if (_mainView.isAudioLoopPlaying && !self.presentedViewController) {
    260    RTCLog(@"Starting audio loop due to WebRTC end.");
    261    [_audioPlayer play];
    262  }
    263 }
    264 
    265 - (void)showAlertWithMessage:(NSString *)message {
    266  UIAlertController *alert =
    267      [UIAlertController alertControllerWithTitle:nil
    268                                          message:message
    269                                   preferredStyle:UIAlertControllerStyleAlert];
    270 
    271  UIAlertAction *defaultAction =
    272      [UIAlertAction actionWithTitle:@"OK"
    273                               style:UIAlertActionStyleDefault
    274                             handler:^(UIAlertAction *action){
    275                             }];
    276 
    277  [alert addAction:defaultAction];
    278  [self presentViewController:alert animated:YES completion:nil];
    279 }
    280 
    281 @end