RTCAudioSession.h 11 KB

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