blob: 274cc2bc978ca849f516032c52b5b2f1fa2da6c5 [file] [log] [blame]
Zeke Chinb3fb71c2016-02-18 15:44:07 -08001/*
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
14NS_ASSUME_NONNULL_BEGIN
15
16extern NSString * const kRTCAudioSessionErrorDomain;
tkchin9f987d32016-03-12 20:06:28 -080017/** Method that requires lock was called without lock. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080018extern NSInteger const kRTCAudioSessionErrorLockRequired;
tkchin9f987d32016-03-12 20:06:28 -080019/** Unknown configuration error occurred. */
20extern NSInteger const kRTCAudioSessionErrorConfiguration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080021
22@class RTCAudioSession;
tkchin9f987d32016-03-12 20:06:28 -080023@class RTCAudioSessionConfiguration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080024
25// Surfaces AVAudioSession events. WebRTC will listen directly for notifications
26// from AVAudioSession and handle them before calling these delegate methods,
27// at which point applications can perform additional processing if required.
28@protocol RTCAudioSessionDelegate <NSObject>
29
Tze Kwang Chin307a0922016-03-21 13:57:40 -070030@optional
31/** Called on a system notification thread when AVAudioSession starts an
32 * interruption event.
33 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080034- (void)audioSessionDidBeginInterruption:(RTCAudioSession *)session;
35
Tze Kwang Chin307a0922016-03-21 13:57:40 -070036/** Called on a system notification thread when AVAudioSession ends an
37 * interruption event.
38 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080039- (void)audioSessionDidEndInterruption:(RTCAudioSession *)session
40 shouldResumeSession:(BOOL)shouldResumeSession;
41
Tze Kwang Chin307a0922016-03-21 13:57:40 -070042/** Called on a system notification thread when AVAudioSession changes the
43 * route.
44 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080045- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
46 reason:(AVAudioSessionRouteChangeReason)reason
47 previousRoute:(AVAudioSessionRouteDescription *)previousRoute;
48
Tze Kwang Chin307a0922016-03-21 13:57:40 -070049/** Called on a system notification thread when AVAudioSession media server
50 * terminates.
51 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080052- (void)audioSessionMediaServicesWereLost:(RTCAudioSession *)session;
53
Tze Kwang Chin307a0922016-03-21 13:57:40 -070054/** Called on a system notification thread when AVAudioSession media server
55 * restarts.
56 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080057- (void)audioSessionMediaServicesWereReset:(RTCAudioSession *)session;
58
Tze Kwang Chin307a0922016-03-21 13:57:40 -070059// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification.
60
tkchind2511962016-05-06 18:54:15 -070061- (void)audioSession:(RTCAudioSession *)session
62 didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord;
tkchin9f987d32016-03-12 20:06:28 -080063
tkchind2511962016-05-06 18:54:15 -070064/** Called on a WebRTC thread when the audio device is notified to begin
65 * playback or recording.
tkchin9f987d32016-03-12 20:06:28 -080066 */
tkchind2511962016-05-06 18:54:15 -070067- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session;
tkchin9f987d32016-03-12 20:06:28 -080068
tkchind2511962016-05-06 18:54:15 -070069/** Called on a WebRTC thread when the audio device is notified to stop
70 * playback or recording.
Tze Kwang Chin307a0922016-03-21 13:57:40 -070071 */
tkchind2511962016-05-06 18:54:15 -070072- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080073
74@end
75
76/** Proxy class for AVAudioSession that adds a locking mechanism similar to
77 * AVCaptureDevice. This is used to that interleaving configurations between
Tze Kwang Chin307a0922016-03-21 13:57:40 -070078 * WebRTC and the application layer are avoided.
Zeke Chinb3fb71c2016-02-18 15:44:07 -080079 *
80 * RTCAudioSession also coordinates activation so that the audio session is
81 * activated only once. See |setActive:error:|.
82 */
83@interface RTCAudioSession : NSObject
84
85/** Convenience property to access the AVAudioSession singleton. Callers should
86 * not call setters on AVAudioSession directly, but other method invocations
87 * are fine.
88 */
89@property(nonatomic, readonly) AVAudioSession *session;
90
91/** Our best guess at whether the session is active based on results of calls to
92 * AVAudioSession.
93 */
94@property(nonatomic, readonly) BOOL isActive;
95/** Whether RTCAudioSession is currently locked for configuration. */
96@property(nonatomic, readonly) BOOL isLocked;
97
tkchin9f987d32016-03-12 20:06:28 -080098/** If YES, WebRTC will not initialize the audio unit automatically when an
99 * audio track is ready for playout or recording. Instead, applications should
tkchind2511962016-05-06 18:54:15 -0700100 * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit
101 * as soon as an audio track is ready for playout or recording.
tkchin9f987d32016-03-12 20:06:28 -0800102 */
tkchind2511962016-05-06 18:54:15 -0700103@property(nonatomic, assign) BOOL useManualAudio;
104
105/** This property is only effective if useManualAudio is YES.
106 * Represents permission for WebRTC to initialize the VoIP audio unit.
107 * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be
108 * stopped and uninitialized. This will stop incoming and outgoing audio.
109 * When set to YES, WebRTC will initialize and start the audio unit when it is
110 * needed (e.g. due to establishing an audio connection).
111 * This property was introduced to work around an issue where if an AVPlayer is
112 * playing audio while the VoIP audio unit is initialized, its audio would be
113 * either cut off completely or played at a reduced volume. By preventing
114 * the audio unit from being initialized until after the audio has completed,
115 * we are able to prevent the abrupt cutoff.
116 */
117@property(nonatomic, assign) BOOL isAudioEnabled;
tkchin9f987d32016-03-12 20:06:28 -0800118
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800119// Proxy properties.
120@property(readonly) NSString *category;
121@property(readonly) AVAudioSessionCategoryOptions categoryOptions;
122@property(readonly) NSString *mode;
123@property(readonly) BOOL secondaryAudioShouldBeSilencedHint;
124@property(readonly) AVAudioSessionRouteDescription *currentRoute;
125@property(readonly) NSInteger maximumInputNumberOfChannels;
126@property(readonly) NSInteger maximumOutputNumberOfChannels;
127@property(readonly) float inputGain;
128@property(readonly) BOOL inputGainSettable;
129@property(readonly) BOOL inputAvailable;
130@property(readonly, nullable)
131 NSArray<AVAudioSessionDataSourceDescription *> * inputDataSources;
132@property(readonly, nullable)
133 AVAudioSessionDataSourceDescription *inputDataSource;
134@property(readonly, nullable)
135 NSArray<AVAudioSessionDataSourceDescription *> * outputDataSources;
136@property(readonly, nullable)
137 AVAudioSessionDataSourceDescription *outputDataSource;
138@property(readonly) double sampleRate;
tkchind2511962016-05-06 18:54:15 -0700139@property(readonly) double preferredSampleRate;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800140@property(readonly) NSInteger inputNumberOfChannels;
141@property(readonly) NSInteger outputNumberOfChannels;
142@property(readonly) float outputVolume;
143@property(readonly) NSTimeInterval inputLatency;
144@property(readonly) NSTimeInterval outputLatency;
145@property(readonly) NSTimeInterval IOBufferDuration;
tkchind2511962016-05-06 18:54:15 -0700146@property(readonly) NSTimeInterval preferredIOBufferDuration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800147
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700148/** Default constructor. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800149+ (instancetype)sharedInstance;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700150- (instancetype)init NS_UNAVAILABLE;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800151
tkchine54467f2016-03-15 16:54:03 -0700152/** Adds a delegate, which is held weakly. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800153- (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate;
154/** Removes an added delegate. */
155- (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate;
156
157/** Request exclusive access to the audio session for configuration. This call
158 * will block if the lock is held by another object.
159 */
160- (void)lockForConfiguration;
161/** Relinquishes exclusive access to the audio session. */
162- (void)unlockForConfiguration;
163
164/** If |active|, activates the audio session if it isn't already active.
165 * Successful calls must be balanced with a setActive:NO when activation is no
166 * longer required. If not |active|, deactivates the audio session if one is
167 * active and this is the last balanced call. When deactivating, the
168 * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to
169 * AVAudioSession.
170 */
171- (BOOL)setActive:(BOOL)active
172 error:(NSError **)outError;
173
174// The following methods are proxies for the associated methods on
175// AVAudioSession. |lockForConfiguration| must be called before using them
176// otherwise they will fail with kRTCAudioSessionErrorLockRequired.
177
178- (BOOL)setCategory:(NSString *)category
179 withOptions:(AVAudioSessionCategoryOptions)options
180 error:(NSError **)outError;
181- (BOOL)setMode:(NSString *)mode error:(NSError **)outError;
182- (BOOL)setInputGain:(float)gain error:(NSError **)outError;
183- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError;
184- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration
185 error:(NSError **)outError;
186- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count
187 error:(NSError **)outError;
188- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count
189 error:(NSError **)outError;
190- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride
191 error:(NSError **)outError;
192- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort
193 error:(NSError **)outError;
194- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
195 error:(NSError **)outError;
196- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
197 error:(NSError **)outError;
198
199@end
200
tkchin9f987d32016-03-12 20:06:28 -0800201@interface RTCAudioSession (Configuration)
202
203/** Applies the configuration to the current session. Attempts to set all
204 * properties even if previous ones fail. Only the last error will be
tkchind2511962016-05-06 18:54:15 -0700205 * returned.
206 * |lockForConfiguration| must be called first.
207 */
208- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
209 error:(NSError **)outError;
210
211/** Convenience method that calls both setConfiguration and setActive.
tkchin9f987d32016-03-12 20:06:28 -0800212 * |lockForConfiguration| must be called first.
213 */
214- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
215 active:(BOOL)active
216 error:(NSError **)outError;
217
tkchin9f987d32016-03-12 20:06:28 -0800218@end
219
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800220NS_ASSUME_NONNULL_END