• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 *  Copyright 2016 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 "RTCAudioSession+Private.h"
12#import "RTCAudioSessionConfiguration.h"
13
14#import "base/RTCLogging.h"
15
16@implementation RTC_OBJC_TYPE (RTCAudioSession)
17(Configuration)
18
19    - (BOOL)setConfiguration : (RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration error
20    : (NSError **)outError {
21  return [self setConfiguration:configuration
22                         active:NO
23                shouldSetActive:NO
24                          error:outError];
25}
26
27- (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration
28                  active:(BOOL)active
29                   error:(NSError **)outError {
30  return [self setConfiguration:configuration
31                         active:active
32                shouldSetActive:YES
33                          error:outError];
34}
35
36#pragma mark - Private
37
38- (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration
39                  active:(BOOL)active
40         shouldSetActive:(BOOL)shouldSetActive
41                   error:(NSError **)outError {
42  NSParameterAssert(configuration);
43  if (outError) {
44    *outError = nil;
45  }
46  if (![self checkLock:outError]) {
47    return NO;
48  }
49
50  // Provide an error even if there isn't one so we can log it. We will not
51  // return immediately on error in this function and instead try to set
52  // everything we can.
53  NSError *error = nil;
54
55  if (self.category != configuration.category ||
56      self.categoryOptions != configuration.categoryOptions) {
57    NSError *categoryError = nil;
58    if (![self setCategory:configuration.category
59               withOptions:configuration.categoryOptions
60                     error:&categoryError]) {
61      RTCLogError(@"Failed to set category: %@",
62                  categoryError.localizedDescription);
63      error = categoryError;
64    } else {
65      RTCLog(@"Set category to: %@", configuration.category);
66    }
67  }
68
69  if (self.mode != configuration.mode) {
70    NSError *modeError = nil;
71    if (![self setMode:configuration.mode error:&modeError]) {
72      RTCLogError(@"Failed to set mode: %@",
73                  modeError.localizedDescription);
74      error = modeError;
75    } else {
76      RTCLog(@"Set mode to: %@", configuration.mode);
77    }
78  }
79
80  // Sometimes category options don't stick after setting mode.
81  if (self.categoryOptions != configuration.categoryOptions) {
82    NSError *categoryError = nil;
83    if (![self setCategory:configuration.category
84               withOptions:configuration.categoryOptions
85                     error:&categoryError]) {
86      RTCLogError(@"Failed to set category options: %@",
87                  categoryError.localizedDescription);
88      error = categoryError;
89    } else {
90      RTCLog(@"Set category options to: %ld",
91             (long)configuration.categoryOptions);
92    }
93  }
94
95  if (self.preferredSampleRate != configuration.sampleRate) {
96    NSError *sampleRateError = nil;
97    if (![self setPreferredSampleRate:configuration.sampleRate
98                                error:&sampleRateError]) {
99      RTCLogError(@"Failed to set preferred sample rate: %@",
100                  sampleRateError.localizedDescription);
101      if (!self.ignoresPreferredAttributeConfigurationErrors) {
102        error = sampleRateError;
103      }
104    } else {
105      RTCLog(@"Set preferred sample rate to: %.2f",
106             configuration.sampleRate);
107    }
108  }
109
110  if (self.preferredIOBufferDuration != configuration.ioBufferDuration) {
111    NSError *bufferDurationError = nil;
112    if (![self setPreferredIOBufferDuration:configuration.ioBufferDuration
113                                      error:&bufferDurationError]) {
114      RTCLogError(@"Failed to set preferred IO buffer duration: %@",
115                  bufferDurationError.localizedDescription);
116      if (!self.ignoresPreferredAttributeConfigurationErrors) {
117        error = bufferDurationError;
118      }
119    } else {
120      RTCLog(@"Set preferred IO buffer duration to: %f",
121             configuration.ioBufferDuration);
122    }
123  }
124
125  if (shouldSetActive) {
126    NSError *activeError = nil;
127    if (![self setActive:active error:&activeError]) {
128      RTCLogError(@"Failed to setActive to %d: %@",
129                  active, activeError.localizedDescription);
130      error = activeError;
131    }
132  }
133
134  if (self.isActive &&
135      // TODO(tkchin): Figure out which category/mode numChannels is valid for.
136      [self.mode isEqualToString:AVAudioSessionModeVoiceChat]) {
137    // Try to set the preferred number of hardware audio channels. These calls
138    // must be done after setting the audio session’s category and mode and
139    // activating the session.
140    NSInteger inputNumberOfChannels = configuration.inputNumberOfChannels;
141    if (self.inputNumberOfChannels != inputNumberOfChannels) {
142      NSError *inputChannelsError = nil;
143      if (![self setPreferredInputNumberOfChannels:inputNumberOfChannels
144                                             error:&inputChannelsError]) {
145       RTCLogError(@"Failed to set preferred input number of channels: %@",
146                   inputChannelsError.localizedDescription);
147       if (!self.ignoresPreferredAttributeConfigurationErrors) {
148         error = inputChannelsError;
149       }
150      } else {
151        RTCLog(@"Set input number of channels to: %ld",
152               (long)inputNumberOfChannels);
153      }
154    }
155    NSInteger outputNumberOfChannels = configuration.outputNumberOfChannels;
156    if (self.outputNumberOfChannels != outputNumberOfChannels) {
157      NSError *outputChannelsError = nil;
158      if (![self setPreferredOutputNumberOfChannels:outputNumberOfChannels
159                                              error:&outputChannelsError]) {
160        RTCLogError(@"Failed to set preferred output number of channels: %@",
161                    outputChannelsError.localizedDescription);
162        if (!self.ignoresPreferredAttributeConfigurationErrors) {
163          error = outputChannelsError;
164        }
165      } else {
166        RTCLog(@"Set output number of channels to: %ld",
167               (long)outputNumberOfChannels);
168      }
169    }
170  }
171
172  if (outError) {
173    *outError = error;
174  }
175
176  return error == nil;
177}
178
179@end
180