react-native-audio-api 0.6.0-rc.5 → 0.6.0

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.
Files changed (201) hide show
  1. package/android/src/main/cpp/audioapi/android/AudioAPIModule.cpp +35 -2
  2. package/android/src/main/cpp/audioapi/android/AudioAPIModule.h +4 -0
  3. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.cpp +31 -17
  4. package/android/src/main/cpp/audioapi/android/core/AndroidAudioRecorder.h +1 -3
  5. package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +56 -2
  6. package/android/src/main/java/com/swmansion/audioapi/AudioAPIPackage.kt +0 -12
  7. package/android/src/main/java/com/swmansion/audioapi/system/AudioFocusListener.kt +35 -12
  8. package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +30 -29
  9. package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +20 -22
  10. package/android/src/main/java/com/swmansion/audioapi/system/MediaReceiver.kt +19 -9
  11. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +30 -11
  12. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +34 -27
  13. package/android/src/main/java/com/swmansion/audioapi/system/VolumeChangeListener.kt +10 -5
  14. package/android/src/oldarch/NativeAudioAPIModuleSpec.java +39 -0
  15. package/common/cpp/audioapi/AudioAPIModuleInstaller.h +20 -14
  16. package/common/cpp/audioapi/HostObjects/AudioBufferSourceNodeHostObject.h +2 -3
  17. package/common/cpp/audioapi/HostObjects/AudioNodeHostObject.h +24 -11
  18. package/common/cpp/audioapi/HostObjects/AudioParamHostObject.h +1 -0
  19. package/common/cpp/audioapi/HostObjects/AudioRecorderHostObject.h +10 -89
  20. package/common/cpp/audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h +3 -24
  21. package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +2 -2
  22. package/common/cpp/audioapi/HostObjects/OscillatorNodeHostObject.h +2 -3
  23. package/common/cpp/audioapi/core/AudioContext.cpp +4 -1
  24. package/common/cpp/audioapi/core/AudioContext.h +1 -1
  25. package/common/cpp/audioapi/core/AudioNode.cpp +31 -2
  26. package/common/cpp/audioapi/core/AudioNode.h +7 -1
  27. package/common/cpp/audioapi/core/AudioParam.cpp +84 -2
  28. package/common/cpp/audioapi/core/AudioParam.h +14 -1
  29. package/common/cpp/audioapi/core/BaseAudioContext.cpp +6 -1
  30. package/common/cpp/audioapi/core/BaseAudioContext.h +7 -1
  31. package/common/cpp/audioapi/core/OfflineAudioContext.cpp +3 -2
  32. package/common/cpp/audioapi/core/OfflineAudioContext.h +1 -1
  33. package/common/cpp/audioapi/core/effects/BiquadFilterNode.cpp +28 -26
  34. package/common/cpp/audioapi/core/effects/GainNode.cpp +9 -9
  35. package/common/cpp/audioapi/core/effects/StereoPannerNode.cpp +5 -2
  36. package/common/cpp/audioapi/core/inputs/AudioRecorder.cpp +56 -0
  37. package/common/cpp/audioapi/core/inputs/AudioRecorder.h +13 -13
  38. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +14 -10
  39. package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
  40. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +7 -6
  41. package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +5 -3
  42. package/common/cpp/audioapi/core/sources/OscillatorNode.cpp +15 -10
  43. package/common/cpp/audioapi/core/utils/AudioNodeManager.cpp +35 -1
  44. package/common/cpp/audioapi/core/utils/AudioNodeManager.h +15 -1
  45. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +108 -0
  46. package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +62 -0
  47. package/common/cpp/audioapi/events/AudioEventHandlerRegistryHostObject.h +48 -0
  48. package/common/cpp/audioapi/jsi/JsiPromise.cpp +3 -4
  49. package/ios/audioapi/ios/AudioAPIModule.h +13 -0
  50. package/ios/audioapi/ios/AudioAPIModule.mm +115 -6
  51. package/ios/audioapi/ios/core/IOSAudioRecorder.h +2 -10
  52. package/ios/audioapi/ios/core/IOSAudioRecorder.mm +6 -17
  53. package/ios/audioapi/ios/core/NativeAudioPlayer.m +2 -0
  54. package/ios/audioapi/ios/core/NativeAudioRecorder.m +7 -3
  55. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.h +7 -0
  56. package/ios/audioapi/ios/events/IOSAudioEventHandlerRegistry.mm +12 -0
  57. package/ios/audioapi/ios/system/AudioEngine.h +5 -0
  58. package/ios/audioapi/ios/system/AudioEngine.mm +7 -15
  59. package/ios/audioapi/ios/system/AudioSessionManager.h +1 -1
  60. package/ios/audioapi/ios/system/AudioSessionManager.mm +2 -18
  61. package/ios/audioapi/ios/system/LockScreenManager.h +3 -3
  62. package/ios/audioapi/ios/system/LockScreenManager.mm +36 -48
  63. package/ios/audioapi/ios/system/NotificationManager.h +3 -3
  64. package/ios/audioapi/ios/system/NotificationManager.mm +21 -29
  65. package/lib/commonjs/api.js +4 -4
  66. package/lib/commonjs/api.js.map +1 -1
  67. package/lib/commonjs/core/AudioBufferSourceNode.js +2 -2
  68. package/lib/commonjs/core/AudioBufferSourceNode.js.map +1 -1
  69. package/lib/commonjs/core/AudioNode.js +8 -2
  70. package/lib/commonjs/core/AudioNode.js.map +1 -1
  71. package/lib/commonjs/core/AudioParam.js +2 -1
  72. package/lib/commonjs/core/AudioParam.js.map +1 -1
  73. package/lib/commonjs/core/AudioRecorder.js +11 -28
  74. package/lib/commonjs/core/AudioRecorder.js.map +1 -1
  75. package/lib/commonjs/core/AudioScheduledSourceNode.js +4 -1
  76. package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
  77. package/lib/commonjs/core/BiquadFilterNode.js +4 -4
  78. package/lib/commonjs/core/BiquadFilterNode.js.map +1 -1
  79. package/lib/commonjs/core/GainNode.js +1 -1
  80. package/lib/commonjs/core/GainNode.js.map +1 -1
  81. package/lib/commonjs/core/OscillatorNode.js +2 -2
  82. package/lib/commonjs/core/OscillatorNode.js.map +1 -1
  83. package/lib/commonjs/core/StereoPannerNode.js +1 -1
  84. package/lib/commonjs/core/StereoPannerNode.js.map +1 -1
  85. package/lib/commonjs/events/AudioEventEmitter.js +22 -0
  86. package/lib/commonjs/events/AudioEventEmitter.js.map +1 -0
  87. package/lib/commonjs/events/AudioEventSubscription.js +20 -0
  88. package/lib/commonjs/events/AudioEventSubscription.js.map +1 -0
  89. package/lib/commonjs/events/index.js +21 -0
  90. package/lib/commonjs/events/index.js.map +1 -0
  91. package/lib/commonjs/events/types.js +6 -0
  92. package/lib/commonjs/events/types.js.map +1 -0
  93. package/lib/commonjs/hooks/useSytemVolume.js +1 -1
  94. package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
  95. package/lib/commonjs/specs/NativeAudioAPIModule.js +3 -3
  96. package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
  97. package/lib/commonjs/specs/index.js +2 -16
  98. package/lib/commonjs/specs/index.js.map +1 -1
  99. package/lib/commonjs/system/AudioManager.js +22 -28
  100. package/lib/commonjs/system/AudioManager.js.map +1 -1
  101. package/lib/module/api.js +2 -2
  102. package/lib/module/api.js.map +1 -1
  103. package/lib/module/core/AudioBufferSourceNode.js +2 -2
  104. package/lib/module/core/AudioBufferSourceNode.js.map +1 -1
  105. package/lib/module/core/AudioNode.js +7 -2
  106. package/lib/module/core/AudioNode.js.map +1 -1
  107. package/lib/module/core/AudioParam.js +2 -1
  108. package/lib/module/core/AudioParam.js.map +1 -1
  109. package/lib/module/core/AudioRecorder.js +11 -28
  110. package/lib/module/core/AudioRecorder.js.map +1 -1
  111. package/lib/module/core/AudioScheduledSourceNode.js +4 -1
  112. package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
  113. package/lib/module/core/BiquadFilterNode.js +4 -4
  114. package/lib/module/core/BiquadFilterNode.js.map +1 -1
  115. package/lib/module/core/GainNode.js +1 -1
  116. package/lib/module/core/GainNode.js.map +1 -1
  117. package/lib/module/core/OscillatorNode.js +2 -2
  118. package/lib/module/core/OscillatorNode.js.map +1 -1
  119. package/lib/module/core/StereoPannerNode.js +1 -1
  120. package/lib/module/core/StereoPannerNode.js.map +1 -1
  121. package/lib/module/events/AudioEventEmitter.js +16 -0
  122. package/lib/module/events/AudioEventEmitter.js.map +1 -0
  123. package/lib/module/events/AudioEventSubscription.js +15 -0
  124. package/lib/module/events/AudioEventSubscription.js.map +1 -0
  125. package/lib/module/events/index.js +6 -0
  126. package/lib/module/events/index.js.map +1 -0
  127. package/lib/module/events/types.js +4 -0
  128. package/lib/module/events/types.js.map +1 -0
  129. package/lib/module/hooks/useSytemVolume.js +1 -1
  130. package/lib/module/hooks/useSytemVolume.js.map +1 -1
  131. package/lib/module/specs/NativeAudioAPIModule.js +3 -2
  132. package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
  133. package/lib/module/specs/index.js +2 -3
  134. package/lib/module/specs/index.js.map +1 -1
  135. package/lib/module/system/AudioManager.js +23 -29
  136. package/lib/module/system/AudioManager.js.map +1 -1
  137. package/lib/typescript/api.d.ts +2 -1
  138. package/lib/typescript/api.d.ts.map +1 -1
  139. package/lib/typescript/core/AudioNode.d.ts +2 -1
  140. package/lib/typescript/core/AudioNode.d.ts.map +1 -1
  141. package/lib/typescript/core/AudioParam.d.ts +4 -2
  142. package/lib/typescript/core/AudioParam.d.ts.map +1 -1
  143. package/lib/typescript/core/AudioRecorder.d.ts +4 -14
  144. package/lib/typescript/core/AudioRecorder.d.ts.map +1 -1
  145. package/lib/typescript/core/AudioScheduledSourceNode.d.ts +3 -1
  146. package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
  147. package/lib/typescript/events/AudioEventEmitter.d.ts +10 -0
  148. package/lib/typescript/events/AudioEventEmitter.d.ts.map +1 -0
  149. package/lib/typescript/events/AudioEventSubscription.d.ts +11 -0
  150. package/lib/typescript/events/AudioEventSubscription.d.ts.map +1 -0
  151. package/lib/typescript/events/index.d.ts +4 -0
  152. package/lib/typescript/events/index.d.ts.map +1 -0
  153. package/lib/typescript/events/types.d.ts +50 -0
  154. package/lib/typescript/events/types.d.ts.map +1 -0
  155. package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
  156. package/lib/typescript/interfaces.d.ts +10 -10
  157. package/lib/typescript/interfaces.d.ts.map +1 -1
  158. package/lib/typescript/specs/NativeAudioAPIModule.d.ts +15 -3
  159. package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
  160. package/lib/typescript/specs/index.d.ts +2 -3
  161. package/lib/typescript/specs/index.d.ts.map +1 -1
  162. package/lib/typescript/system/AudioManager.d.ts +6 -4
  163. package/lib/typescript/system/AudioManager.d.ts.map +1 -1
  164. package/lib/typescript/system/types.d.ts +0 -34
  165. package/lib/typescript/system/types.d.ts.map +1 -1
  166. package/lib/typescript/types.d.ts +0 -1
  167. package/lib/typescript/types.d.ts.map +1 -1
  168. package/package.json +3 -3
  169. package/src/api.ts +6 -3
  170. package/src/core/AudioBufferSourceNode.ts +2 -2
  171. package/src/core/AudioNode.ts +8 -3
  172. package/src/core/AudioParam.ts +5 -2
  173. package/src/core/AudioRecorder.ts +22 -62
  174. package/src/core/AudioScheduledSourceNode.ts +13 -2
  175. package/src/core/BiquadFilterNode.ts +4 -4
  176. package/src/core/GainNode.ts +1 -1
  177. package/src/core/OscillatorNode.ts +2 -2
  178. package/src/core/StereoPannerNode.ts +1 -1
  179. package/src/events/AudioEventEmitter.ts +29 -0
  180. package/src/events/AudioEventSubscription.ts +26 -0
  181. package/src/events/index.ts +4 -0
  182. package/src/events/types.ts +64 -0
  183. package/src/hooks/useSytemVolume.ts +2 -1
  184. package/src/interfaces.ts +19 -20
  185. package/src/specs/NativeAudioAPIModule.ts +23 -2
  186. package/src/specs/index.ts +2 -4
  187. package/src/system/AudioManager.ts +35 -43
  188. package/src/system/types.ts +0 -42
  189. package/src/types.ts +0 -8
  190. package/android/src/main/java/com/swmansion/audioapi/AudioManagerModule.kt +0 -77
  191. package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionEventEmitter.kt +0 -88
  192. package/android/src/oldarch/NativeAudioManagerModuleSpec.java +0 -99
  193. package/ios/audioapi/ios/AudioManagerModule.h +0 -18
  194. package/ios/audioapi/ios/AudioManagerModule.mm +0 -108
  195. package/lib/commonjs/specs/NativeAudioManagerModule.js +0 -42
  196. package/lib/commonjs/specs/NativeAudioManagerModule.js.map +0 -1
  197. package/lib/module/specs/NativeAudioManagerModule.js +0 -39
  198. package/lib/module/specs/NativeAudioManagerModule.js.map +0 -1
  199. package/lib/typescript/specs/NativeAudioManagerModule.d.ts +0 -18
  200. package/lib/typescript/specs/NativeAudioManagerModule.d.ts.map +0 -1
  201. package/src/specs/NativeAudioManagerModule.ts +0 -53
