/* * 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 "RTCAudioSession+Private.h" #import "RTCAudioSessionConfiguration.h" #import "base/RTCLogging.h" @implementation RTC_OBJC_TYPE (RTCAudioSession) (Configuration) - (BOOL)setConfiguration : (RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration error : (NSError **)outError { return [self setConfiguration:configuration active:NO shouldSetActive:NO error:outError]; } - (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration active:(BOOL)active error:(NSError **)outError { return [self setConfiguration:configuration active:active shouldSetActive:YES error:outError]; } #pragma mark - Private - (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration active:(BOOL)active shouldSetActive:(BOOL)shouldSetActive error:(NSError **)outError { NSParameterAssert(configuration); if (outError) { *outError = nil; } 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; } else { RTCLog(@"Set category to: %@", configuration.category); } } if (self.mode != configuration.mode) { NSError *modeError = nil; if (![self setMode:configuration.mode error:&modeError]) { RTCLogError(@"Failed to set mode: %@", modeError.localizedDescription); error = modeError; } else { RTCLog(@"Set mode to: %@", configuration.mode); } } // Sometimes category options don't stick after setting mode. if (self.categoryOptions != configuration.categoryOptions) { NSError *categoryError = nil; if (![self setCategory:configuration.category withOptions:configuration.categoryOptions error:&categoryError]) { RTCLogError(@"Failed to set category options: %@", categoryError.localizedDescription); error = categoryError; } else { RTCLog(@"Set category options to: %ld", (long)configuration.categoryOptions); } } if (self.preferredSampleRate != configuration.sampleRate) { NSError *sampleRateError = nil; if (![self setPreferredSampleRate:configuration.sampleRate error:&sampleRateError]) { RTCLogError(@"Failed to set preferred sample rate: %@", sampleRateError.localizedDescription); if (!self.ignoresPreferredAttributeConfigurationErrors) { error = sampleRateError; } } else { RTCLog(@"Set preferred sample rate to: %.2f", configuration.sampleRate); } } if (self.preferredIOBufferDuration != configuration.ioBufferDuration) { NSError *bufferDurationError = nil; if (![self setPreferredIOBufferDuration:configuration.ioBufferDuration error:&bufferDurationError]) { RTCLogError(@"Failed to set preferred IO buffer duration: %@", bufferDurationError.localizedDescription); if (!self.ignoresPreferredAttributeConfigurationErrors) { error = bufferDurationError; } } else { RTCLog(@"Set preferred IO buffer duration to: %f", configuration.ioBufferDuration); } } if (shouldSetActive) { NSError *activeError = nil; if (![self setActive:active error:&activeError]) { RTCLogError(@"Failed to setActive to %d: %@", active, activeError.localizedDescription); error = activeError; } } if (self.isActive && // TODO(tkchin): Figure out which category/mode numChannels is valid for. [self.mode isEqualToString:AVAudioSessionModeVoiceChat]) { // Try to set the preferred number of hardware audio channels. These calls // must be done after setting the audio session’s 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); if (!self.ignoresPreferredAttributeConfigurationErrors) { error = inputChannelsError; } } else { RTCLog(@"Set input number of channels to: %ld", (long)inputNumberOfChannels); } } 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); if (!self.ignoresPreferredAttributeConfigurationErrors) { error = outputChannelsError; } } else { RTCLog(@"Set output number of channels to: %ld", (long)outputNumberOfChannels); } } } if (outError) { *outError = error; } return error == nil; } @end