RTCAudioSession.h 10 KB

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