@@ -1,56 +1,14 @@
1
- import {
2
- IAudioRecorder,
3
- IErrorCallback,
4
- IAudioReadyCallback,
5
- IStatusChangeCallback,
6
- IAudioBuffer,
7
- } from '../interfaces';
8
- import { AudioRecorderStatus, AudioRecorderOptions } from '../types';
1
+ import { IAudioRecorder } from '../interfaces';
2
+ import { AudioRecorderOptions } from '../types';
9
3
  import AudioBuffer from './AudioBuffer';
10
-
11
- export type AudioReadyCallback = (
12
- buffer: AudioBuffer,
13
- numFrames: number,
14
- when: number
15
- ) => void;
16
-
17
- export type ErrorCallback = (error: Error) => void;
18
-
19
- export type StatusChangeCallback = (
20
- status: AudioRecorderStatus,
21
- previousStatus: AudioRecorderStatus
22
- ) => void;
4
+ import { OnAudioReadyEventType } from '../events/types';
5
+ import { AudioEventEmitter } from '../events';
23
6
 
24
7
  export default class AudioRecorder {
25
8
  protected readonly recorder: IAudioRecorder;
26
- private onAudioReadyCallback: AudioReadyCallback | null = null;
27
- private onErrorCallback: ErrorCallback | null = null;
28
- private onStatusChangeCallback: StatusChangeCallback | null = null;
29
-
30
- private onAudioReadyInternal: IAudioReadyCallback = (
31
- buffer: IAudioBuffer,
32
- numFrames: number,
33
- when: number
34
- ) => {
35
- if (this.onAudioReadyCallback) {
36
- this.onAudioReadyCallback(new AudioBuffer(buffer), numFrames, when);
37
- }
38
- };
39
-
40
- private onErrorInternal: IErrorCallback = (error: Error) => {
41
- if (this.onErrorCallback) {
42
- this.onErrorCallback(error);
43
- }
44
- };
45
-
46
- private onStatusChangeInternal: IStatusChangeCallback = (
47
- status: AudioRecorderStatus,
48
- previousStatus: AudioRecorderStatus
49
- ) => {
50
- if (this.onStatusChangeCallback) {
51
- this.onStatusChangeCallback(status, previousStatus);
52
- }
53
- };
9
+ private readonly audioEventEmitter = new AudioEventEmitter(
10
+ global.AudioEventEmitter
11
+ );
54
12
 
55
13
  constructor(options: AudioRecorderOptions) {
56
14
  this.recorder = global.createAudioRecorder(options);
@@ -64,18 +22,20 @@ export default class AudioRecorder {
64
22
  this.recorder.stop();
65
23
  }
66
24
 
67
- public onAudioReady(callback: AudioReadyCallback): void {
68
- this.onAudioReadyCallback = callback;
69
- this.recorder.onAudioReady(this.onAudioReadyInternal);
70
- }
71
-
72
- public onError(callback: ErrorCallback): void {
73
- this.onErrorCallback = callback;
74
- this.recorder.onError(this.onErrorInternal);
75
- }
76
-
77
- public onStatusChange(callback: StatusChangeCallback): void {
78
- this.onStatusChangeCallback = callback;
79
- this.recorder.onStatusChange(this.onStatusChangeInternal);
25
+ public onAudioReady(callback: (event: OnAudioReadyEventType) => void): void {
26
+ const onAudioReadyCallback = (event: OnAudioReadyEventType) => {
27
+ callback({
28
+ buffer: new AudioBuffer(event.buffer),
29
+ numFrames: event.numFrames,
30
+ when: event.when,
31
+ });
32
+ };
33
+
34
+ const subscription = this.audioEventEmitter.addAudioEventListener(
35
+ 'audioReady',
36
+ onAudioReadyCallback
37
+ );
38
+
39
+ this.recorder.onAudioReady = subscription.subscriptionId;
80
40
  }
81
41
  }
@@ -1,9 +1,14 @@
1
1
  import { IAudioScheduledSourceNode } from '../interfaces';
2
2
  import AudioNode from './AudioNode';
3
3
  import { InvalidStateError, RangeError } from '../errors';
4
+ import { EventTypeWithValue } from '../events/types';
5
+ import { AudioEventEmitter } from '../events';
4
6
 
5
7
  export default class AudioScheduledSourceNode extends AudioNode {
6
8
  protected hasBeenStarted: boolean = false;
9
+ private readonly audioEventEmitter = new AudioEventEmitter(
10
+ global.AudioEventEmitter
11
+ );
7
12
 
8
13
  public start(when: number = 0): void {
9
14
  if (when < 0) {
@@ -37,7 +42,13 @@ export default class AudioScheduledSourceNode extends AudioNode {
37
42
  }
38
43
 
39
44
  // eslint-disable-next-line accessor-pairs
40
- public set onended(callback: (arg?: number) => void) {
41
- (this.node as IAudioScheduledSourceNode).onended = callback;
45
+ public set onended(callback: (event: EventTypeWithValue) => void) {
46
+ const subscription = this.audioEventEmitter.addAudioEventListener(
47
+ 'ended',
48
+ callback
49
+ );
50
+
51
+ (this.node as IAudioScheduledSourceNode).onended =
52
+ subscription.subscriptionId;
42
53
  }
43
54
  }
@@ -13,10 +13,10 @@ export default class BiquadFilterNode extends AudioNode {
13
13
 
14
14
  constructor(context: BaseAudioContext, biquadFilter: IBiquadFilterNode) {
15
15
  super(context, biquadFilter);
16
- this.frequency = new AudioParam(biquadFilter.frequency);
17
- this.detune = new AudioParam(biquadFilter.detune);
18
- this.Q = new AudioParam(biquadFilter.Q);
19
- this.gain = new AudioParam(biquadFilter.gain);
16
+ this.frequency = new AudioParam(biquadFilter.frequency, context);
17
+ this.detune = new AudioParam(biquadFilter.detune, context);
18
+ this.Q = new AudioParam(biquadFilter.Q, context);
19
+ this.gain = new AudioParam(biquadFilter.gain, context);
20
20
  }
21
21
 
22
22
  public get type(): BiquadFilterType {
@@ -8,6 +8,6 @@ export default class GainNode extends AudioNode {
8
8
 
9
9
  constructor(context: BaseAudioContext, gain: IGainNode) {
10
10
  super(context, gain);
11
- this.gain = new AudioParam(gain.gain);
11
+ this.gain = new AudioParam(gain.gain, context);
12
12
  }
13
13
  }
@@ -12,8 +12,8 @@ export default class OscillatorNode extends AudioScheduledSourceNode {
12
12
 
13
13
  constructor(context: BaseAudioContext, node: IOscillatorNode) {
14
14
  super(context, node);
15
- this.frequency = new AudioParam(node.frequency);
16
- this.detune = new AudioParam(node.detune);
15
+ this.frequency = new AudioParam(node.frequency, context);
16
+ this.detune = new AudioParam(node.detune, context);
17
17
  this.type = node.type;
18
18
  }
19
19
 
@@ -8,6 +8,6 @@ export default class StereoPannerNode extends AudioNode {
8
8
 
9
9
  constructor(context: BaseAudioContext, pan: IStereoPannerNode) {
10
10
  super(context, pan);
11
- this.pan = new AudioParam(pan.pan);
11
+ this.pan = new AudioParam(pan.pan, context);
12
12
  }
13
13
  }
@@ -0,0 +1,29 @@
1
+ import { AudioEventName, AudioEventCallback } from './types';
2
+ import AudioEventSubscription from './AudioEventSubscription';
3
+ import { IAudioEventEmitter } from '../interfaces';
4
+
5
+ export default class AudioEventEmitter {
6
+ private readonly audioEventEmitter: IAudioEventEmitter;
7
+
8
+ constructor(audioEventEmitter: IAudioEventEmitter) {
9
+ this.audioEventEmitter = audioEventEmitter;
10
+ }
11
+
12
+ addAudioEventListener<Name extends AudioEventName>(
13
+ name: Name,
14
+ callback: AudioEventCallback<Name>
15
+ ): AudioEventSubscription {
16
+ const subscriptionId = this.audioEventEmitter.addAudioEventListener(
17
+ name,
18
+ callback
19
+ );
20
+ return new AudioEventSubscription(subscriptionId, name, this);
21
+ }
22
+
23
+ removeAudioEventListener<Name extends AudioEventName>(
24
+ name: Name,
25
+ subscriptionId: string
26
+ ): void {
27
+ this.audioEventEmitter.removeAudioEventListener(name, subscriptionId);
28
+ }
29
+ }
@@ -0,0 +1,26 @@
1
+ import { AudioEventName } from './types';
2
+ import { AudioEventEmitter } from './';
3
+
4
+ export default class AudioEventSubscription {
5
+ private readonly audioEventEmitter: AudioEventEmitter;
6
+ private readonly eventName: AudioEventName;
7
+ /** @internal */
8
+ public readonly subscriptionId: string;
9
+
10
+ constructor(
11
+ subscriptionId: string,
12
+ eventName: AudioEventName,
13
+ audioEventEmitter: AudioEventEmitter
14
+ ) {
15
+ this.subscriptionId = subscriptionId;
16
+ this.eventName = eventName;
17
+ this.audioEventEmitter = audioEventEmitter;
18
+ }
19
+
20
+ public remove(): void {
21
+ this.audioEventEmitter.removeAudioEventListener(
22
+ this.eventName,
23
+ this.subscriptionId
24
+ );
25
+ }
26
+ }
@@ -0,0 +1,4 @@
1
+ import AudioEventEmitter from './AudioEventEmitter';
2
+ import AudioEventSubscription from './AudioEventSubscription';
3
+
4
+ export { AudioEventEmitter, AudioEventSubscription };
@@ -0,0 +1,64 @@
1
+ import AudioBuffer from '../core/AudioBuffer';
2
+
3
+ interface EventEmptyType {}
4
+
5
+ export interface EventTypeWithValue {
6
+ value: number;
7
+ }
8
+
9
+ interface OnInterruptionEventType {
10
+ type: 'ended' | 'began';
11
+ shouldResume: boolean;
12
+ }
13
+
14
+ interface OnRouteChangeEventType {
15
+ reason: string;
16
+ }
17
+
18
+ interface SystemEvents {
19
+ remotePlay: EventEmptyType;
20
+ remotePause: EventEmptyType;
21
+ remoteStop: EventEmptyType;
22
+ remoteTogglePlayPause: EventEmptyType;
23
+ remoteChangePlaybackRate: EventTypeWithValue;
24
+ remoteNextTrack: EventEmptyType;
25
+ remotePreviousTrack: EventEmptyType;
26
+ remoteSkipForward: EventEmptyType;
27
+ remoteSkipBackward: EventEmptyType;
28
+ remoteSeekForward: EventTypeWithValue;
29
+ remoteSeekBackward: EventTypeWithValue;
30
+ remoteChangePlaybackPosition: EventTypeWithValue;
31
+ volumeChange: EventTypeWithValue;
32
+ interruption: OnInterruptionEventType;
33
+ routeChange: OnRouteChangeEventType;
34
+ }
35
+
36
+ export interface OnAudioReadyEventType {
37
+ buffer: AudioBuffer;
38
+ numFrames: number;
39
+ when: number;
40
+ }
41
+
42
+ interface AudioAPIEvents {
43
+ ended: EventTypeWithValue;
44
+ audioReady: OnAudioReadyEventType;
45
+ audioError: EventEmptyType; // to change
46
+ systemStateChanged: EventEmptyType; // to change
47
+ }
48
+
49
+ type AudioEvents = SystemEvents & AudioAPIEvents;
50
+
51
+ export type SystemEventName = keyof SystemEvents;
52
+ export type SystemEventCallback<Name extends SystemEventName> = (
53
+ event: SystemEvents[Name]
54
+ ) => void;
55
+
56
+ export type AudioAPIEventName = keyof AudioAPIEvents;
57
+ export type AudioAPIEventCallback<Name extends AudioAPIEventName> = (
58
+ event: AudioAPIEvents[Name]
59
+ ) => void;
60
+
61
+ export type AudioEventName = keyof AudioEvents;
62
+ export type AudioEventCallback<Name extends AudioEventName> = (
63
+ event: AudioEvents[Name]
64
+ ) => void;
@@ -6,11 +6,12 @@ export default function useSystemVolume() {
6
6
 
7
7
  useEffect(() => {
8
8
  AudioManager.observeVolumeChanges(true);
9
- const listener = AudioManager.enableRemoteEvent('volumeChange', (e) => {
9
+ const listener = AudioManager.enableSystemEvent('volumeChange', (e) => {
10
10
  setVolume(parseFloat(e.value.toFixed(2)));
11
11
  });
12
12
  return () => {
13
13
  listener?.remove();
14
+
14
15
  AudioManager.observeVolumeChanges(false);
15
16
  };
16
17
  }, []);
package/src/interfaces.ts CHANGED
@@ -4,9 +4,9 @@ import {
4
4
  OscillatorType,
5
5
  BiquadFilterType,
6
6
  ChannelCountMode,
7
- AudioRecorderStatus,
8
7
  ChannelInterpretation,
9
8
  } from './types';
9
+ import { AudioEventName, AudioEventCallback } from './events/types';
10
10
 
11
11
  export interface IBaseAudioContext {
12
12
  readonly destination: IAudioDestinationNode;
@@ -54,8 +54,8 @@ export interface IAudioNode {
54
54
  readonly channelCountMode: ChannelCountMode;
55
55
  readonly channelInterpretation: ChannelInterpretation;
56
56
 
57
- connect: (node: IAudioNode) => void;
58
- disconnect: (node?: IAudioNode) => void;
57
+ connect: (destination: IAudioNode | IAudioParam) => void;
58
+ disconnect: (destination?: IAudioNode | IAudioParam) => void;
59
59
  }
60
60
 
61
61
  export interface IGainNode extends IAudioNode {
@@ -85,7 +85,9 @@ export interface IAudioDestinationNode extends IAudioNode {}
85
85
  export interface IAudioScheduledSourceNode extends IAudioNode {
86
86
  start(when?: number): void;
87
87
  stop: (when: number) => void;
88
- onended: (arg?: number) => void | null;
88
+
89
+ // passing subscriptionId(uint_64 in cpp, string in js) to the cpp
90
+ onended: string;
89
91
  }
90
92
 
91
93
  export interface IOscillatorNode extends IAudioScheduledSourceNode {
@@ -165,24 +167,21 @@ export interface IAnalyserNode extends IAudioNode {
165
167
  getByteTimeDomainData: (array: Uint8Array) => void;
166
168
  }
167
169
 
168
- export type IAudioReadyCallback = (
169
- buffer: IAudioBuffer,
170
- numFrames: number,
171
- when: number
172
- ) => void;
173
-
174
- export type IErrorCallback = (error: Error) => void;
175
-
176
- export type IStatusChangeCallback = (
177
- status: AudioRecorderStatus,
178
- previousStatus: AudioRecorderStatus
179
- ) => void;
180
-
181
170
  export interface IAudioRecorder {
182
171
  start: () => void;
183
172
  stop: () => void;
184
173
 
185
- onAudioReady: (callback: IAudioReadyCallback) => void;
186
- onError: (callback: IErrorCallback) => void;
187
- onStatusChange: (callback: IStatusChangeCallback) => void;
174
+ // passing subscriptionId(uint_64 in cpp, string in js) to the cpp
175
+ onAudioReady: string;
176
+ }
177
+
178
+ export interface IAudioEventEmitter {
179
+ addAudioEventListener<Name extends AudioEventName>(
180
+ name: Name,
181
+ callback: AudioEventCallback<Name>
182
+ ): string;
183
+ removeAudioEventListener<Name extends AudioEventName>(
184
+ name: Name,
185
+ subscriptionId: string
186
+ ): void;
188
187
  }
@@ -1,7 +1,28 @@
1
- import { TurboModuleRegistry, TurboModule } from 'react-native';
1
+ 'use strict';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+ import type { TurboModule } from 'react-native';
4
+ import { PermissionStatus } from '../system/types';
2
5
 
3
6
  interface Spec extends TurboModule {
4
7
  install(): boolean;
8
+
9
+ setLockScreenInfo(info: {
10
+ [key: string]: string | boolean | number | undefined;
11
+ }): void;
12
+ resetLockScreenInfo(): void;
13
+ enableRemoteCommand(name: string, enabled: boolean): void;
14
+ setAudioSessionOptions(
15
+ category: string,
16
+ mode: string,
17
+ options: Array<string>
18
+ ): void;
19
+ getDevicePreferredSampleRate(): number;
20
+ observeAudioInterruptions(enabled: boolean): void;
21
+ observeVolumeChanges(enabled: boolean): void;
22
+ requestRecordingPermissions(): Promise<PermissionStatus>;
23
+ checkRecordingPermissions(): Promise<PermissionStatus>;
5
24
  }
6
25
 
7
- export default TurboModuleRegistry.get<Spec>('AudioAPIModule');
26
+ const NativeAudioAPIModule = TurboModuleRegistry.get<Spec>('AudioAPIModule');
27
+
28
+ export { NativeAudioAPIModule };
@@ -1,6 +1,4 @@
1
1
  'use strict';
2
+ import { NativeAudioAPIModule } from './NativeAudioAPIModule';
2
3
 
3
- import NativeAudioAPIModule from './NativeAudioAPIModule';
4
- import { AudioManagerModule, eventEmitter } from './NativeAudioManagerModule';
5
-
6
- export { NativeAudioAPIModule, AudioManagerModule, eventEmitter };
4
+ export { NativeAudioAPIModule };
@@ -1,25 +1,34 @@
1
- import {
2
- SessionOptions,
3
- LockScreenInfo,
4
- RemoteEventName,
5
- RemoteEventCallback,
6
- RemoteCommandName,
7
- PermissionStatus,
8
- } from './types';
9
- import { AudioManagerModule, eventEmitter } from '../specs';
10
- import { EmitterSubscription } from 'react-native';
1
+ import { SessionOptions, LockScreenInfo, PermissionStatus } from './types';
2
+ import { SystemEventName, SystemEventCallback } from '../events/types';
3
+ import { NativeAudioAPIModule } from '../specs';
4
+ import { AudioEventEmitter, AudioEventSubscription } from '../events';
5
+
6
+ if (global.AudioEventEmitter == null) {
7
+ if (!NativeAudioAPIModule) {
8
+ throw new Error(
9
+ `Failed to install react-native-audio-api: The native module could not be found.`
10
+ );
11
+ }
12
+
13
+ NativeAudioAPIModule.install();
14
+ }
11
15
 
12
16
  class AudioManager {
17
+ private readonly audioEventEmitter: AudioEventEmitter;
18
+ constructor() {
19
+ this.audioEventEmitter = new AudioEventEmitter(global.AudioEventEmitter);
20
+ }
21
+
13
22
  setLockScreenInfo(info: LockScreenInfo) {
14
- AudioManagerModule.setLockScreenInfo(info);
23
+ NativeAudioAPIModule!.setLockScreenInfo(info);
15
24
  }
16
25
 
17
26
  resetLockScreenInfo() {
18
- AudioManagerModule.resetLockScreenInfo();
27
+ NativeAudioAPIModule!.resetLockScreenInfo();
19
28
  }
20
29
 
21
30
  setAudioSessionOptions(options: SessionOptions) {
22
- AudioManagerModule.setAudioSessionOptions(
31
+ NativeAudioAPIModule!.setAudioSessionOptions(
23
32
  options.iosCategory ?? '',
24
33
  options.iosMode ?? '',
25
34
  options.iosOptions ?? []
@@ -27,54 +36,37 @@ class AudioManager {
27
36
  }
28
37
 
29
38
  getDevicePreferredSampleRate(): number {
30
- return AudioManagerModule.getDevicePreferredSampleRate();
39
+ return NativeAudioAPIModule!.getDevicePreferredSampleRate();
31
40
  }
32
41
 
33
42
  observeAudioInterruptions(enabled: boolean) {
34
- AudioManagerModule.observeAudioInterruptions(enabled);
43
+ NativeAudioAPIModule!.observeAudioInterruptions(enabled);
35
44
  }
36
45
 
37
46
  observeVolumeChanges(enabled: boolean) {
38
- AudioManagerModule.observeVolumeChanges(enabled);
47
+ NativeAudioAPIModule!.observeVolumeChanges(enabled);
39
48
  }
40
49
 
41
- enableRemoteCommand<Name extends RemoteCommandName>(name: Name): void {
42
- AudioManagerModule.enableRemoteCommand(name, true);
43
- }
44
-
45
- enableRemoteEvent<Name extends RemoteEventName>(
50
+ enableSystemEvent<Name extends SystemEventName>(
46
51
  name: Name,
47
- callback?: RemoteEventCallback<Name>
48
- ): EmitterSubscription | null {
49
- let subscription = null;
50
- if (!callback) {
52
+ callback?: SystemEventCallback<Name>,
53
+ enabled = true
54
+ ): AudioEventSubscription | null {
55
+ NativeAudioAPIModule!.enableRemoteCommand(name, enabled);
56
+
57
+ if (!enabled || !callback) {
51
58
  return null;
52
59
  }
53
- switch (name) {
54
- case 'interruption':
55
- subscription = eventEmitter.addListener('onInterruption', callback);
56
- break;
57
60
 
58
- case 'routeChange':
59
- subscription = eventEmitter.addListener('onRouteChange', callback);
60
- break;
61
-
62
- case 'volumeChange':
63
- subscription = eventEmitter.addListener('onVolumeChange', callback);
64
- break;
65
-
66
- default:
67
- console.error('Unsupported RemoteControl action:', name);
68
- }
69
- return subscription;
61
+ return this.audioEventEmitter.addAudioEventListener(name, callback);
70
62
  }
71
63
 
72
64
  async requestRecordingPermissions(): Promise<PermissionStatus> {
73
- return AudioManagerModule.requestRecordingPermissions();
65
+ return NativeAudioAPIModule!.requestRecordingPermissions();
74
66
  }
75
67
 
76
68
  async checkRecordingPermissions(): Promise<PermissionStatus> {
77
- return AudioManagerModule.checkRecordingPermissions();
69
+ return NativeAudioAPIModule!.checkRecordingPermissions();
78
70
  }
79
71
  }
80
72
 
@@ -51,46 +51,4 @@ export interface LockScreenInfo extends BaseLockScreenInfo {
51
51
  elapsedTime?: number;
52
52
  }
53
53
 
54
- interface RemoteEmptyType {}
55
-
56
- interface RemoteControlEventType {
57
- value: number;
58
- }
59
-
60
- interface OnInterruptionEventType {
61
- type: 'ended' | 'began';
62
- shouldResume: boolean;
63
- }
64
-
65
- interface OnRouteChangeEventType {
66
- reason: string;
67
- }
68
-
69
- interface RemoteCommands {
70
- play: RemoteEmptyType;
71
- pause: RemoteEmptyType;
72
- stop: RemoteEmptyType;
73
- togglePlayPause: RemoteEmptyType;
74
- changePlaybackRate: RemoteEmptyType;
75
- nextTrack: RemoteEmptyType;
76
- previousTrack: RemoteEmptyType;
77
- skipForward: RemoteEmptyType;
78
- skipBackward: RemoteEmptyType;
79
- seekForward: RemoteEmptyType;
80
- seekBackward: RemoteEmptyType;
81
- changePlaybackPosition: RemoteEmptyType;
82
- }
83
-
84
- interface RemoteEvents {
85
- volumeChange: RemoteControlEventType;
86
- interruption: OnInterruptionEventType;
87
- routeChange: OnRouteChangeEventType;
88
- }
89
-
90
- export type RemoteCommandName = keyof RemoteCommands;
91
- export type RemoteEventName = keyof RemoteEvents;
92
- export type RemoteEventCallback<Name extends RemoteEventName> = (
93
- event: RemoteEvents[Name]
94
- ) => void;
95
-
96
54
  export type PermissionStatus = 'Undetermined' | 'Denied' | 'Granted';
package/src/types.ts CHANGED
@@ -45,11 +45,3 @@ export type WindowType = 'blackman' | 'hann';
45
45
  export interface AudioBufferSourceNodeOptions {
46
46
  pitchCorrection: boolean;
47
47
  }
48
-
49
- export type AudioRecorderStatus =
50
- | 'idle'
51
- | 'initializing'
52
- | 'ready'
53
- | 'running'
54
- | 'stopping'
55
- | 'error';