xref: /aosp_15_r20/external/webrtc/sdk/objc/components/audio/RTCAudioSession+Configuration.mm (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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
47  // Provide an error even if there isn't one so we can log it. We will not
48  // return immediately on error in this function and instead try to set
49  // everything we can.
50  NSError *error = nil;
51
52  if (self.category != configuration.category ||
53      self.categoryOptions != configuration.categoryOptions) {
54    NSError *categoryError = nil;
55    if (![self setCategory:configuration.category
56               withOptions:configuration.categoryOptions
57                     error:&categoryError]) {
58      RTCLogError(@"Failed to set category: %@",
59                  categoryError.localizedDescription);
60      error = categoryError;
61    } else {
62      RTCLog(@"Set category to: %@", configuration.category);
63    }
64  }
65
66  if (self.mode != configuration.mode) {
67    NSError *modeError = nil;
68    if (![self setMode:configuration.mode error:&modeError]) {
69      RTCLogError(@"Failed to set mode: %@",
70                  modeError.localizedDescription);
71      error = modeError;
72    } else {
73      RTCLog(@"Set mode to: %@", configuration.mode);
74    }
75  }
76
77  // Sometimes category options don't stick after setting mode.
78  if (self.categoryOptions != configuration.categoryOptions) {
79    NSError *categoryError = nil;
80    if (![self setCategory:configuration.category
81               withOptions:configuration.categoryOptions
82                     error:&categoryError]) {
83      RTCLogError(@"Failed to set category options: %@",
84                  categoryError.localizedDescription);
85      error = categoryError;
86    } else {
87      RTCLog(@"Set category options to: %ld",
88             (long)configuration.categoryOptions);
89    }
90  }
91
92  if (self.preferredSampleRate != configuration.sampleRate) {
93    NSError *sampleRateError = nil;
94    if (![self setPreferredSampleRate:configuration.sampleRate
95                                error:&sampleRateError]) {
96      RTCLogError(@"Failed to set preferred sample rate: %@",
97                  sampleRateError.localizedDescription);
98      if (!self.ignoresPreferredAttributeConfigurationErrors) {
99        error = sampleRateError;
100      }
101    } else {
102      RTCLog(@"Set preferred sample rate to: %.2f",
103             configuration.sampleRate);
104    }
105  }
106
107  if (self.preferredIOBufferDuration != configuration.ioBufferDuration) {
108    NSError *bufferDurationError = nil;
109    if (![self setPreferredIOBufferDuration:configuration.ioBufferDuration
110                                      error:&bufferDurationError]) {
111      RTCLogError(@"Failed to set preferred IO buffer duration: %@",
112                  bufferDurationError.localizedDescription);
113      if (!self.ignoresPreferredAttributeConfigurationErrors) {
114        error = bufferDurationError;
115      }
116    } else {
117      RTCLog(@"Set preferred IO buffer duration to: %f",
118             configuration.ioBufferDuration);
119    }
120  }
121
122  if (shouldSetActive) {
123    NSError *activeError = nil;
124    if (![self setActive:active error:&activeError]) {
125      RTCLogError(@"Failed to setActive to %d: %@",
126                  active, activeError.localizedDescription);
127      error = activeError;
128    }
129  }
130
131  if (self.isActive &&
132      // TODO(tkchin): Figure out which category/mode numChannels is valid for.
133      [self.mode isEqualToString:AVAudioSessionModeVoiceChat]) {
134    // Try to set the preferred number of hardware audio channels. These calls
135    // must be done after setting the audio session’s category and mode and
136    // activating the session.
137    NSInteger inputNumberOfChannels = configuration.inputNumberOfChannels;
138    if (self.inputNumberOfChannels != inputNumberOfChannels) {
139      NSError *inputChannelsError = nil;
140      if (![self setPreferredInputNumberOfChannels:inputNumberOfChannels
141                                             error:&inputChannelsError]) {
142       RTCLogError(@"Failed to set preferred input number of channels: %@",
143                   inputChannelsError.localizedDescription);
144       if (!self.ignoresPreferredAttributeConfigurationErrors) {
145         error = inputChannelsError;
146       }
147      } else {
148        RTCLog(@"Set input number of channels to: %ld",
149               (long)inputNumberOfChannels);
150      }
151    }
152    NSInteger outputNumberOfChannels = configuration.outputNumberOfChannels;
153    if (self.outputNumberOfChannels != outputNumberOfChannels) {
154      NSError *outputChannelsError = nil;
155      if (![self setPreferredOutputNumberOfChannels:outputNumberOfChannels
156                                              error:&outputChannelsError]) {
157        RTCLogError(@"Failed to set preferred output number of channels: %@",
158                    outputChannelsError.localizedDescription);
159        if (!self.ignoresPreferredAttributeConfigurationErrors) {
160          error = outputChannelsError;
161        }
162      } else {
163        RTCLog(@"Set output number of channels to: %ld",
164               (long)outputNumberOfChannels);
165      }
166    }
167  }
168
169  if (outError) {
170    *outError = error;
171  }
172
173  return error == nil;
174}
175
176@end
177