diff --git a/packages/react-native-audio-api/src/specs/NativeAudioAPIModule.ts b/packages/react-native-audio-api/src/specs/NativeAudioAPIModule.ts index f5b8d54a9..1208b6b26 100644 --- a/packages/react-native-audio-api/src/specs/NativeAudioAPIModule.ts +++ b/packages/react-native-audio-api/src/specs/NativeAudioAPIModule.ts @@ -18,10 +18,16 @@ interface Spec extends TurboModule { ): void; getDevicePreferredSampleRate(): number; observeAudioInterruptions(enabled: boolean): void; - requestAudioFocus( + setAudioOptions( observeAudioInterruptions: boolean, options?: { - [key: string]: string | boolean | number | AudioAttributeType | undefined; + [key: string]: + | string + | string[] + | boolean + | number + | AudioAttributeType + | undefined; } ): void; abandonAudioFocus(): void; diff --git a/packages/react-native-audio-api/src/system/AudioManager.ts b/packages/react-native-audio-api/src/system/AudioManager.ts index 69cfa29ec..7234edec7 100644 --- a/packages/react-native-audio-api/src/system/AudioManager.ts +++ b/packages/react-native-audio-api/src/system/AudioManager.ts @@ -1,9 +1,4 @@ -import { - SessionOptions, - LockScreenInfo, - PermissionStatus, - AudioFocusOptions, -} from './types'; +import { AudioOptions, LockScreenInfo, PermissionStatus } from './types'; import { SystemEventName, SystemEventCallback } from '../events/types'; import { NativeAudioAPIModule } from '../specs'; import { AudioEventEmitter, AudioEventSubscription } from '../events'; @@ -32,14 +27,6 @@ class AudioManager { NativeAudioAPIModule!.resetLockScreenInfo(); } - setAudioSessionOptions(options: SessionOptions) { - NativeAudioAPIModule!.setAudioSessionOptions( - options.iosCategory ?? '', - options.iosMode ?? '', - options.iosOptions ?? [] - ); - } - getDevicePreferredSampleRate(): number { return NativeAudioAPIModule!.getDevicePreferredSampleRate(); } @@ -48,11 +35,15 @@ class AudioManager { NativeAudioAPIModule!.observeAudioInterruptions(enabled); } - requestAudioFocus( - observeAudioInterruption = true, - options?: AudioFocusOptions - ) { - NativeAudioAPIModule!.requestAudioFocus(observeAudioInterruption, options); + /** + * Used to set various system options for android and iOS + * + * @param observeAudioInterruption - If true, the module will observe audio + * interruptions and emit events accordingly (true by default). + * @param options - Additional audio options to configure the audio session. + */ + setAudioOptions(observeAudioInterruption = true, options?: AudioOptions) { + NativeAudioAPIModule!.setAudioOptions(observeAudioInterruption, options); } abandonAudioFocus() { diff --git a/packages/react-native-audio-api/src/system/types.ts b/packages/react-native-audio-api/src/system/types.ts index bd713ce73..e3abf1334 100644 --- a/packages/react-native-audio-api/src/system/types.ts +++ b/packages/react-native-audio-api/src/system/types.ts @@ -1,3 +1,4 @@ +// category that defines a set of audio behaviors, f.e. recording is only allowed in 'record' or 'playAndRecord' category export type IOSCategory = | 'record' | 'ambient' @@ -6,6 +7,7 @@ export type IOSCategory = | 'soloAmbient' | 'playAndRecord'; +// used to define specialized behaviors to an audio session export type IOSMode = | 'default' | 'gameChat' @@ -18,68 +20,59 @@ export type IOSMode = | 'videoRecording'; export type IOSOption = - | 'duckOthers' - | 'allowAirPlay' - | 'mixWithOthers' - | 'allowBluetooth' - | 'defaultToSpeaker' - | 'allowBluetoothA2DP' - | 'overrideMutedMicrophoneInterruption' - | 'interruptSpokenAudioAndMixWithOthers'; + | 'duckOthers' // reduce the volume of other audio sessions + | 'allowAirPlay' // whether you can stream audio from this session to AirPlay devices + | 'mixWithOthers' // mixing with other audio sessions + | 'allowBluetooth' // deprecated, option that determines whether Bluetooth hands-free devices appear as available input routes + | 'defaultToSpeaker' // whether audio from the session defaults to the built-in speaker instead of the receiver + | 'allowBluetoothA2DP' // whether you can stream audio from this session to Bluetooth devices that support the Advanced Audio Distribution Profile + | 'overrideMutedMicrophoneInterruption' // whether the system interrupts the audio session when it mutes the built-in microphone + | 'interruptSpokenAudioAndMixWithOthers'; // whether to pause spoken audio from other apps when this session plays +// specifies why the source is playing and controls routing, focus, and volume decisions export type audioAttributeUsageType = - | 'usage_alarm' - | 'usage_assistance_accessibility' - | 'usage_assistance_navigation_guidance' - | 'usage_assistance_sonification' - | 'usage_assistant' - | 'usage_game' - | 'usage_media' - | 'usage_notification' - | 'usage_notification_event' - | 'usage_notification_ringtone' - | 'usage_notification_communication_request' - | 'usage_notification_communication_instant' - | 'usage_notification_communication_delayed' - | 'usage_unknown' - | 'usage_voice_communication' - | 'usage_voice_communication_signalling'; + | 'usageAlarm' + | 'usageAssistanceAccessibility' + | 'usageAssistanceNavigationGuidance' + | 'usageAssistanceSonification' + | 'usageAssistant' + | 'usageGame' + | 'usageMedia' + | 'usageNotification' + | 'usageNotificationEvent' + | 'usageNotificationRingtone' + | 'usageNotificationCommunicationRequest' + | 'usageNotificationCommunicationInstant' + | 'usageNotificationCommunicationDelayed' + | 'usageUnknown' + | 'usageVoiceCommunication' + | 'usageVoiceCommunicationSignalling'; +// specifies what the source is playing export type audioAttributeContentType = - | 'content_type_movie' - | 'content_type_music' - | 'content_type_sonification' - | 'content_type_speech' - | 'content_type_unknown'; + | 'contentTypeMovie' + | 'contentTypeMusic' + | 'contentTypeSonification' + | 'contentTypeSpeech' + | 'contentTypeUnknown'; export type focusGainType = - | 'audiofocus_gain' - | 'audiofocus_gain_transient' - | 'audiofocus_gain_transient_exclusive' - | 'audiofocus_gain_transient_may_duck'; + | 'audiofocusGain' // indicate a gain of audio focus, or a request of audio focus, of unknown duration + | 'audiofocusGainTransient' // indicate a temporary gain or request of audio focus, anticipated to last a short amount of time + | 'audiofocusGainTransientExclusive' // indicate a temporary request of audio focus, anticipated to last a short amount of time, during which no other applications, or system components, should play anything + | 'audiofocusGainTransientMayDuck'; // indicate a temporary request of audio focus, anticipated to last a short amount of time, and where it is acceptable for other audio applications to keep playing after having lowered their output level export type AudioAttributeType = { allowedCapturePolicy?: - | 'allow_capture_by_all' - | 'allow_capture_by_system' - | 'allow_capture_by_none'; + | 'allowCaptureByAll' // audio may be captured by any app + | 'allowCaptureBySystem' // audio may be captured by system apps only + | 'allowCaptureByNone'; // audio may not be captured by any app contentType?: audioAttributeContentType; - flag?: 'flag_hw_av_sync' | 'flag_audibility_enforced'; hapticChannelsMuted?: boolean; - isContentSpatialized?: boolean; - spatializationBehavior?: - | 'spatialization_behavior_auto' - | 'spatialization_behavior_never'; usage?: audioAttributeUsageType; }; -export interface SessionOptions { - iosMode?: IOSMode; - iosOptions?: IOSOption[]; - iosCategory?: IOSCategory; -} - -export type MediaState = 'state_playing' | 'state_paused'; +export type MediaState = 'statePlaying' | 'statePaused'; interface BaseLockScreenInfo { [key: string]: string | boolean | number | undefined; @@ -97,15 +90,24 @@ export interface LockScreenInfo extends BaseLockScreenInfo { elapsedTime?: number; } -export type PermissionStatus = 'Undetermined' | 'Denied' | 'Granted'; +export type PermissionStatus = 'undetermined' | 'denied' | 'granted'; -interface BaseAudioFocusOptions { - [key: string]: string | boolean | number | AudioAttributeType | undefined; +interface BaseAudioOptions { + [key: string]: + | string + | string[] + | boolean + | number + | AudioAttributeType + | undefined; } -export interface AudioFocusOptions extends BaseAudioFocusOptions { - acceptsDelayedFocusGain?: boolean; - audioAttributes?: AudioAttributeType; - focusGain?: focusGainType; - pauseWhenDucked?: boolean; +export interface AudioOptions extends BaseAudioOptions { + androidAcceptsDelayedFocusGain?: boolean; // marks this focus request as compatible with delayed focus + androidAudioAttributes?: AudioAttributeType; + androidFocusGain?: focusGainType; + androidPauseWhenDucked?: boolean; // whether the app will pause when instructed to duck + iosMode?: IOSMode; + iosOptions?: IOSOption[]; + iosCategory?: IOSCategory; }