blob: 199fd17b285684d8b4e8cb5ed732249d32f7e2fb [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
tkchin5fa51e22016-10-05 13:16:03 -070014#import "WebRTC/RTCMacros.h"
15
Zeke Chinb3fb71c2016-02-18 15:44:07 -080016NS_ASSUME_NONNULL_BEGIN
17
18extern NSString * const kRTCAudioSessionErrorDomain;
tkchin9f987d32016-03-12 20:06:28 -080019/** Method that requires lock was called without lock. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080020extern NSInteger const kRTCAudioSessionErrorLockRequired;
tkchin9f987d32016-03-12 20:06:28 -080021/** Unknown configuration error occurred. */
22extern NSInteger const kRTCAudioSessionErrorConfiguration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080023
24@class RTCAudioSession;
tkchin9f987d32016-03-12 20:06:28 -080025@class RTCAudioSessionConfiguration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080026
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.
tkchin5fa51e22016-10-05 13:16:03 -070030RTC_EXPORT
Zeke Chinb3fb71c2016-02-18 15:44:07 -080031@protocol RTCAudioSessionDelegate <NSObject>
32
Tze Kwang Chin307a0922016-03-21 13:57:40 -070033@optional
34/** Called on a system notification thread when AVAudioSession starts an
35 * interruption event.
36 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080037- (void)audioSessionDidBeginInterruption:(RTCAudioSession *)session;
38
Tze Kwang Chin307a0922016-03-21 13:57:40 -070039/** Called on a system notification thread when AVAudioSession ends an
40 * interruption event.
41 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080042- (void)audioSessionDidEndInterruption:(RTCAudioSession *)session
43 shouldResumeSession:(BOOL)shouldResumeSession;
44
Tze Kwang Chin307a0922016-03-21 13:57:40 -070045/** Called on a system notification thread when AVAudioSession changes the
46 * route.
47 */
Zeke Chinb3fb71c2016-02-18 15:44:07 -080048- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
49 reason:(AVAudioSessionRouteChangeReason)reason
50 previousRoute:(AVAudioSessionRouteDescription *)previousRoute;
51
Tze Kwang Chin307a0922016-03-21 13:57:40 -070052/** Called on a system notification thread when AVAudioSession media server
53 * terminates.
54 */
kthelgason1634e162017-02-07 02:48:55 -080055- (void)audioSessionMediaServerTerminated:(RTCAudioSession *)session;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080056
Tze Kwang Chin307a0922016-03-21 13:57:40 -070057/** Called on a system notification thread when AVAudioSession media server
58 * restarts.
59 */
kthelgason1634e162017-02-07 02:48:55 -080060- (void)audioSessionMediaServerReset:(RTCAudioSession *)session;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080061
Tze Kwang Chin307a0922016-03-21 13:57:40 -070062// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification.
63
tkchind2511962016-05-06 18:54:15 -070064- (void)audioSession:(RTCAudioSession *)session
65 didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord;
tkchin9f987d32016-03-12 20:06:28 -080066
tkchind2511962016-05-06 18:54:15 -070067/** Called on a WebRTC thread when the audio device is notified to begin
68 * playback or recording.
tkchin9f987d32016-03-12 20:06:28 -080069 */
tkchind2511962016-05-06 18:54:15 -070070- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session;
tkchin9f987d32016-03-12 20:06:28 -080071
tkchind2511962016-05-06 18:54:15 -070072/** Called on a WebRTC thread when the audio device is notified to stop
73 * playback or recording.
Tze Kwang Chin307a0922016-03-21 13:57:40 -070074 */
tkchind2511962016-05-06 18:54:15 -070075- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session;
Zeke Chinb3fb71c2016-02-18 15:44:07 -080076
77@end
78
79/** Proxy class for AVAudioSession that adds a locking mechanism similar to
80 * AVCaptureDevice. This is used to that interleaving configurations between
Tze Kwang Chin307a0922016-03-21 13:57:40 -070081 * WebRTC and the application layer are avoided.
Zeke Chinb3fb71c2016-02-18 15:44:07 -080082 *
83 * RTCAudioSession also coordinates activation so that the audio session is
84 * activated only once. See |setActive:error:|.
85 */
tkchin5fa51e22016-10-05 13:16:03 -070086RTC_EXPORT
Zeke Chinb3fb71c2016-02-18 15:44:07 -080087@interface RTCAudioSession : NSObject
88
89/** Convenience property to access the AVAudioSession singleton. Callers should
90 * not call setters on AVAudioSession directly, but other method invocations
91 * are fine.
92 */
93@property(nonatomic, readonly) AVAudioSession *session;
94
95/** Our best guess at whether the session is active based on results of calls to
96 * AVAudioSession.
97 */
98@property(nonatomic, readonly) BOOL isActive;
99/** Whether RTCAudioSession is currently locked for configuration. */
100@property(nonatomic, readonly) BOOL isLocked;
101
tkchin9f987d32016-03-12 20:06:28 -0800102/** If YES, WebRTC will not initialize the audio unit automatically when an
103 * audio track is ready for playout or recording. Instead, applications should
tkchind2511962016-05-06 18:54:15 -0700104 * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit
105 * as soon as an audio track is ready for playout or recording.
tkchin9f987d32016-03-12 20:06:28 -0800106 */
tkchind2511962016-05-06 18:54:15 -0700107@property(nonatomic, assign) BOOL useManualAudio;
108
109/** This property is only effective if useManualAudio is YES.
110 * Represents permission for WebRTC to initialize the VoIP audio unit.
111 * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be
112 * stopped and uninitialized. This will stop incoming and outgoing audio.
113 * When set to YES, WebRTC will initialize and start the audio unit when it is
114 * needed (e.g. due to establishing an audio connection).
115 * This property was introduced to work around an issue where if an AVPlayer is
116 * playing audio while the VoIP audio unit is initialized, its audio would be
117 * either cut off completely or played at a reduced volume. By preventing
118 * the audio unit from being initialized until after the audio has completed,
119 * we are able to prevent the abrupt cutoff.
120 */
121@property(nonatomic, assign) BOOL isAudioEnabled;
tkchin9f987d32016-03-12 20:06:28 -0800122
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800123// Proxy properties.
124@property(readonly) NSString *category;
125@property(readonly) AVAudioSessionCategoryOptions categoryOptions;
126@property(readonly) NSString *mode;
127@property(readonly) BOOL secondaryAudioShouldBeSilencedHint;
128@property(readonly) AVAudioSessionRouteDescription *currentRoute;
129@property(readonly) NSInteger maximumInputNumberOfChannels;
130@property(readonly) NSInteger maximumOutputNumberOfChannels;
131@property(readonly) float inputGain;
132@property(readonly) BOOL inputGainSettable;
133@property(readonly) BOOL inputAvailable;
134@property(readonly, nullable)
135 NSArray<AVAudioSessionDataSourceDescription *> * inputDataSources;
136@property(readonly, nullable)
137 AVAudioSessionDataSourceDescription *inputDataSource;
138@property(readonly, nullable)
139 NSArray<AVAudioSessionDataSourceDescription *> * outputDataSources;
140@property(readonly, nullable)
141 AVAudioSessionDataSourceDescription *outputDataSource;
142@property(readonly) double sampleRate;
tkchind2511962016-05-06 18:54:15 -0700143@property(readonly) double preferredSampleRate;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800144@property(readonly) NSInteger inputNumberOfChannels;
145@property(readonly) NSInteger outputNumberOfChannels;
146@property(readonly) float outputVolume;
147@property(readonly) NSTimeInterval inputLatency;
148@property(readonly) NSTimeInterval outputLatency;
149@property(readonly) NSTimeInterval IOBufferDuration;
tkchind2511962016-05-06 18:54:15 -0700150@property(readonly) NSTimeInterval preferredIOBufferDuration;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800151
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700152/** Default constructor. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800153+ (instancetype)sharedInstance;
Tze Kwang Chin307a0922016-03-21 13:57:40 -0700154- (instancetype)init NS_UNAVAILABLE;
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800155
tkchine54467f2016-03-15 16:54:03 -0700156/** Adds a delegate, which is held weakly. */
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800157- (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate;
158/** Removes an added delegate. */
159- (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate;
160
161/** Request exclusive access to the audio session for configuration. This call
162 * will block if the lock is held by another object.
163 */
164- (void)lockForConfiguration;
165/** Relinquishes exclusive access to the audio session. */
166- (void)unlockForConfiguration;
167
168/** If |active|, activates the audio session if it isn't already active.
169 * Successful calls must be balanced with a setActive:NO when activation is no
170 * longer required. If not |active|, deactivates the audio session if one is
171 * active and this is the last balanced call. When deactivating, the
172 * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to
173 * AVAudioSession.
174 */
175- (BOOL)setActive:(BOOL)active
176 error:(NSError **)outError;
177
178// The following methods are proxies for the associated methods on
179// AVAudioSession. |lockForConfiguration| must be called before using them
180// otherwise they will fail with kRTCAudioSessionErrorLockRequired.
181
182- (BOOL)setCategory:(NSString *)category
183 withOptions:(AVAudioSessionCategoryOptions)options
184 error:(NSError **)outError;
185- (BOOL)setMode:(NSString *)mode error:(NSError **)outError;
186- (BOOL)setInputGain:(float)gain error:(NSError **)outError;
187- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError;
188- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration
189 error:(NSError **)outError;
190- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count
191 error:(NSError **)outError;
192- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count
193 error:(NSError **)outError;
194- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride
195 error:(NSError **)outError;
196- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort
197 error:(NSError **)outError;
198- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
199 error:(NSError **)outError;
200- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource
201 error:(NSError **)outError;
202
203@end
204
tkchin9f987d32016-03-12 20:06:28 -0800205@interface RTCAudioSession (Configuration)
206
207/** Applies the configuration to the current session. Attempts to set all
208 * properties even if previous ones fail. Only the last error will be
tkchind2511962016-05-06 18:54:15 -0700209 * returned.
210 * |lockForConfiguration| must be called first.
211 */
212- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
213 error:(NSError **)outError;
214
215/** Convenience method that calls both setConfiguration and setActive.
tkchin9f987d32016-03-12 20:06:28 -0800216 * |lockForConfiguration| must be called first.
217 */
218- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration
219 active:(BOOL)active
220 error:(NSError **)outError;
221
tkchin9f987d32016-03-12 20:06:28 -0800222@end
223
Zeke Chinb3fb71c2016-02-18 15:44:07 -0800224NS_ASSUME_NONNULL_END