session-ios/Signal/src/audio/AppAudioManager.m

215 lines
6.3 KiB
Objective-C

#import "AppAudioManager.h"
#import "AudioRouter.h"
#import "SoundBoard.h"
#define DEFAULT_CATEGORY AVAudioSessionCategorySoloAmbient
#define RECORDING_CATEGORY AVAudioSessionCategoryPlayAndRecord
AppAudioManager* sharedAppAudioManager;
@interface AppAudioManager () <UIAlertViewDelegate>{
enum AudioProfile _audioProfile;
BOOL isSpeakerphoneActive;
}
@property (retain) SoundPlayer *soundPlayer;
@end
@implementation AppAudioManager
+(AppAudioManager*) sharedInstance {
@synchronized(self){
if( nil == sharedAppAudioManager){
sharedAppAudioManager = [AppAudioManager new];
sharedAppAudioManager.soundPlayer = [SoundPlayer new];
[[sharedAppAudioManager soundPlayer] setDelegate:sharedAppAudioManager];
}
}
return sharedAppAudioManager;
}
#pragma mark AudioState Management
-(void) setAudioProfile:(enum AudioProfile) profile {
[self updateAudioRouter];
_audioProfile = profile;
}
-(void) updateAudioRouter{
if (isSpeakerphoneActive){
[AudioRouter routeAllAudioToExternalSpeaker];
}else{
switch (_audioProfile) {
case AudioProfile_Default:
[AudioRouter routeAllAudioToInteralSpeaker];
break;
case AudioProfile_ExternalSpeaker:
[AudioRouter routeAllAudioToExternalSpeaker];
break;
default:
DDLogError(@"Unhandled AudioProfile");
}
}
}
-(void) overrideAudioProfile{
isSpeakerphoneActive = YES;
[self updateAudioRouter];
}
-(void) resetOverride{
isSpeakerphoneActive = NO;
[self updateAudioRouter];
}
-(enum AudioProfile) getCurrentAudioProfile{
return (isSpeakerphoneActive) ? AudioProfile_ExternalSpeaker : _audioProfile;
}
#pragma mark AudioControl;
-(void) respondToProgressChange:(enum CallProgressType) progressType
forLocallyInitiatedCall:(BOOL) initiatedLocally {
switch (progressType){
case CallProgressType_Connecting:
[sharedAppAudioManager setAudioEnabled:YES];
case CallProgressType_Ringing:
(initiatedLocally) ? [self handleOutboundRing] : [self handleInboundRing];
break;
case CallProgressType_Terminated:
break;
case CallProgressType_Securing:
[self handleSecuring];
break;
case CallProgressType_Talking:
[self handleCallEstablished];
break;
}
}
-(void) respondToTerminationType:(enum CallTerminationType) terminationType {
if(terminationType == CallTerminationType_ResponderIsBusy) {
[_soundPlayer playSound:[SoundBoard instanceOfBusySound]];
}
else if([self shouldErrorSoundBePlayedForCallTerminationType:terminationType]){
[_soundPlayer playSound:[SoundBoard instanceOfErrorAlert]];
}
else {
[_soundPlayer playSound:[SoundBoard instanceOfAlert]];
}
}
-(BOOL) shouldErrorSoundBePlayedForCallTerminationType:(enum CallTerminationType) type{
[_soundPlayer stopAllAudio];
if (type == CallTerminationType_RejectedLocal ||
type == CallTerminationType_RejectedRemote ||
type == CallTerminationType_HangupLocal ||
type == CallTerminationType_HangupRemote ||
type == CallTerminationType_RecipientUnavailable) {
return NO;
}
return YES;
}
-(void) handleInboundRing {
[_soundPlayer playSound:[SoundBoard instanceOfInboundRingtone]];
}
-(void) handleOutboundRing {
[self setAudioProfile:AudioProfile_Default];
[_soundPlayer playSound:[SoundBoard instanceOfOutboundRingtone]];
}
-(void) handleSecuring {
[_soundPlayer stopAllAudio];
[self setAudioProfile:AudioProfile_Default];
[_soundPlayer playSound:[SoundBoard instanceOfHandshakeSound]];
}
-(void) handleCallEstablished {
[_soundPlayer stopAllAudio];
[self setAudioProfile:AudioProfile_Default];
[_soundPlayer playSound:[SoundBoard instanceOfCompletedSound]];
}
-(BOOL) toggleSpeakerPhone {
isSpeakerphoneActive=!isSpeakerphoneActive;
[self updateAudioRouter];
return isSpeakerphoneActive;
}
#pragma mark Audio Control
-(void) cancellAllAudio {
[_soundPlayer stopAllAudio];
}
-(BOOL) requestRecordingPrivilege {
return [self changeAudioSessionCategoryTo:RECORDING_CATEGORY];
}
-(BOOL) releaseRecordingPrivilege{
return [self changeAudioSessionCategoryTo:DEFAULT_CATEGORY];
}
-(void) requestRequiredPermissionsIfNeededWithCompletion:(PermissionBlock)permissionBlock incoming:(BOOL)isIncoming {
[AVAudioSession.sharedInstance requestRecordPermission:^(BOOL granted) {
if (!granted) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"") message:NSLocalizedString(@"AUDIO_PERMISSION_MESSAGE", @"") delegate:nil cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"") otherButtonTitles:NSLocalizedString(@"SETTINGS_NAV_BAR_TITLE",nil), nil];
[alertView setDelegate:self];
[alertView show];
}
permissionBlock(granted);
}];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 1) { // Tapped the Settings button
NSURL *appSettings = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
[[UIApplication sharedApplication] openURL:appSettings];
}
}
-(BOOL) changeAudioSessionCategoryTo:(NSString*) category {
NSError* e;
[AVAudioSession.sharedInstance setCategory:category error:&e];
return (nil != e);
}
-(BOOL) setAudioEnabled:(BOOL) enable {
NSError* e;
if (enable) {
[[AVAudioSession sharedInstance] setActive:enable error:&e];
[_soundPlayer awake];
} else {
[[AVAudioSession sharedInstance] setActive:enable
withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
error:&e];
}
return ( nil !=e );
}
-(void) awake {
[_soundPlayer awake];
}
#pragma mark Sound Player Delegate
- (void)didCompleteSoundInstanceOfType:(SoundInstanceType)instanceType {
if (instanceType == SoundInstanceTypeBusySound ||
instanceType == SoundInstanceTypeErrorAlert ||
instanceType == SoundInstanceTypeAlert) {
[sharedAppAudioManager setAudioEnabled:NO];
}
}
@end