blob: 2730664858188e16cdc5612d4f608fbc42d9a02f [file] [log] [blame]
Anders Carlsson7bca8ca2018-08-30 07:30:291/*
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 <AVFoundation/AVFoundation.h>
12#import <Foundation/Foundation.h>
13
14#import "RTCMacros.h"
15
16NS_ASSUME_NONNULL_BEGIN
17
18extern NSString *const kRTCAudioSessionErrorDomain;
19/** Method that requires lock was called without lock. */
20extern NSInteger const kRTCAudioSessionErrorLockRequired;
21/** Unknown configuration error occurred. */
22extern NSInteger const kRTCAudioSessionErrorConfiguration;
23
Mirko Bonadeia81e9c82020-05-04 14:14:3224@class RTC_OBJC_TYPE(RTCAudioSession);
25@class RTC_OBJC_TYPE(RTCAudioSessionConfiguration);
Anders Carlsson7bca8ca2018-08-30 07:30:2926
27// Surfaces AVAudioSession events. WebRTC will listen directly for notifications
28// from AVAudioSession and handle them before calling these delegate methods,
29// at which point applications can perform additional processing if required.
Mirko Bonadeie8d57242018-09-17 08:22:5630RTC_OBJC_EXPORT
Mirko Bonadeia81e9c82020-05-04 14:14:3231@protocol RTC_OBJC_TYPE
32(RTCAudioSessionDelegate)<NSObject>
Anders Carlsson7bca8ca2018-08-30 07:30:2933
Mirko Bonadeia81e9c82020-05-04 14:14:3234 @optional
Anders Carlsson7bca8ca2018-08-30 07:30:2935/** Called on a system notification thread when AVAudioSession starts an
36 * interruption event.
37 */
Mirko Bonadeia81e9c82020-05-04 14:14:3238- (void)audioSessionDidBeginInterruption:(RTC_OBJC_TYPE(RTCAudioSession) *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:2939
40/** Called on a system notification thread when AVAudioSession ends an
41 * interruption event.
42 */
Mirko Bonadeia81e9c82020-05-04 14:14:3243- (void)audioSessionDidEndInterruption:(RTC_OBJC_TYPE(RTCAudioSession) *)session
Anders Carlsson7bca8ca2018-08-30 07:30:2944 shouldResumeSession:(BOOL)shouldResumeSession;
45
46/** Called on a system notification thread when AVAudioSession changes the
47 * route.
48 */
Mirko Bonadeia81e9c82020-05-04 14:14:3249- (void)audioSessionDidChangeRoute:(RTC_OBJC_TYPE(RTCAudioSession) *)session
Anders Carlsson7bca8ca2018-08-30 07:30:2950 reason:(AVAudioSessionRouteChangeReason)reason
51 previousRoute:(AVAudioSessionRouteDescription *)previousRoute;
52
53/** Called on a system notification thread when AVAudioSession media server
54 * terminates.
55 */
Mirko Bonadeia81e9c82020-05-04 14:14:3256- (void)audioSessionMediaServerTerminated:(RTC_OBJC_TYPE(RTCAudioSession) *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:2957
58/** Called on a system notification thread when AVAudioSession media server
59 * restarts.
60 */
Mirko Bonadeia81e9c82020-05-04 14:14:3261- (void)audioSessionMediaServerReset:(RTC_OBJC_TYPE(RTCAudioSession) *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:2962
63// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification.
64
Mirko Bonadeia81e9c82020-05-04 14:14:3265- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)session
66 didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord;
Anders Carlsson7bca8ca2018-08-30 07:30:2967
68/** Called on a WebRTC thread when the audio device is notified to begin
69 * playback or recording.
70 */
Mirko Bonadeia81e9c82020-05-04 14:14:3271- (void)audioSessionDidStartPlayOrRecord:(RTC_OBJC_TYPE(RTCAudioSession) *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:2972
73/** Called on a WebRTC thread when the audio device is notified to stop
74 * playback or recording.
75 */
Mirko Bonadeia81e9c82020-05-04 14:14:3276- (void)audioSessionDidStopPlayOrRecord:(RTC_OBJC_TYPE(RTCAudioSession) *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:2977
78/** Called when the AVAudioSession output volume value changes. */
Mirko Bonadeia81e9c82020-05-04 14:14:3279- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession
80 didChangeOutputVolume:(float)outputVolume;
Anders Carlsson7bca8ca2018-08-30 07:30:2981
82/** Called when the audio device detects a playout glitch. The argument is the
83 * number of glitches detected so far in the current audio playout session.
84 */
Mirko Bonadeia81e9c82020-05-04 14:14:3285- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession
Anders Carlsson7bca8ca2018-08-30 07:30:2986 didDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches;
87
88/** Called when the audio session is about to change the active state.
89 */
Mirko Bonadeia81e9c82020-05-04 14:14:3290- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession willSetActive:(BOOL)active;
Anders Carlsson7bca8ca2018-08-30 07:30:2991
92/** Called after the audio session sucessfully changed the active state.
93 */
Mirko Bonadeia81e9c82020-05-04 14:14:3294- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession didSetActive:(BOOL)active;
Anders Carlsson7bca8ca2018-08-30 07:30:2995
96/** Called after the audio session failed to change the active state.
97 */
Mirko Bonadeia81e9c82020-05-04 14:14:3298- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession
Anders Carlsson7bca8ca2018-08-30 07:30:2999 failedToSetActive:(BOOL)active
100 error:(NSError *)error;
101
Peter Hansperse5b4e942021-08-26 15:56:44102- (void)audioSession:(RTC_OBJC_TYPE(RTCAudioSession) *)audioSession
103 audioUnitStartFailedWithError:(NSError *)error;
104
Anders Carlsson7bca8ca2018-08-30 07:30:29105@end
106
107/** This is a protocol used to inform RTCAudioSession when the audio session
108 * activation state has changed outside of RTCAudioSession. The current known use
109 * case of this is when CallKit activates the audio session for the application
110 */
Mirko Bonadeie8d57242018-09-17 08:22:56111RTC_OBJC_EXPORT
Mirko Bonadeia81e9c82020-05-04 14:14:32112@protocol RTC_OBJC_TYPE
113(RTCAudioSessionActivationDelegate)<NSObject>
Anders Carlsson7bca8ca2018-08-30 07:30:29114
Mirko Bonadeia81e9c82020-05-04 14:14:32115 /** Called when the audio session is activated outside of the app by iOS. */
116 - (void)audioSessionDidActivate : (AVAudioSession *)session;
Anders Carlsson7bca8ca2018-08-30 07:30:29117
118/** Called when the audio session is deactivated outside of the app by iOS. */
119- (void)audioSessionDidDeactivate:(AVAudioSession *)session;
120
121@end
122
123/** Proxy class for AVAudioSession that adds a locking mechanism similar to
124 * AVCaptureDevice. This is used to that interleaving configurations between
125 * WebRTC and the application layer are avoided.
126 *
127 * RTCAudioSession also coordinates activation so that the audio session is
Artem Titovcfea2182021-08-09 23:22:31128 * activated only once. See `setActive:error:`.
Anders Carlsson7bca8ca2018-08-30 07:30:29129 */
Mirko Bonadeie8d57242018-09-17 08:22:56130RTC_OBJC_EXPORT
Mirko Bonadeia81e9c82020-05-04 14:14:32131@interface RTC_OBJC_TYPE (RTCAudioSession) : NSObject <RTC_OBJC_TYPE(RTCAudioSessionActivationDelegate)>
Anders Carlsson7bca8ca2018-08-30 07:30:29132
133/** Convenience property to access the AVAudioSession singleton. Callers should
134 * not call setters on AVAudioSession directly, but other method invocations
135 * are fine.
136 */
137@property(nonatomic, readonly) AVAudioSession *session;
138
139/** Our best guess at whether the session is active based on results of calls to
140 * AVAudioSession.
141 */
142@property(nonatomic, readonly) BOOL isActive;
Anders Carlsson7bca8ca2018-08-30 07:30:29143
144/** If YES, WebRTC will not initialize the audio unit automatically when an
145 * audio track is ready for playout or recording. Instead, applications should
146 * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit
147 * as soon as an audio track is ready for playout or recording.
148 */
149@property(nonatomic, assign) BOOL useManualAudio;
150
151/** This property is only effective if useManualAudio is YES.
152 * Represents permission for WebRTC to initialize the VoIP audio unit.
153 * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be
154 * stopped and uninitialized. This will stop incoming and outgoing audio.
155 * When set to YES, WebRTC will initialize and start the audio unit when it is
156 * needed (e.g. due to establishing an audio connection).
157 * This property was introduced to work around an issue where if an AVPlayer is
158 * playing audio while the VoIP audio unit is initialized, its audio would be
159 * either cut off completely or played at a reduced volume. By preventing
160 * the audio unit from being initialized until after the audio has completed,
161 * we are able to prevent the abrupt cutoff.
162 */
163@property(nonatomic, assign) BOOL isAudioEnabled;
164
165// Proxy properties.
166@property(readonly) NSString *category;
167@property(readonly) AVAudioSessionCategoryOptions categoryOptions;
168@property(readonly) NSString *mode;
169@property(readonly) BOOL secondaryAudioShouldBeSilencedHint;
170@property(readonly) AVAudioSessionRouteDescription *currentRoute;
171@property(readonly) NSInteger maximumInputNumberOfChannels;
172@property(readonly) NSInteger maximumOutputNumberOfChannels;
173@property(readonly) float inputGain;
174@property(readonly) BOOL inputGainSettable;
175@property(readonly) BOOL inputAvailable;
176@property(readonly, nullable) NSArray<AVAudioSessionDataSourceDescription *> *inputDataSources;
177@property(readonly, nullable) AVAudioSessionDataSourceDescription *inputDataSource;
178@property(readonly, nullable) NSArray<AVAudioSessionDataSourceDescription *> *outputDataSources;
179@property(readonly, nullable) AVAudioSessionDataSourceDescription *outputDataSource;
180@property(readonly) double sampleRate;
181@property(readonly) double preferredSampleRate;
182@property(readonly) NSInteger inputNumberOfChannels;
183@property(readonly) NSInteger outputNumberOfChannels;
184@property(readonly) float outputVolume;
185@property(readonly) NSTimeInterval inputLatency;
186@property(readonly) NSTimeInterval outputLatency;
187@property(readonly) NSTimeInterval IOBufferDuration;
188@property(readonly) NSTimeInterval preferredIOBufferDuration;
189
Joe Chen0c05b1a2019-05-07 17:46:22190/**
191 When YES, calls to -setConfiguration:error: and -setConfiguration:active:error: ignore errors in
192 configuring the audio session's "preferred" attributes (e.g. preferredInputNumberOfChannels).
193 Typically, configurations to preferred attributes are optimizations, and ignoring this type of
194 configuration error allows code flow to continue along the happy path when these optimization are
195 not available. The default value of this property is NO.
196 */
197@property(nonatomic) BOOL ignoresPreferredAttributeConfigurationErrors;
198
Anders Carlsson7bca8ca2018-08-30 07:30:29199/** Default constructor. */
200+ (instancetype)sharedInstance;
201- (instancetype)init NS_UNAVAILABLE;
202
203/** Adds a delegate, which is held weakly. */
Mirko Bonadeia81e9c82020-05-04 14:14:32204- (void)addDelegate:(id<RTC_OBJC_TYPE(RTCAudioSessionDelegate)>)delegate;
Anders Carlsson7bca8ca2018-08-30 07:30:29205/** Removes an added delegate. */
Mirko Bonadeia81e9c82020-05-04 14:14:32206- (void)removeDelegate:(id<RTC_OBJC_TYPE(RTCAudioSessionDelegate)>)delegate;
Anders Carlsson7bca8ca2018-08-30 07:30:29207
208/** Request exclusive access to the audio session for configuration. This call
209 * will block if the lock is held by another object.
210 */
211- (void)lockForConfiguration;
212/** Relinquishes exclusive access to the audio session. */
213- (void)unlockForConfiguration;
214
Artem Titovd7ac5812021-07-27 10:23:39215/** If `active`, activates the audio session if it isn't already active.
Anders Carlsson7bca8ca2018-08-30 07:30:29216 * Successful calls must be balanced with a setActive:NO when activation is no
Artem Titovd7ac5812021-07-27 10:23:39217 * longer required. If not `active`, deactivates the audio session if one is
Anders Carlsson7bca8ca2018-08-30 07:30:29218 * active and this is the last balanced call. When deactivating, the
219 * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to
220 * AVAudioSession.
221 */
222- (BOOL)setActive:(BOOL)active error:(NSError **)outError;
223
224// The following methods are proxies for the associated methods on
Artem Titovd7ac5812021-07-27 10:23:39225// AVAudioSession. `lockForConfiguration` must be called before using them
Anders Carlsson7bca8ca2018-08-30 07:30:29226// otherwise they will fail with kRTCAudioSessionErrorLockRequired.
227
Abby Yehde923382023-06-12 11:05:29228- (BOOL)setCategory:(AVAudioSessionCategory)category
229 mode:(AVAudioSessionMode)mode
Abby Yeh47bdcc12023-06-11 07:35:07230 options:(AVAudioSessionCategoryOptions)options
231 error:(NSError **)outError;
Abby Yehde923382023-06-12 11:05:29232- (BOOL)setCategory:(AVAudioSessionCategory)category
Anders Carlsson7bca8ca2018-08-30 07:30:29233 withOptions:(AVAudioSessionCategoryOptions)options
234 error:(NSError **)outError;
Abby Yehde923382023-06-12 11:05:29235- (BOOL)setMode:(AVAudioSessionMode)mode error:(NSError **)outError;
Anders Carlsson7bca8ca2018-08-30 07:30:29236- (BOOL)setInputGain:(float)gain error:(NSError **)outError;
237- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError;
238- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError **)outError;
239- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count error:(NSError **)outError;
240- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count error:(NSError **)outError;
241- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride error:(NSError **)outError;
242- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort error:(NSError **)outError;
243- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
244 error:(NSError **)outError;
245- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
246 error:(NSError **)outError;
247@end
248
Mirko Bonadeia81e9c82020-05-04 14:14:32249@interface RTC_OBJC_TYPE (RTCAudioSession)
250(Configuration)
Anders Carlsson7bca8ca2018-08-30 07:30:29251
Mirko Bonadeia81e9c82020-05-04 14:14:32252 /** Applies the configuration to the current session. Attempts to set all
253 * properties even if previous ones fail. Only the last error will be
254 * returned.
Artem Titovd7ac5812021-07-27 10:23:39255 * `lockForConfiguration` must be called first.
Mirko Bonadeia81e9c82020-05-04 14:14:32256 */
257 - (BOOL)setConfiguration : (RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration error
258 : (NSError **)outError;
Anders Carlsson7bca8ca2018-08-30 07:30:29259
260/** Convenience method that calls both setConfiguration and setActive.
Artem Titovd7ac5812021-07-27 10:23:39261 * `lockForConfiguration` must be called first.
Anders Carlsson7bca8ca2018-08-30 07:30:29262 */
Mirko Bonadeia81e9c82020-05-04 14:14:32263- (BOOL)setConfiguration:(RTC_OBJC_TYPE(RTCAudioSessionConfiguration) *)configuration
Anders Carlsson7bca8ca2018-08-30 07:30:29264 active:(BOOL)active
265 error:(NSError **)outError;
266
267@end
268
269NS_ASSUME_NONNULL_END