diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m index dca48b60c3..0e93aae9ad 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDMainViewController.m @@ -12,10 +12,11 @@ #import +#import "WebRTC/RTCAudioSession.h" +#import "WebRTC/RTCAudioSessionConfiguration.h" #import "WebRTC/RTCDispatcher.h" #import "WebRTC/RTCLogging.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" + #import "ARDAppClient.h" #import "ARDMainView.h" diff --git a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m index 9a9b9c5b31..fd33e01e71 100644 --- a/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m +++ b/webrtc/examples/objc/AppRTCMobile/ios/ARDVideoCallViewController.m @@ -10,7 +10,7 @@ #import "ARDVideoCallViewController.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" +#import "WebRTC/RTCAudioSession.h" #import "ARDAppClient.h" #import "ARDCaptureController.h" diff --git a/webrtc/modules/audio_device/BUILD.gn b/webrtc/modules/audio_device/BUILD.gn index b8d884a19f..b3ba8524a8 100644 --- a/webrtc/modules/audio_device/BUILD.gn +++ b/webrtc/modules/audio_device/BUILD.gn @@ -176,6 +176,7 @@ rtc_static_library("audio_device") { public_deps = [ "../../base:gtest_prod", "../../base:rtc_base", + "../../sdk:objc_audio", "../../sdk:objc_common", ] sources += [ @@ -183,12 +184,6 @@ rtc_static_library("audio_device") { "ios/audio_device_ios.mm", "ios/audio_device_not_implemented_ios.mm", "ios/audio_session_observer.h", - "ios/objc/RTCAudioSession+Configuration.mm", - "ios/objc/RTCAudioSession+Private.h", - "ios/objc/RTCAudioSession.h", - "ios/objc/RTCAudioSession.mm", - "ios/objc/RTCAudioSessionConfiguration.h", - "ios/objc/RTCAudioSessionConfiguration.m", "ios/objc/RTCAudioSessionDelegateAdapter.h", "ios/objc/RTCAudioSessionDelegateAdapter.mm", "ios/voice_processing_audio_unit.h", @@ -310,10 +305,7 @@ if (rtc_include_tests) { ] } if (is_ios) { - sources += [ - "ios/audio_device_unittest_ios.mm", - "ios/objc/RTCAudioSessionTest.mm", - ] + sources += [ "ios/audio_device_unittest_ios.mm" ] deps += [ "//third_party/ocmock" ] } if (!build_with_chromium && is_clang) { diff --git a/webrtc/modules/audio_device/DEPS b/webrtc/modules/audio_device/DEPS index d7f600cd93..8ad9db7a3b 100644 --- a/webrtc/modules/audio_device/DEPS +++ b/webrtc/modules/audio_device/DEPS @@ -11,4 +11,19 @@ specific_include_rules = { "audio_device_ios\.mm": [ "+webrtc/sdk/objc", ], + "audio_device_unittest_ios\.mm": [ + "+webrtc/sdk/objc", + ], + "RTCAudioSession\.h": [ + "+webrtc/sdk/objc", + ], + "RTCAudioSessionConfiguration\.h": [ + "+webrtc/sdk/objc", + ], + "RTCAudioSessionDelegateAdapter\.h": [ + "+webrtc/sdk/objc", + ], + "voice_processing_audio_unit\.mm": [ + "+webrtc/sdk/objc", + ], } diff --git a/webrtc/modules/audio_device/ios/audio_device_ios.mm b/webrtc/modules/audio_device/ios/audio_device_ios.mm index 798b543422..128ea53e22 100644 --- a/webrtc/modules/audio_device/ios/audio_device_ios.mm +++ b/webrtc/modules/audio_device/ios/audio_device_ios.mm @@ -27,10 +27,11 @@ #include "webrtc/sdk/objc/Framework/Classes/Common/helpers.h" #import "WebRTC/RTCLogging.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" #import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionDelegateAdapter.h" +#import "webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Private.h" +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h" +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h" + namespace webrtc { diff --git a/webrtc/modules/audio_device/ios/audio_device_unittest_ios.mm b/webrtc/modules/audio_device/ios/audio_device_unittest_ios.mm index cccbfbc246..2c22c0f0c7 100644 --- a/webrtc/modules/audio_device/ios/audio_device_unittest_ios.mm +++ b/webrtc/modules/audio_device/ios/audio_device_unittest_ios.mm @@ -31,8 +31,8 @@ #include "webrtc/test/gtest.h" #include "webrtc/test/testsupport/fileutils.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" +#import "webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Private.h" +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h" using std::cout; using std::endl; diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h index c0ea2163ae..2f52ca383d 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSession.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * Copyright 2017 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -8,235 +8,4 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import -#import - -#import "WebRTC/RTCMacros.h" - -NS_ASSUME_NONNULL_BEGIN - -extern NSString * const kRTCAudioSessionErrorDomain; -/** Method that requires lock was called without lock. */ -extern NSInteger const kRTCAudioSessionErrorLockRequired; -/** Unknown configuration error occurred. */ -extern NSInteger const kRTCAudioSessionErrorConfiguration; - -@class RTCAudioSession; -@class RTCAudioSessionConfiguration; - -// Surfaces AVAudioSession events. WebRTC will listen directly for notifications -// from AVAudioSession and handle them before calling these delegate methods, -// at which point applications can perform additional processing if required. -RTC_EXPORT -@protocol RTCAudioSessionDelegate - -@optional -/** Called on a system notification thread when AVAudioSession starts an - * interruption event. - */ -- (void)audioSessionDidBeginInterruption:(RTCAudioSession *)session; - -/** Called on a system notification thread when AVAudioSession ends an - * interruption event. - */ -- (void)audioSessionDidEndInterruption:(RTCAudioSession *)session - shouldResumeSession:(BOOL)shouldResumeSession; - -/** Called on a system notification thread when AVAudioSession changes the - * route. - */ -- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session - reason:(AVAudioSessionRouteChangeReason)reason - previousRoute:(AVAudioSessionRouteDescription *)previousRoute; - -/** Called on a system notification thread when AVAudioSession media server - * terminates. - */ -- (void)audioSessionMediaServerTerminated:(RTCAudioSession *)session; - -/** Called on a system notification thread when AVAudioSession media server - * restarts. - */ -- (void)audioSessionMediaServerReset:(RTCAudioSession *)session; - -// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification. - -- (void)audioSession:(RTCAudioSession *)session - didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord; - -/** Called on a WebRTC thread when the audio device is notified to begin - * playback or recording. - */ -- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session; - -/** Called on a WebRTC thread when the audio device is notified to stop - * playback or recording. - */ -- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session; - -/** Called when the AVAudioSession output volume value changes. */ -- (void)audioSession:(RTCAudioSession *)audioSession - didChangeOutputVolume:(float)outputVolume; - -@end - -/** This is a protocol used to inform RTCAudioSession when the audio session - * activation state has changed outside of RTCAudioSession. The current known use - * case of this is when CallKit activates the audio session for the application - */ -RTC_EXPORT -@protocol RTCAudioSessionActivationDelegate - -/** Called when the audio session is activated outside of the app by iOS. */ -- (void)audioSessionDidActivate:(AVAudioSession *)session; - -/** Called when the audio session is deactivated outside of the app by iOS. */ -- (void)audioSessionDidDeactivate:(AVAudioSession *)session; - -@end - -/** Proxy class for AVAudioSession that adds a locking mechanism similar to - * AVCaptureDevice. This is used to that interleaving configurations between - * WebRTC and the application layer are avoided. - * - * RTCAudioSession also coordinates activation so that the audio session is - * activated only once. See |setActive:error:|. - */ -RTC_EXPORT -@interface RTCAudioSession : NSObject - -/** Convenience property to access the AVAudioSession singleton. Callers should - * not call setters on AVAudioSession directly, but other method invocations - * are fine. - */ -@property(nonatomic, readonly) AVAudioSession *session; - -/** Our best guess at whether the session is active based on results of calls to - * AVAudioSession. - */ -@property(nonatomic, readonly) BOOL isActive; -/** Whether RTCAudioSession is currently locked for configuration. */ -@property(nonatomic, readonly) BOOL isLocked; - -/** If YES, WebRTC will not initialize the audio unit automatically when an - * audio track is ready for playout or recording. Instead, applications should - * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit - * as soon as an audio track is ready for playout or recording. - */ -@property(nonatomic, assign) BOOL useManualAudio; - -/** This property is only effective if useManualAudio is YES. - * Represents permission for WebRTC to initialize the VoIP audio unit. - * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be - * stopped and uninitialized. This will stop incoming and outgoing audio. - * When set to YES, WebRTC will initialize and start the audio unit when it is - * needed (e.g. due to establishing an audio connection). - * This property was introduced to work around an issue where if an AVPlayer is - * playing audio while the VoIP audio unit is initialized, its audio would be - * either cut off completely or played at a reduced volume. By preventing - * the audio unit from being initialized until after the audio has completed, - * we are able to prevent the abrupt cutoff. - */ -@property(nonatomic, assign) BOOL isAudioEnabled; - -// Proxy properties. -@property(readonly) NSString *category; -@property(readonly) AVAudioSessionCategoryOptions categoryOptions; -@property(readonly) NSString *mode; -@property(readonly) BOOL secondaryAudioShouldBeSilencedHint; -@property(readonly) AVAudioSessionRouteDescription *currentRoute; -@property(readonly) NSInteger maximumInputNumberOfChannels; -@property(readonly) NSInteger maximumOutputNumberOfChannels; -@property(readonly) float inputGain; -@property(readonly) BOOL inputGainSettable; -@property(readonly) BOOL inputAvailable; -@property(readonly, nullable) - NSArray * inputDataSources; -@property(readonly, nullable) - AVAudioSessionDataSourceDescription *inputDataSource; -@property(readonly, nullable) - NSArray * outputDataSources; -@property(readonly, nullable) - AVAudioSessionDataSourceDescription *outputDataSource; -@property(readonly) double sampleRate; -@property(readonly) double preferredSampleRate; -@property(readonly) NSInteger inputNumberOfChannels; -@property(readonly) NSInteger outputNumberOfChannels; -@property(readonly) float outputVolume; -@property(readonly) NSTimeInterval inputLatency; -@property(readonly) NSTimeInterval outputLatency; -@property(readonly) NSTimeInterval IOBufferDuration; -@property(readonly) NSTimeInterval preferredIOBufferDuration; - -/** Default constructor. */ -+ (instancetype)sharedInstance; -- (instancetype)init NS_UNAVAILABLE; - -/** Adds a delegate, which is held weakly. */ -- (void)addDelegate:(id)delegate; -/** Removes an added delegate. */ -- (void)removeDelegate:(id)delegate; - -/** Request exclusive access to the audio session for configuration. This call - * will block if the lock is held by another object. - */ -- (void)lockForConfiguration; -/** Relinquishes exclusive access to the audio session. */ -- (void)unlockForConfiguration; - -/** If |active|, activates the audio session if it isn't already active. - * Successful calls must be balanced with a setActive:NO when activation is no - * longer required. If not |active|, deactivates the audio session if one is - * active and this is the last balanced call. When deactivating, the - * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to - * AVAudioSession. - */ -- (BOOL)setActive:(BOOL)active - error:(NSError **)outError; - -// The following methods are proxies for the associated methods on -// AVAudioSession. |lockForConfiguration| must be called before using them -// otherwise they will fail with kRTCAudioSessionErrorLockRequired. - -- (BOOL)setCategory:(NSString *)category - withOptions:(AVAudioSessionCategoryOptions)options - error:(NSError **)outError; -- (BOOL)setMode:(NSString *)mode error:(NSError **)outError; -- (BOOL)setInputGain:(float)gain error:(NSError **)outError; -- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError; -- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration - error:(NSError **)outError; -- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count - error:(NSError **)outError; -- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count - error:(NSError **)outError; -- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride - error:(NSError **)outError; -- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort - error:(NSError **)outError; -- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource - error:(NSError **)outError; -- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource - error:(NSError **)outError; -@end - -@interface RTCAudioSession (Configuration) - -/** Applies the configuration to the current session. Attempts to set all - * properties even if previous ones fail. Only the last error will be - * returned. - * |lockForConfiguration| must be called first. - */ -- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration - error:(NSError **)outError; - -/** Convenience method that calls both setConfiguration and setActive. - * |lockForConfiguration| must be called first. - */ -- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration - active:(BOOL)active - error:(NSError **)outError; - -@end - -NS_ASSUME_NONNULL_END +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h" diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h index 6a02751d29..e40910820d 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * Copyright 2017 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -8,41 +8,4 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import -#import - -#import "WebRTC/RTCMacros.h" - -NS_ASSUME_NONNULL_BEGIN - -extern const int kRTCAudioSessionPreferredNumberOfChannels; -extern const double kRTCAudioSessionHighPerformanceSampleRate; -extern const double kRTCAudioSessionLowComplexitySampleRate; -extern const double kRTCAudioSessionHighPerformanceIOBufferDuration; -extern const double kRTCAudioSessionLowComplexityIOBufferDuration; - -// Struct to hold configuration values. -RTC_EXPORT -@interface RTCAudioSessionConfiguration : NSObject - -@property(nonatomic, strong) NSString *category; -@property(nonatomic, assign) AVAudioSessionCategoryOptions categoryOptions; -@property(nonatomic, strong) NSString *mode; -@property(nonatomic, assign) double sampleRate; -@property(nonatomic, assign) NSTimeInterval ioBufferDuration; -@property(nonatomic, assign) NSInteger inputNumberOfChannels; -@property(nonatomic, assign) NSInteger outputNumberOfChannels; - -/** Initializes configuration to defaults. */ -- (instancetype)init NS_DESIGNATED_INITIALIZER; - -/** Returns the current configuration of the audio session. */ -+ (instancetype)currentConfiguration; -/** Returns the configuration that WebRTC needs. */ -+ (instancetype)webRTCConfiguration; -/** Provide a way to override the default configuration. */ -+ (void)setWebRTCConfiguration:(RTCAudioSessionConfiguration *)configuration; - -@end - -NS_ASSUME_NONNULL_END +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h" diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionDelegateAdapter.h b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionDelegateAdapter.h index 0140aa043a..9f71e972f4 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionDelegateAdapter.h +++ b/webrtc/modules/audio_device/ios/objc/RTCAudioSessionDelegateAdapter.h @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h" namespace webrtc { class AudioSessionObserver; diff --git a/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm b/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm index d8805a1004..3ad8801cdd 100644 --- a/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm +++ b/webrtc/modules/audio_device/ios/voice_processing_audio_unit.mm @@ -13,7 +13,7 @@ #include "webrtc/base/checks.h" #import "WebRTC/RTCLogging.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" +#import "webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h" #if !defined(NDEBUG) static void LogStreamDescription(AudioStreamBasicDescription description) { diff --git a/webrtc/sdk/BUILD.gn b/webrtc/sdk/BUILD.gn index 34ea001e87..e1d8e934ea 100644 --- a/webrtc/sdk/BUILD.gn +++ b/webrtc/sdk/BUILD.gn @@ -80,6 +80,27 @@ if (is_ios || is_mac) { } if (!build_with_chromium) { + rtc_static_library("objc_audio") { + sources = [ + "objc/Framework/Classes/Audio/RTCAudioSession+Configuration.mm", + "objc/Framework/Classes/Audio/RTCAudioSession+Private.h", + "objc/Framework/Classes/Audio/RTCAudioSession.mm", + "objc/Framework/Classes/Audio/RTCAudioSessionConfiguration.m", + "objc/Framework/Headers/WebRTC/RTCAudioSession.h", + "objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h", + ] + configs += [ "..:common_objc" ] + + deps = [ + ":objc_common", + "../base:rtc_base_approved", + ] + + if (is_clang) { + # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). + suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] + } + } rtc_static_library("objc_video") { sources = [ "objc/Framework/Classes/Video/RTCAVFoundationVideoCapturerInternal.h", @@ -370,17 +391,20 @@ if (is_ios || is_mac) { "//third_party/ocmock", ] - # RTCMTLVideoView not supported on 32-bit arm - if (is_ios && current_cpu != "arm") { - sources += [ "objc/Framework/UnitTests/RTCMTLVideoViewTests.mm" ] - if (current_cpu != "arm64") { - # Only include this file on simulator, as it's already - # included in device builds. - sources += [ "objc/Framework/Classes/Metal/RTCMTLVideoView.m" ] - libs = [ "CoreVideo.framework" ] + if (is_ios) { + sources += [ "objc/Framework/UnitTests/RTCAudioSessionTest.mm" ] + + # RTCMTLVideoView not supported on 32-bit arm + if (current_cpu != "arm") { + sources += [ "objc/Framework/UnitTests/RTCMTLVideoViewTests.mm" ] + if (current_cpu != "arm64") { + # Only include this file on simulator, as it's already + # included in device builds. + sources += [ "objc/Framework/Classes/Metal/RTCMTLVideoView.m" ] + libs = [ "CoreVideo.framework" ] + } } } - if (!build_with_chromium && is_clang) { # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163). suppressed_configs += [ "//build/config/clang:find_bad_constructs" ] @@ -394,6 +418,8 @@ if (is_ios || is_mac) { output_name = "WebRTC" common_objc_headers = [ + "objc/Framework/Headers/WebRTC/RTCAudioSession.h", + "objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h", "objc/Framework/Headers/WebRTC/RTCAVFoundationVideoSource.h", "objc/Framework/Headers/WebRTC/RTCAudioSource.h", "objc/Framework/Headers/WebRTC/RTCAudioTrack.h", @@ -454,6 +480,7 @@ if (is_ios || is_mac) { ] deps = [ + ":objc_audio", ":objc_peerconnection", ":objc_ui", "../base:rtc_base_approved", diff --git a/webrtc/sdk/objc/DEPS b/webrtc/sdk/objc/DEPS index ac54cc054c..eea7e4ffc9 100644 --- a/webrtc/sdk/objc/DEPS +++ b/webrtc/sdk/objc/DEPS @@ -15,4 +15,4 @@ include_rules = [ "+webrtc/modules/video_coding", "+webrtc/pc", "+webrtc/system_wrappers", -] +] \ No newline at end of file diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Configuration.mm b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Configuration.mm similarity index 96% rename from webrtc/modules/audio_device/ios/objc/RTCAudioSession+Configuration.mm rename to webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Configuration.mm index 5a7600a5d3..c4d0d0c54c 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Configuration.mm +++ b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Configuration.mm @@ -8,11 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" +#import "WebRTC/RTCAudioSession.h" +#import "WebRTC/RTCAudioSessionConfiguration.h" #import "WebRTC/RTCLogging.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" +#import "RTCAudioSession+Private.h" + @implementation RTCAudioSession (Configuration) diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Private.h similarity index 98% rename from webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h rename to webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Private.h index 36be014386..5a063ed902 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h +++ b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession+Private.h @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" +#import "WebRTC/RTCAudioSession.h" #include diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession.mm similarity index 99% rename from webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm rename to webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession.mm index 763f1fae54..ce0e2633f9 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSession.mm +++ b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSession.mm @@ -8,18 +8,20 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" +#import "WebRTC/RTCAudioSession.h" #import #include "webrtc/base/atomicops.h" #include "webrtc/base/checks.h" #include "webrtc/base/criticalsection.h" -#include "webrtc/modules/audio_device/ios/audio_device_ios.h" + +#import "WebRTC/RTCAudioSessionConfiguration.h" #import "WebRTC/RTCLogging.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" + +#import "RTCAudioSession+Private.h" + NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession"; NSInteger const kRTCAudioSessionErrorLockRequired = -1; diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.m b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSessionConfiguration.m similarity index 97% rename from webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.m rename to webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSessionConfiguration.m index 9bbd4b7012..fe7b54430a 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.m +++ b/webrtc/sdk/objc/Framework/Classes/Audio/RTCAudioSessionConfiguration.m @@ -8,12 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" +#import "WebRTC/RTCAudioSession.h" +#import "WebRTC/RTCAudioSessionConfiguration.h" #import "WebRTC/RTCDispatcher.h" #import "WebRTC/UIDevice+RTCDevice.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" // Try to use mono to save resources. Also avoids channel format conversion // in the I/O audio unit. Initial tests have shown that it is possible to use diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h new file mode 100644 index 0000000000..c0ea2163ae --- /dev/null +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSession.h @@ -0,0 +1,242 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import +#import + +#import "WebRTC/RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +extern NSString * const kRTCAudioSessionErrorDomain; +/** Method that requires lock was called without lock. */ +extern NSInteger const kRTCAudioSessionErrorLockRequired; +/** Unknown configuration error occurred. */ +extern NSInteger const kRTCAudioSessionErrorConfiguration; + +@class RTCAudioSession; +@class RTCAudioSessionConfiguration; + +// Surfaces AVAudioSession events. WebRTC will listen directly for notifications +// from AVAudioSession and handle them before calling these delegate methods, +// at which point applications can perform additional processing if required. +RTC_EXPORT +@protocol RTCAudioSessionDelegate + +@optional +/** Called on a system notification thread when AVAudioSession starts an + * interruption event. + */ +- (void)audioSessionDidBeginInterruption:(RTCAudioSession *)session; + +/** Called on a system notification thread when AVAudioSession ends an + * interruption event. + */ +- (void)audioSessionDidEndInterruption:(RTCAudioSession *)session + shouldResumeSession:(BOOL)shouldResumeSession; + +/** Called on a system notification thread when AVAudioSession changes the + * route. + */ +- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session + reason:(AVAudioSessionRouteChangeReason)reason + previousRoute:(AVAudioSessionRouteDescription *)previousRoute; + +/** Called on a system notification thread when AVAudioSession media server + * terminates. + */ +- (void)audioSessionMediaServerTerminated:(RTCAudioSession *)session; + +/** Called on a system notification thread when AVAudioSession media server + * restarts. + */ +- (void)audioSessionMediaServerReset:(RTCAudioSession *)session; + +// TODO(tkchin): Maybe handle SilenceSecondaryAudioHintNotification. + +- (void)audioSession:(RTCAudioSession *)session + didChangeCanPlayOrRecord:(BOOL)canPlayOrRecord; + +/** Called on a WebRTC thread when the audio device is notified to begin + * playback or recording. + */ +- (void)audioSessionDidStartPlayOrRecord:(RTCAudioSession *)session; + +/** Called on a WebRTC thread when the audio device is notified to stop + * playback or recording. + */ +- (void)audioSessionDidStopPlayOrRecord:(RTCAudioSession *)session; + +/** Called when the AVAudioSession output volume value changes. */ +- (void)audioSession:(RTCAudioSession *)audioSession + didChangeOutputVolume:(float)outputVolume; + +@end + +/** This is a protocol used to inform RTCAudioSession when the audio session + * activation state has changed outside of RTCAudioSession. The current known use + * case of this is when CallKit activates the audio session for the application + */ +RTC_EXPORT +@protocol RTCAudioSessionActivationDelegate + +/** Called when the audio session is activated outside of the app by iOS. */ +- (void)audioSessionDidActivate:(AVAudioSession *)session; + +/** Called when the audio session is deactivated outside of the app by iOS. */ +- (void)audioSessionDidDeactivate:(AVAudioSession *)session; + +@end + +/** Proxy class for AVAudioSession that adds a locking mechanism similar to + * AVCaptureDevice. This is used to that interleaving configurations between + * WebRTC and the application layer are avoided. + * + * RTCAudioSession also coordinates activation so that the audio session is + * activated only once. See |setActive:error:|. + */ +RTC_EXPORT +@interface RTCAudioSession : NSObject + +/** Convenience property to access the AVAudioSession singleton. Callers should + * not call setters on AVAudioSession directly, but other method invocations + * are fine. + */ +@property(nonatomic, readonly) AVAudioSession *session; + +/** Our best guess at whether the session is active based on results of calls to + * AVAudioSession. + */ +@property(nonatomic, readonly) BOOL isActive; +/** Whether RTCAudioSession is currently locked for configuration. */ +@property(nonatomic, readonly) BOOL isLocked; + +/** If YES, WebRTC will not initialize the audio unit automatically when an + * audio track is ready for playout or recording. Instead, applications should + * call setIsAudioEnabled. If NO, WebRTC will initialize the audio unit + * as soon as an audio track is ready for playout or recording. + */ +@property(nonatomic, assign) BOOL useManualAudio; + +/** This property is only effective if useManualAudio is YES. + * Represents permission for WebRTC to initialize the VoIP audio unit. + * When set to NO, if the VoIP audio unit used by WebRTC is active, it will be + * stopped and uninitialized. This will stop incoming and outgoing audio. + * When set to YES, WebRTC will initialize and start the audio unit when it is + * needed (e.g. due to establishing an audio connection). + * This property was introduced to work around an issue where if an AVPlayer is + * playing audio while the VoIP audio unit is initialized, its audio would be + * either cut off completely or played at a reduced volume. By preventing + * the audio unit from being initialized until after the audio has completed, + * we are able to prevent the abrupt cutoff. + */ +@property(nonatomic, assign) BOOL isAudioEnabled; + +// Proxy properties. +@property(readonly) NSString *category; +@property(readonly) AVAudioSessionCategoryOptions categoryOptions; +@property(readonly) NSString *mode; +@property(readonly) BOOL secondaryAudioShouldBeSilencedHint; +@property(readonly) AVAudioSessionRouteDescription *currentRoute; +@property(readonly) NSInteger maximumInputNumberOfChannels; +@property(readonly) NSInteger maximumOutputNumberOfChannels; +@property(readonly) float inputGain; +@property(readonly) BOOL inputGainSettable; +@property(readonly) BOOL inputAvailable; +@property(readonly, nullable) + NSArray * inputDataSources; +@property(readonly, nullable) + AVAudioSessionDataSourceDescription *inputDataSource; +@property(readonly, nullable) + NSArray * outputDataSources; +@property(readonly, nullable) + AVAudioSessionDataSourceDescription *outputDataSource; +@property(readonly) double sampleRate; +@property(readonly) double preferredSampleRate; +@property(readonly) NSInteger inputNumberOfChannels; +@property(readonly) NSInteger outputNumberOfChannels; +@property(readonly) float outputVolume; +@property(readonly) NSTimeInterval inputLatency; +@property(readonly) NSTimeInterval outputLatency; +@property(readonly) NSTimeInterval IOBufferDuration; +@property(readonly) NSTimeInterval preferredIOBufferDuration; + +/** Default constructor. */ ++ (instancetype)sharedInstance; +- (instancetype)init NS_UNAVAILABLE; + +/** Adds a delegate, which is held weakly. */ +- (void)addDelegate:(id)delegate; +/** Removes an added delegate. */ +- (void)removeDelegate:(id)delegate; + +/** Request exclusive access to the audio session for configuration. This call + * will block if the lock is held by another object. + */ +- (void)lockForConfiguration; +/** Relinquishes exclusive access to the audio session. */ +- (void)unlockForConfiguration; + +/** If |active|, activates the audio session if it isn't already active. + * Successful calls must be balanced with a setActive:NO when activation is no + * longer required. If not |active|, deactivates the audio session if one is + * active and this is the last balanced call. When deactivating, the + * AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation option is passed to + * AVAudioSession. + */ +- (BOOL)setActive:(BOOL)active + error:(NSError **)outError; + +// The following methods are proxies for the associated methods on +// AVAudioSession. |lockForConfiguration| must be called before using them +// otherwise they will fail with kRTCAudioSessionErrorLockRequired. + +- (BOOL)setCategory:(NSString *)category + withOptions:(AVAudioSessionCategoryOptions)options + error:(NSError **)outError; +- (BOOL)setMode:(NSString *)mode error:(NSError **)outError; +- (BOOL)setInputGain:(float)gain error:(NSError **)outError; +- (BOOL)setPreferredSampleRate:(double)sampleRate error:(NSError **)outError; +- (BOOL)setPreferredIOBufferDuration:(NSTimeInterval)duration + error:(NSError **)outError; +- (BOOL)setPreferredInputNumberOfChannels:(NSInteger)count + error:(NSError **)outError; +- (BOOL)setPreferredOutputNumberOfChannels:(NSInteger)count + error:(NSError **)outError; +- (BOOL)overrideOutputAudioPort:(AVAudioSessionPortOverride)portOverride + error:(NSError **)outError; +- (BOOL)setPreferredInput:(AVAudioSessionPortDescription *)inPort + error:(NSError **)outError; +- (BOOL)setInputDataSource:(AVAudioSessionDataSourceDescription *)dataSource + error:(NSError **)outError; +- (BOOL)setOutputDataSource:(AVAudioSessionDataSourceDescription *)dataSource + error:(NSError **)outError; +@end + +@interface RTCAudioSession (Configuration) + +/** Applies the configuration to the current session. Attempts to set all + * properties even if previous ones fail. Only the last error will be + * returned. + * |lockForConfiguration| must be called first. + */ +- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration + error:(NSError **)outError; + +/** Convenience method that calls both setConfiguration and setActive. + * |lockForConfiguration| must be called first. + */ +- (BOOL)setConfiguration:(RTCAudioSessionConfiguration *)configuration + active:(BOOL)active + error:(NSError **)outError; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h new file mode 100644 index 0000000000..6a02751d29 --- /dev/null +++ b/webrtc/sdk/objc/Framework/Headers/WebRTC/RTCAudioSessionConfiguration.h @@ -0,0 +1,48 @@ +/* + * Copyright 2016 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#import +#import + +#import "WebRTC/RTCMacros.h" + +NS_ASSUME_NONNULL_BEGIN + +extern const int kRTCAudioSessionPreferredNumberOfChannels; +extern const double kRTCAudioSessionHighPerformanceSampleRate; +extern const double kRTCAudioSessionLowComplexitySampleRate; +extern const double kRTCAudioSessionHighPerformanceIOBufferDuration; +extern const double kRTCAudioSessionLowComplexityIOBufferDuration; + +// Struct to hold configuration values. +RTC_EXPORT +@interface RTCAudioSessionConfiguration : NSObject + +@property(nonatomic, strong) NSString *category; +@property(nonatomic, assign) AVAudioSessionCategoryOptions categoryOptions; +@property(nonatomic, strong) NSString *mode; +@property(nonatomic, assign) double sampleRate; +@property(nonatomic, assign) NSTimeInterval ioBufferDuration; +@property(nonatomic, assign) NSInteger inputNumberOfChannels; +@property(nonatomic, assign) NSInteger outputNumberOfChannels; + +/** Initializes configuration to defaults. */ +- (instancetype)init NS_DESIGNATED_INITIALIZER; + +/** Returns the current configuration of the audio session. */ ++ (instancetype)currentConfiguration; +/** Returns the configuration that WebRTC needs. */ ++ (instancetype)webRTCConfiguration; +/** Provide a way to override the default configuration. */ ++ (void)setWebRTCConfiguration:(RTCAudioSessionConfiguration *)configuration; + +@end + +NS_ASSUME_NONNULL_END diff --git a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm b/webrtc/sdk/objc/Framework/UnitTests/RTCAudioSessionTest.mm similarity index 97% rename from webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm rename to webrtc/sdk/objc/Framework/UnitTests/RTCAudioSessionTest.mm index c050e314c9..f932457108 100644 --- a/webrtc/modules/audio_device/ios/objc/RTCAudioSessionTest.mm +++ b/webrtc/sdk/objc/Framework/UnitTests/RTCAudioSessionTest.mm @@ -11,11 +11,12 @@ #import #import -#include "webrtc/test/gtest.h" +#include "webrtc/base/gunit.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" -#import "webrtc/modules/audio_device/ios/objc/RTCAudioSessionConfiguration.h" +#import "RTCAudioSession+Private.h" + +#import "WebRTC/RTCAudioSession.h" +#import "WebRTC/RTCAudioSessionConfiguration.h" @interface RTCAudioSessionTestDelegate : NSObject