react-native-audio-api 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +9 -0
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +2 -0
- package/android/src/oldarch/NativeAudioAPIModuleSpec.java +4 -0
- package/common/cpp/audioapi/HostObjects/inputs/AudioRecorderHostObject.cpp +2 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.h +6 -0
- package/common/cpp/audioapi/jsi/JsiUtils.cpp +21 -0
- package/common/cpp/audioapi/jsi/JsiUtils.h +17 -0
- package/ios/audioapi/ios/AudioAPIModule.mm +9 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +3 -1
- package/ios/audioapi/ios/system/AudioSessionManager.h +3 -0
- package/ios/audioapi/ios/system/AudioSessionManager.mm +38 -2
- package/lib/commonjs/api.js +8 -8
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioDecoder.js +2 -2
- package/lib/commonjs/core/AudioDecoder.js.map +1 -1
- package/lib/commonjs/core/AudioRecorder.js +1 -1
- package/lib/commonjs/core/AudioRecorder.js.map +1 -1
- package/lib/commonjs/hooks/index.js +21 -0
- package/lib/commonjs/hooks/index.js.map +1 -0
- package/lib/commonjs/hooks/useAudioInput.js +70 -0
- package/lib/commonjs/hooks/useAudioInput.js.map +1 -0
- package/lib/commonjs/hooks/useSystemVolume.js +4 -5
- package/lib/commonjs/hooks/useSystemVolume.js.map +1 -1
- package/lib/commonjs/index.js +11 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.web.js +1 -0
- package/lib/commonjs/specs/NativeAudioAPIModule.web.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +3 -0
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/commonjs/web-system/AudioManager.js +1 -0
- package/lib/commonjs/web-system/AudioManager.js.map +1 -1
- package/lib/module/api.js +2 -3
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioDecoder.js +2 -2
- package/lib/module/core/AudioDecoder.js.map +1 -1
- package/lib/module/core/AudioRecorder.js +1 -1
- package/lib/module/core/AudioRecorder.js.map +1 -1
- package/lib/module/hooks/index.js +5 -0
- package/lib/module/hooks/index.js.map +1 -0
- package/lib/module/hooks/useAudioInput.js +66 -0
- package/lib/module/hooks/useAudioInput.js.map +1 -0
- package/lib/module/hooks/useSystemVolume.js +1 -1
- package/lib/module/hooks/useSystemVolume.js.map +1 -1
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.web.js +1 -0
- package/lib/module/specs/NativeAudioAPIModule.web.js.map +1 -1
- package/lib/module/system/AudioManager.js +3 -0
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/module/web-system/AudioManager.js +1 -0
- package/lib/module/web-system/AudioManager.js.map +1 -1
- package/lib/typescript/api.d.ts +2 -3
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioDecoder.d.ts.map +1 -1
- package/lib/typescript/events/types.d.ts +6 -4
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/hooks/index.d.ts +3 -0
- package/lib/typescript/hooks/index.d.ts.map +1 -0
- package/lib/typescript/hooks/useAudioInput.d.ts +28 -0
- package/lib/typescript/hooks/useAudioInput.d.ts.map +1 -0
- package/lib/typescript/hooks/useSystemVolume.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +2 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.web.d.ts +1 -0
- package/lib/typescript/specs/NativeAudioAPIModule.web.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +1 -0
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/system/types.d.ts +3 -1
- package/lib/typescript/system/types.d.ts.map +1 -1
- package/lib/typescript/web-system/AudioManager.d.ts +1 -0
- package/lib/typescript/web-system/AudioManager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +5 -4
- package/src/core/AudioDecoder.ts +2 -2
- package/src/core/AudioRecorder.ts +1 -1
- package/src/events/types.ts +16 -12
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useAudioInput.ts +93 -0
- package/src/hooks/useSystemVolume.ts +3 -2
- package/src/index.ts +5 -0
- package/src/specs/NativeAudioAPIModule.ts +2 -1
- package/src/specs/NativeAudioAPIModule.web.ts +2 -0
- package/src/system/AudioManager.ts +4 -0
- package/src/system/types.ts +3 -1
- package/src/web-system/AudioManager.ts +1 -0
package/src/api.ts
CHANGED
|
@@ -20,6 +20,7 @@ export { default as DelayNode } from './core/DelayNode';
|
|
|
20
20
|
export { default as GainNode } from './core/GainNode';
|
|
21
21
|
export { default as OfflineAudioContext } from './core/OfflineAudioContext';
|
|
22
22
|
export { default as OscillatorNode } from './core/OscillatorNode';
|
|
23
|
+
export { default as PeriodicWave } from './core/PeriodicWave';
|
|
23
24
|
export { default as RecorderAdapterNode } from './core/RecorderAdapterNode';
|
|
24
25
|
export { default as StereoPannerNode } from './core/StereoPannerNode';
|
|
25
26
|
export { default as StreamerNode } from './core/StreamerNode';
|
|
@@ -27,8 +28,6 @@ export { default as WaveShaperNode } from './core/WaveShaperNode';
|
|
|
27
28
|
export { default as WorkletNode } from './core/WorkletNode';
|
|
28
29
|
export { default as WorkletProcessingNode } from './core/WorkletProcessingNode';
|
|
29
30
|
export { default as WorkletSourceNode } from './core/WorkletSourceNode';
|
|
30
|
-
|
|
31
|
-
export { default as useSystemVolume } from './hooks/useSystemVolume';
|
|
32
31
|
export { default as AudioManager } from './system';
|
|
33
32
|
|
|
34
33
|
export * from './errors';
|
|
@@ -37,8 +36,10 @@ export * from './types';
|
|
|
37
36
|
export { default as FilePreset } from './utils/filePresets';
|
|
38
37
|
|
|
39
38
|
// Notification System
|
|
40
|
-
export {
|
|
41
|
-
|
|
39
|
+
export {
|
|
40
|
+
PlaybackNotificationManager,
|
|
41
|
+
RecordingNotificationManager,
|
|
42
|
+
} from './system/notification';
|
|
42
43
|
|
|
43
44
|
export {
|
|
44
45
|
NotificationManager,
|
package/src/core/AudioDecoder.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Image } from 'react-native';
|
|
2
2
|
|
|
3
|
+
import { AudioApiError } from '../errors';
|
|
3
4
|
import { IAudioDecoder } from '../interfaces';
|
|
4
5
|
import { DecodeDataInput } from '../types';
|
|
5
6
|
import {
|
|
@@ -8,7 +9,6 @@ import {
|
|
|
8
9
|
isRemoteSource,
|
|
9
10
|
} from '../utils/paths';
|
|
10
11
|
import AudioBuffer from './AudioBuffer';
|
|
11
|
-
import { AudioApiError } from '../errors';
|
|
12
12
|
|
|
13
13
|
class AudioDecoder {
|
|
14
14
|
private static instance: AudioDecoder | null = null;
|
|
@@ -62,7 +62,7 @@ class AudioDecoder {
|
|
|
62
62
|
return new AudioBuffer(buffer);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (!(typeof
|
|
65
|
+
if (!(typeof stringSource === 'string')) {
|
|
66
66
|
throw new TypeError('Input must be a module, uri or ArrayBuffer');
|
|
67
67
|
}
|
|
68
68
|
|
package/src/events/types.ts
CHANGED
|
@@ -7,21 +7,25 @@ export interface EventTypeWithValue {
|
|
|
7
7
|
value: number;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
export type InterruptionType = 'began' | 'ended';
|
|
11
|
+
|
|
12
|
+
export interface OnInterruptionEventType {
|
|
13
|
+
type: InterruptionType;
|
|
12
14
|
shouldResume: boolean;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
export type RouteChangeReason =
|
|
18
|
+
| 'Unknown'
|
|
19
|
+
| 'Override'
|
|
20
|
+
| 'CategoryChange'
|
|
21
|
+
| 'WakeFromSleep'
|
|
22
|
+
| 'NewDeviceAvailable'
|
|
23
|
+
| 'OldDeviceUnavailable'
|
|
24
|
+
| 'ConfigurationChange'
|
|
25
|
+
| 'NoSuitableRouteForCategory';
|
|
26
|
+
|
|
27
|
+
export interface OnRouteChangeEventType {
|
|
28
|
+
reason: RouteChangeReason;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
export interface OnRecorderErrorEventType {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { AudioManager } from '../api';
|
|
4
|
+
import { OnRouteChangeEventType, RouteChangeReason } from '../events/types';
|
|
5
|
+
import {
|
|
6
|
+
AudioDeviceInfo,
|
|
7
|
+
AudioDeviceList,
|
|
8
|
+
AudioDevicesInfo,
|
|
9
|
+
} from '../system/types';
|
|
10
|
+
|
|
11
|
+
const meaningfulReasons: RouteChangeReason[] = [
|
|
12
|
+
'NewDeviceAvailable',
|
|
13
|
+
'OldDeviceUnavailable',
|
|
14
|
+
// e.g. system picks a different device as current one is not suitable for the new configuration
|
|
15
|
+
'CategoryChange',
|
|
16
|
+
'ConfigurationChange',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A hook that provides basic information and selection capabilities for audio
|
|
21
|
+
* input devices on the system. (iOS only currently). The hook will
|
|
22
|
+
* automatically listen for configuration changes and updates its state. If you
|
|
23
|
+
* need more granular control, consider using the AudioManager API directly.
|
|
24
|
+
*
|
|
25
|
+
* @returns An object containing audio input information and selection
|
|
26
|
+
* capabilities
|
|
27
|
+
*/
|
|
28
|
+
export default function useAudioInput() {
|
|
29
|
+
const [availableInputs, setAvailableInputs] = useState<AudioDeviceList>([]);
|
|
30
|
+
const [currentInput, setCurrentInput] = useState<string | null>(null);
|
|
31
|
+
|
|
32
|
+
const onSelectInput = useCallback(async (device: AudioDeviceInfo) => {
|
|
33
|
+
const success = await AudioManager.setInputDevice(device.id);
|
|
34
|
+
|
|
35
|
+
if (success) {
|
|
36
|
+
setCurrentInput(device.id);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const devicesInfo: AudioDevicesInfo = await AudioManager.getDevicesInfo();
|
|
40
|
+
setAvailableInputs(devicesInfo.availableInputs);
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
async function fetchAvailableInputs() {
|
|
45
|
+
const audioDevices = await AudioManager.getDevicesInfo();
|
|
46
|
+
const currentDeviceId = audioDevices.currentInputs.length
|
|
47
|
+
? audioDevices.currentInputs[0].id
|
|
48
|
+
: null;
|
|
49
|
+
|
|
50
|
+
setAvailableInputs(audioDevices.availableInputs);
|
|
51
|
+
setCurrentInput(currentDeviceId);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function handleRouteChange(event: OnRouteChangeEventType) {
|
|
55
|
+
if (!meaningfulReasons.includes(event.reason)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
await fetchAvailableInputs();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const sub = AudioManager.addSystemEventListener(
|
|
63
|
+
'routeChange',
|
|
64
|
+
handleRouteChange
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
fetchAvailableInputs();
|
|
68
|
+
return () => {
|
|
69
|
+
sub?.remove();
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
73
|
+
return useMemo(
|
|
74
|
+
() => ({
|
|
75
|
+
/**
|
|
76
|
+
* The list of available audio input devices under current device
|
|
77
|
+
* configuration.
|
|
78
|
+
*/
|
|
79
|
+
availableInputs,
|
|
80
|
+
/**
|
|
81
|
+
* The currently selected audio input device, or null if none is yet
|
|
82
|
+
* decided by the system.
|
|
83
|
+
*/
|
|
84
|
+
currentInput: availableInputs.find((d) => d.id === currentInput) || null,
|
|
85
|
+
/**
|
|
86
|
+
* Selects the given device as the current input. Returns true if
|
|
87
|
+
* successful, throws otherwise.
|
|
88
|
+
*/
|
|
89
|
+
onSelectInput,
|
|
90
|
+
}),
|
|
91
|
+
[availableInputs, currentInput, onSelectInput]
|
|
92
|
+
);
|
|
93
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { AudioManager } from '../api';
|
|
3
4
|
|
|
4
5
|
export default function useSystemVolume() {
|
|
5
6
|
const [volume, setVolume] = useState(0);
|
|
@@ -12,9 +13,9 @@ export default function useSystemVolume() {
|
|
|
12
13
|
setVolume(parseFloat(e.value.toFixed(2)));
|
|
13
14
|
}
|
|
14
15
|
);
|
|
16
|
+
|
|
15
17
|
return () => {
|
|
16
18
|
listener?.remove();
|
|
17
|
-
|
|
18
19
|
AudioManager.observeVolumeChanges(false);
|
|
19
20
|
};
|
|
20
21
|
}, []);
|
package/src/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ interface Spec extends TurboModule {
|
|
|
34
34
|
|
|
35
35
|
// Audio devices
|
|
36
36
|
getDevicesInfo(): Promise<AudioDevicesInfo>;
|
|
37
|
+
setInputDevice(deviceId: string): Promise<boolean>;
|
|
37
38
|
|
|
38
39
|
// Notification system
|
|
39
40
|
showNotification(
|
|
@@ -45,6 +46,6 @@ interface Spec extends TurboModule {
|
|
|
45
46
|
isNotificationActive(key: string): Promise<boolean>;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
|
-
const NativeAudioAPIModule = TurboModuleRegistry.get<Spec>('AudioAPIModule')
|
|
49
|
+
const NativeAudioAPIModule = TurboModuleRegistry.get<Spec>('AudioAPIModule')!;
|
|
49
50
|
|
|
50
51
|
export { NativeAudioAPIModule };
|
|
@@ -35,6 +35,7 @@ interface Spec extends TurboModule {
|
|
|
35
35
|
|
|
36
36
|
// Audio devices
|
|
37
37
|
getDevicesInfo(): Promise<AudioDevicesInfo>;
|
|
38
|
+
setInputDevice(deviceId: string): Promise<boolean>;
|
|
38
39
|
|
|
39
40
|
// New notification system
|
|
40
41
|
showNotification(
|
|
@@ -74,6 +75,7 @@ const NativeAudioAPIModule: Spec = {
|
|
|
74
75
|
currentInputs: [],
|
|
75
76
|
currentOutputs: [],
|
|
76
77
|
}),
|
|
78
|
+
setInputDevice: mockAsync(true),
|
|
77
79
|
showNotification: mockAsync({ success: true }),
|
|
78
80
|
hideNotification: mockAsync({ success: true }),
|
|
79
81
|
isNotificationActive: mockAsync(false),
|
|
@@ -94,6 +94,10 @@ class AudioManager implements IAudioManager {
|
|
|
94
94
|
async getDevicesInfo(): Promise<AudioDevicesInfo> {
|
|
95
95
|
return NativeAudioAPIModule.getDevicesInfo();
|
|
96
96
|
}
|
|
97
|
+
|
|
98
|
+
async setInputDevice(deviceId: string): Promise<boolean> {
|
|
99
|
+
return NativeAudioAPIModule.setInputDevice(deviceId);
|
|
100
|
+
}
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
export default new AudioManager();
|
package/src/system/types.ts
CHANGED
|
@@ -24,8 +24,8 @@ export type IOSOption =
|
|
|
24
24
|
| 'duckOthers'
|
|
25
25
|
| 'allowAirPlay'
|
|
26
26
|
| 'mixWithOthers'
|
|
27
|
-
| 'allowBluetooth'
|
|
28
27
|
| 'defaultToSpeaker'
|
|
28
|
+
| 'allowBluetoothHFP'
|
|
29
29
|
| 'allowBluetoothA2DP'
|
|
30
30
|
| 'overrideMutedMicrophoneInterruption'
|
|
31
31
|
| 'interruptSpokenAudioAndMixWithOthers';
|
|
@@ -40,6 +40,7 @@ export interface SessionOptions {
|
|
|
40
40
|
export type PermissionStatus = 'Undetermined' | 'Denied' | 'Granted';
|
|
41
41
|
|
|
42
42
|
export interface AudioDeviceInfo {
|
|
43
|
+
id: string;
|
|
43
44
|
name: string;
|
|
44
45
|
category: string;
|
|
45
46
|
}
|
|
@@ -70,4 +71,5 @@ export interface IAudioManager {
|
|
|
70
71
|
requestNotificationPermissions(): Promise<PermissionStatus>;
|
|
71
72
|
checkNotificationPermissions(): Promise<PermissionStatus>;
|
|
72
73
|
getDevicesInfo(): Promise<AudioDevicesInfo>;
|
|
74
|
+
setInputDevice(deviceId: string): Promise<boolean>;
|
|
73
75
|
}
|
|
@@ -22,6 +22,7 @@ class AudioManager implements IAudioManager {
|
|
|
22
22
|
checkRecordingPermissions = mockAsync('Granted' as PermissionStatus);
|
|
23
23
|
requestNotificationPermissions = mockAsync('Granted' as PermissionStatus);
|
|
24
24
|
checkNotificationPermissions = mockAsync('Granted' as PermissionStatus);
|
|
25
|
+
setInputDevice = mockAsync(true);
|
|
25
26
|
getDevicesInfo = mockAsync({
|
|
26
27
|
availableInputs: [],
|
|
27
28
|
availableOutputs: [],
|