webrtc_m130/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Configuration.mm
tkchin e54467f73e Use RTCAudioSessionDelegateAdapter in AudioDeviceIOS.
Part 3 of refactor. Also:
- better weak pointer delegate storage + tests
- we now ignore route changes when we're interrupted
- fixed bug where preferred sample rate wasn't set if audio session
   wasn't active

BUG=

Review URL: https://codereview.webrtc.org/1796983004

Cr-Commit-Position: refs/heads/master@{#12007}
2016-03-15 23:54:11 +00:00

189 lines
6.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2016 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 "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h"
#import "webrtc/base/objc/RTCLogging.h"
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h"
#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h"
@implementation RTCAudioSession (Configuration)
- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
active:(BOOL)active
error:(NSError **)outError {
if (![self checkLock:outError]) {
return NO;
}
// Provide an error even if there isn't one so we can log it. We will not
// return immediately on error in this function and instead try to set
// everything we can.
NSError *error = nil;
if (self.category != configuration.category ||
self.categoryOptions != configuration.categoryOptions) {
NSError *categoryError = nil;
if (![self setCategory:configuration.category
withOptions:configuration.categoryOptions
error:&categoryError]) {
RTCLogError(@"Failed to set category: %@",
categoryError.localizedDescription);
error = categoryError;
}
}
if (self.mode != configuration.mode) {
NSError *modeError = nil;
if (![self setMode:configuration.mode error:&modeError]) {
RTCLogError(@"Failed to set mode: %@",
modeError.localizedDescription);
error = modeError;
}
}
// self.sampleRate is accurate only if the audio session is active.
if (!self.isActive || self.sampleRate != configuration.sampleRate) {
NSError *sampleRateError = nil;
if (![self setPreferredSampleRate:configuration.sampleRate
error:&sampleRateError]) {
RTCLogError(@"Failed to set preferred sample rate: %@",
sampleRateError.localizedDescription);
error = sampleRateError;
}
}
// self.IOBufferDuration is accurate only if the audio session is active.
if (!self.isActive ||
self.IOBufferDuration != configuration.ioBufferDuration) {
NSError *bufferDurationError = nil;
if (![self setPreferredIOBufferDuration:configuration.ioBufferDuration
error:&bufferDurationError]) {
RTCLogError(@"Failed to set preferred IO buffer duration: %@",
bufferDurationError.localizedDescription);
error = bufferDurationError;
}
}
NSError *activeError = nil;
if (![self setActive:active error:&activeError]) {
RTCLogError(@"Failed to setActive to %d: %@",
active, activeError.localizedDescription);
error = activeError;
}
if (self.isActive) {
// Try to set the preferred number of hardware audio channels. These calls
// must be done after setting the audio sessions category and mode and
// activating the session.
NSInteger inputNumberOfChannels = configuration.inputNumberOfChannels;
if (self.inputNumberOfChannels != inputNumberOfChannels) {
NSError *inputChannelsError = nil;
if (![self setPreferredInputNumberOfChannels:inputNumberOfChannels
error:&inputChannelsError]) {
RTCLogError(@"Failed to set preferred input number of channels: %@",
inputChannelsError.localizedDescription);
error = inputChannelsError;
}
}
NSInteger outputNumberOfChannels = configuration.outputNumberOfChannels;
if (self.outputNumberOfChannels != outputNumberOfChannels) {
NSError *outputChannelsError = nil;
if (![self setPreferredOutputNumberOfChannels:outputNumberOfChannels
error:&outputChannelsError]) {
RTCLogError(@"Failed to set preferred output number of channels: %@",
outputChannelsError.localizedDescription);
error = outputChannelsError;
}
}
}
if (outError) {
*outError = error;
}
return error == nil;
}
- (BOOL)configureWebRTCSession:(NSError **)outError {
if (![self checkLock:outError]) {
return NO;
}
RTCLog(@"Configuring audio session for WebRTC.");
// Provide an error even if there isn't one so we can log it.
BOOL hasSucceeded = YES;
NSError *error = nil;
RTCAudioSessionConfiguration *currentConfig =
[RTCAudioSessionConfiguration currentConfiguration];
RTCAudioSessionConfiguration *webRTCConfig =
[RTCAudioSessionConfiguration webRTCConfiguration];
if (![self setConfiguration:webRTCConfig active:YES error:&error]) {
RTCLogError(@"Failed to set WebRTC audio configuration: %@",
error.localizedDescription);
// Attempt to restore previous state.
[self setConfiguration:currentConfig active:NO error:nil];
hasSucceeded = NO;
} else if (![self isConfiguredForWebRTC]) {
// Ensure that the active audio session has the correct category and mode.
// This should never happen - this means that we succeeded earlier but
// somehow the settings didn't apply.
RTCLogError(@"Failed to configure audio session.");
// Attempt to restore previous state.
[self setConfiguration:currentConfig active:NO error:nil];
error =
[[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain
code:kRTCAudioSessionErrorConfiguration
userInfo:nil];
hasSucceeded = NO;
}
if (outError) {
*outError = error;
}
return hasSucceeded;
}
#pragma mark - Private
- (BOOL)isConfiguredForWebRTC {
// Ensure that the device currently supports audio input.
if (!self.inputAvailable) {
RTCLogError(@"No audio input path is available!");
return NO;
}
// Only check a minimal list of requirements for whether we have
// what we want.
RTCAudioSessionConfiguration *currentConfig =
[RTCAudioSessionConfiguration currentConfiguration];
RTCAudioSessionConfiguration *webRTCConfig =
[RTCAudioSessionConfiguration webRTCConfiguration];
if (![currentConfig.category isEqualToString:webRTCConfig.category]) {
RTCLog(@"Current category %@ does not match %@",
currentConfig.category,
webRTCConfig.category);
return NO;
}
if (![currentConfig.mode isEqualToString:webRTCConfig.mode]) {
RTCLog(@"Current mode %@ does not match %@",
currentConfig.mode,
webRTCConfig.mode);
return NO;
}
return YES;
}
@end