blob: 15b63d39dc4c138883fec24eb2fdeeb610d612ff [file] [log] [blame]
denicija59ee91b2017-06-05 05:48:47 -07001/*
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
Anders Carlsson8ecfd802017-09-15 14:07:30 +020014#import <WebRTC/RTCMacros.h>
denicija59ee91b2017-06-05 05:48:47 -070015
16NS_ASSUME_NONNULL_BEGIN
17
Yves Gerey665174f2018-06-19 15:03:05 +020018extern NSString *const kRTCAudioSessionErrorDomain;
denicija59ee91b2017-06-05 05:48:47 -070019/** Method that requires lock was called without lock. */
20extern NSInteger const kRTCAudioSessionErrorLockRequired;
21/** Unknown configuration error occurred. */
22extern NSInteger const kRTCAudioSessionErrorConfiguration;
23
24@class RTCAudioSession;
25@class RTCAudioSessionConfiguration;
26
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.
30RTC_EXPORT
31@protocol RTCAudioSessionDelegate <NSObject>
32
33@optional
34/** Called on a system notification thread when AVAudioSession starts an
35 * interruption event.
36 */
37- (void)audioSessionDidBeginInterruption:(RTCAudioSession *)session;
38
39/** Called on a system notification thread when AVAudioSession ends an
40 * interruption event.
41 */
42- (void)audioSessionDidEndInterruption:(RTCAudioSession *)session
43 shouldResumeSession:(BOOL)shouldResumeSession;
44
45/** Called on a system notification thread when AVAudioSession changes the
46 * route.
47 */
48- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
Yves Gerey665174f2018-06-19 15:03:05 +020049 reason:(AVAudioSessionRouteChangeReason)reason
50 previousRoute:(AVAudioSessionRouteDescription *)previousRoute;
denicija59ee91b2017-06-05 05:48:47 -070051
52/** Called on a system notification thread when AVAudioSession media server
53 * terminates.
54 */
55- (void)audioSessionMediaServerTerminated:(RTCAudioSession *)session;
56
57/** Called on a system notification thread when AVAudioSession media server
58 * restarts.
59 */
60- (void)audioSessionMediaServerReset:(RTCAudioSession *)session;
61
62// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification.
63
Yves Gerey665174f2018-06-19 15:03:05 +020064- (void)audioSession:(RTCAudioSession *)session didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord;
denicija59ee91b2017-06-05 05:48:47 -070065
66/** Called on a WebRTC thread when the audio device is notified to begin
67 * playback or recording.
68 */
69- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session;
70
71/** Called on a WebRTC thread when the audio device is notified to stop
72 * playback or recording.
73 */
74- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session;
75
76/** Called when the AVAudioSession output volume value changes. */
Yves Gerey665174f2018-06-19 15:03:05 +020077- (void)audioSession:(RTCAudioSession *)audioSession didChangeOutputVolume:(float)outputVolume;
denicija59ee91b2017-06-05 05:48:47 -070078
Anders Carlsson121ea322017-06-26 15:34:47 +020079/** Called when the audio device detects a playout glitch. The argument is the
80 * number of glitches detected so far in the current audio playout session.
81 */
82- (void)audioSession:(RTCAudioSession *)audioSession
83 didDetectPlayoutGlitch:(int64_t)totalNumberOfGlitches;
84
JT Tehc1f083d2018-04-25 09:19:35 -070085/** Called when the audio session is about to change the active state.
86 */
87- (void)audioSession:(RTCAudioSession *)audioSession willSetActive:(BOOL)active;
88
89/** Called after the audio session sucessfully changed the active state.
90 */
91- (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active;
92
93/** Called after the audio session failed to change the active state.
94 */
95- (void)audioSession:(RTCAudioSession *)audioSession
96 failedToSetActive:(BOOL)active
97 error:(NSError *)error;
98
denicija59ee91b2017-06-05 05:48:47 -070099@end
100
101/** This is a protocol used to inform RTCAudioSession when the audio session
102 * activation state has changed outside of RTCAudioSession. The current known use
103 * case of this is when CallKit activates the audio session for the application
104 */
105RTC_EXPORT
106@protocol RTCAudioSessionActivationDelegate <NSObject>
107
108/** Called when the audio session is activated outside of the app by iOS. */
109- (void)audioSessionDidActivate:(AVAudioSession *)session;
110
111/** Called when the audio session is deactivated outside of the app by iOS. */
112- (void)audioSessionDidDeactivate:(AVAudioSession *)session;
113
114@end
115
116/** Proxy class for AVAudioSession that adds a locking mechanism similar to
117 * AVCaptureDevice. This is used to that interleaving configurations between
118 * WebRTC and the application layer are avoided.
119 *
120 * RTCAudioSession also coordinates activation so that the audio session is
121 * activated only once. See |setActive:error:|.
122 */
123RTC_EXPORT
124@interface RTCAudioSession : NSObject <RTCAudioSessionActivationDelegate>
125
126/** Convenience property to access the AVAudioSession singleton. Callers should
127 * not call setters on AVAudioSession directly, but other method invocations
128 * are fine.
129 */
130@property(nonatomic, readonly) AVAudioSession *session;
131
132/** Our best guess at whether the session is active based on results of calls to
133 * AVAudioSession.
134 */
135@property(nonatomic, readonly) BOOL isActive;
136/** Whether RTCAudioSession is currently locked for configuration. */
137@property(nonatomic, readonly) BOOL isLocked;
138
139/** If YES, WebRTC will not initialize the audio unit automatically when an
140 * audio track is ready for playout or recording. Instead, applications should
141 * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit
142 * as soon as an audio track is ready for playout or recording.
143 */
144@property(nonatomic, assign) BOOL useManualAudio;
145
146/** This property is only effective if useManualAudio is YES.
147 * Represents permission for WebRTC to initialize the VoIP audio unit.
148 * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be
149 * stopped and uninitialized. This will stop incoming and outgoing audio.
150 * When set to YES, WebRTC will initialize and start the audio unit when it is
151 * needed (e.g. due to establishing an audio connection).
152 * This property was introduced to work around an issue where if an AVPlayer is
153 * playing audio while the VoIP audio unit is initialized, its audio would be
154 * either cut off completely or played at a reduced volume. By preventing
155 * the audio unit from being initialized until after the audio has completed,
156 * we are able to prevent the abrupt cutoff.
157 */
158@property(nonatomic, assign) BOOL isAudioEnabled;
159
160// Proxy properties.
161@property(readonly) NSString *category;
162@property(readonly) AVAudioSessionCategoryOptions categoryOptions;
163@property(readonly) NSString *mode;
164@property(readonly) BOOL secondaryAudioShouldBeSilencedHint;
165@property(readonly) AVAudioSessionRouteDescription *currentRoute;
166@property(readonly) NSInteger maximumInputNumberOfChannels;
167@property(readonly) NSInteger maximumOutputNumberOfChannels;
168@property(readonly) float inputGain;
169@property(readonly) BOOL inputGainSettable;
170@property(readonly) BOOL inputAvailable;
Yves Gerey665174f2018-06-19 15:03:05 +0200171@property(readonly, nullable) NSArray<AVAudioSessionDataSourceDescription *> *inputDataSources;
172@property(readonly, nullable) AVAudioSessionDataSourceDescription *inputDataSource;
173@property(readonly, nullable) NSArray<AVAudioSessionDataSourceDescription *> *outputDataSources;
174@property(readonly, nullable) AVAudioSessionDataSourceDescription *outputDataSource;
denicija59ee91b2017-06-05 05:48:47 -0700175@property(readonly) double sampleRate;
176@property(readonly) double preferredSampleRate;
177@property(readonly) NSInteger inputNumberOfChannels;
178@property(readonly) NSInteger outputNumberOfChannels;
179@property(readonly) float outputVolume;
180@property(readonly) NSTimeInterval inputLatency;
181@property(readonly) NSTimeInterval outputLatency;
182@property(readonly) NSTimeInterval IOBufferDuration;
183@property(readonly) NSTimeInterval preferredIOBufferDuration;
184
185/** Default constructor. */
186+ (instancetype)sharedInstance;
187- (instancetype)init NS_UNAVAILABLE;
188
189/** Adds a delegate, which is held weakly. */
190- (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate;
191/** Removes an added delegate. */
192- (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate;
193
194/** Request exclusive access to the audio session for configuration. This call
195 * will block if the lock is held by another object.
196 */
197- (void)lockForConfiguration;
198/** Relinquishes exclusive access to the audio session. */
199- (void)unlockForConfiguration;
200
201/** If |active|, activates the audio session if it isn't already active.
202 * Successful calls must be balanced with a setActive:NO when activation is no
203 * longer required. If not |active|, deactivates the audio session if one is
204 * active and this is the last balanced call. When deactivating, the
205 * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to
206 * AVAudioSession.
207 */
Yves Gerey665174f2018-06-19 15:03:05 +0200208- (BOOL)setActive:(BOOL)active error:(NSError **)outError;
denicija59ee91b2017-06-05 05:48:47 -0700209
210// The following methods are proxies for the associated methods on
211// AVAudioSession. |lockForConfiguration| must be called before using them
212// otherwise they will fail with kRTCAudioSessionErrorLockRequired.
213
214- (BOOL)setCategory:(NSString *)category
215 withOptions:(AVAudioSessionCategoryOptions)options
216 error:(NSError **)outError;
217- (BOOL)setMode:(NSString *)mode error:(NSError **)outError;
218- (BOOL)setInputGain:(float)gain error:(NSError **)outError;
219- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError;
Yves Gerey665174f2018-06-19 15:03:05 +0200220- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration error:(NSError **)outError;
221- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count error:(NSError **)outError;
222- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count error:(NSError **)outError;
223- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride error:(NSError **)outError;
224- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort error:(NSError **)outError;
denicija59ee91b2017-06-05 05:48:47 -0700225- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
226 error:(NSError **)outError;
227- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
228 error:(NSError **)outError;
229@end
230
231@interface RTCAudioSession (Configuration)
232
233/** Applies the configuration to the current session. Attempts to set all
234 * properties even if previous ones fail. Only the last error will be
235 * returned.
236 * |lockForConfiguration| must be called first.
237 */
Yves Gerey665174f2018-06-19 15:03:05 +0200238- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration error:(NSError **)outError;
denicija59ee91b2017-06-05 05:48:47 -0700239
240/** Convenience method that calls both setConfiguration and setActive.
241 * |lockForConfiguration| must be called first.
242 */
243- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
244 active:(BOOL)active
245 error:(NSError **)outError;
246
247@end
248
249NS_ASSUME_NONNULL_END