@symbiote-native/audio 0.1.2 → 0.1.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/README.md +96 -52
- package/build/angular/index.d.ts +8 -0
- package/build/angular/index.js +8 -3
- package/build/angular/inject-audio-player-status.d.ts +4 -0
- package/build/angular/inject-audio-player-status.js +4 -0
- package/build/angular/inject-audio-player.d.ts +4 -0
- package/build/angular/inject-audio-player.js +8 -0
- package/build/angular/inject-audio-playlist-status.d.ts +3 -0
- package/build/angular/inject-audio-playlist-status.js +4 -0
- package/build/angular/inject-audio-playlist.d.ts +5 -0
- package/build/angular/inject-audio-playlist.js +7 -0
- package/build/angular/inject-audio-recorder-state.d.ts +5 -0
- package/build/angular/inject-audio-recorder-state.js +10 -0
- package/build/angular/inject-audio-recorder.d.ts +5 -0
- package/build/angular/inject-audio-recorder.js +13 -0
- package/build/angular/inject-audio-sample-listener.d.ts +4 -0
- package/build/angular/inject-audio-sample-listener.js +7 -0
- package/build/angular/inject-audio-stream.d.ts +4 -0
- package/build/angular/inject-audio-stream.js +17 -0
- package/build/core/audio-module.js +1 -1
- package/build/core/audio-player-controller.d.ts +7 -0
- package/build/core/audio-player-controller.js +10 -0
- package/build/core/audio-player.js +16 -4
- package/build/core/audio-playlist-controller.d.ts +4 -0
- package/build/core/audio-playlist-controller.js +5 -0
- package/build/core/audio-recorder-controller.d.ts +4 -0
- package/build/core/audio-recorder-controller.js +5 -0
- package/build/core/audio-recorder-polling.d.ts +5 -0
- package/build/core/audio-recorder-polling.js +10 -0
- package/build/core/audio-recorder-state.d.ts +2 -0
- package/build/core/audio-recorder-state.js +18 -0
- package/build/core/audio-recorder-status.d.ts +8 -0
- package/build/core/audio-recorder-status.js +6 -0
- package/build/core/audio-recorder.d.ts +2 -0
- package/build/core/audio-recorder.js +4 -0
- package/build/core/audio-sample-listener.d.ts +11 -0
- package/build/core/audio-sample-listener.js +9 -0
- package/build/core/audio-stream-controller.d.ts +4 -0
- package/build/core/audio-stream-controller.js +5 -0
- package/build/core/audio-stream-hooks.d.ts +8 -0
- package/build/core/audio-stream-hooks.js +13 -0
- package/build/core/audio-stream-lifecycle.d.ts +3 -0
- package/build/core/audio-stream-lifecycle.js +9 -0
- package/build/core/audio-stream-subscription.d.ts +10 -0
- package/build/core/audio-stream-subscription.js +12 -0
- package/build/core/audio-stream.d.ts +9 -10
- package/build/core/audio-stream.js +1 -9
- package/build/core/index.d.ts +14 -2
- package/build/core/index.js +9 -1
- package/build/core/json-keyed-resource-controller.d.ts +2 -0
- package/build/core/json-keyed-resource-controller.js +5 -0
- package/build/core/resolve-source.d.ts +2 -7
- package/build/core/resolve-source.js +69 -15
- package/build/core/subscribe-single-event.d.ts +5 -0
- package/build/core/subscribe-single-event.js +8 -0
- package/build/core/types.d.ts +11 -5
- package/build/react/index.d.ts +9 -0
- package/build/react/index.js +9 -0
- package/build/react/use-audio-player-status.d.ts +4 -0
- package/build/react/use-audio-player-status.js +4 -0
- package/build/react/use-audio-player.d.ts +3 -0
- package/build/react/use-audio-player.js +7 -0
- package/build/react/use-audio-playlist-status.d.ts +3 -0
- package/build/react/use-audio-playlist-status.js +4 -0
- package/build/react/use-audio-playlist.d.ts +4 -0
- package/build/react/use-audio-playlist.js +7 -0
- package/build/react/use-audio-recorder-state.d.ts +4 -0
- package/build/react/use-audio-recorder-state.js +9 -0
- package/build/react/use-audio-recorder.d.ts +4 -0
- package/build/react/use-audio-recorder.js +11 -0
- package/build/react/use-audio-sample-listener.d.ts +4 -0
- package/build/react/use-audio-sample-listener.js +6 -0
- package/build/react/use-audio-stream.d.ts +3 -0
- package/build/react/use-audio-stream.js +14 -0
- package/build/solid/index.d.ts +9 -0
- package/build/solid/index.js +9 -0
- package/build/solid/use-audio-player-status.d.ts +4 -0
- package/build/solid/use-audio-player-status.js +4 -0
- package/build/solid/use-audio-player.d.ts +5 -0
- package/build/solid/use-audio-player.js +7 -0
- package/build/solid/use-audio-playlist-status.d.ts +3 -0
- package/build/solid/use-audio-playlist-status.js +4 -0
- package/build/solid/use-audio-playlist.d.ts +5 -0
- package/build/solid/use-audio-playlist.js +7 -0
- package/build/solid/use-audio-recorder-state.d.ts +5 -0
- package/build/solid/use-audio-recorder-state.js +9 -0
- package/build/solid/use-audio-recorder.d.ts +5 -0
- package/build/solid/use-audio-recorder.js +13 -0
- package/build/solid/use-audio-sample-listener.d.ts +4 -0
- package/build/solid/use-audio-sample-listener.js +8 -0
- package/build/solid/use-audio-stream.d.ts +4 -0
- package/build/solid/use-audio-stream.js +16 -0
- package/build/svelte/index.d.ts +9 -0
- package/build/svelte/index.js +9 -0
- package/build/svelte/use-audio-player-status.svelte.d.ts +6 -0
- package/build/svelte/use-audio-player-status.svelte.js +4 -0
- package/build/svelte/use-audio-player.svelte.d.ts +6 -0
- package/build/svelte/use-audio-player.svelte.js +8 -0
- package/build/svelte/use-audio-playlist-status.svelte.d.ts +5 -0
- package/build/svelte/use-audio-playlist-status.svelte.js +4 -0
- package/build/svelte/use-audio-playlist.svelte.d.ts +6 -0
- package/build/svelte/use-audio-playlist.svelte.js +8 -0
- package/build/svelte/use-audio-recorder-state.svelte.d.ts +7 -0
- package/build/svelte/use-audio-recorder-state.svelte.js +14 -0
- package/build/svelte/use-audio-recorder.svelte.d.ts +6 -0
- package/build/svelte/use-audio-recorder.svelte.js +11 -0
- package/build/svelte/use-audio-sample-listener.svelte.d.ts +4 -0
- package/build/svelte/use-audio-sample-listener.svelte.js +5 -0
- package/build/svelte/use-audio-stream.svelte.d.ts +4 -0
- package/build/svelte/use-audio-stream.svelte.js +29 -0
- package/build/vue/index.d.ts +9 -0
- package/build/vue/index.js +9 -0
- package/build/vue/use-audio-player-status.d.ts +4 -0
- package/build/vue/use-audio-player-status.js +4 -0
- package/build/vue/use-audio-player.d.ts +5 -0
- package/build/vue/use-audio-player.js +8 -0
- package/build/vue/use-audio-playlist-status.d.ts +3 -0
- package/build/vue/use-audio-playlist-status.js +4 -0
- package/build/vue/use-audio-playlist.d.ts +5 -0
- package/build/vue/use-audio-playlist.js +8 -0
- package/build/vue/use-audio-recorder-state.d.ts +5 -0
- package/build/vue/use-audio-recorder-state.js +12 -0
- package/build/vue/use-audio-recorder.d.ts +5 -0
- package/build/vue/use-audio-recorder.js +11 -0
- package/build/vue/use-audio-sample-listener.d.ts +4 -0
- package/build/vue/use-audio-sample-listener.js +11 -0
- package/build/vue/use-audio-stream.d.ts +4 -0
- package/build/vue/use-audio-stream.js +18 -0
- package/build-ngc/angular/index.d.ts +8 -0
- package/build-ngc/angular/index.js +8 -3
- package/build-ngc/angular/index.js.map +1 -1
- package/build-ngc/angular/inject-audio-player-status.d.ts +4 -0
- package/build-ngc/angular/inject-audio-player-status.js +5 -0
- package/build-ngc/angular/inject-audio-player-status.js.map +1 -0
- package/build-ngc/angular/inject-audio-player.d.ts +4 -0
- package/build-ngc/angular/inject-audio-player.js +9 -0
- package/build-ngc/angular/inject-audio-player.js.map +1 -0
- package/build-ngc/angular/inject-audio-playlist-status.d.ts +3 -0
- package/build-ngc/angular/inject-audio-playlist-status.js +5 -0
- package/build-ngc/angular/inject-audio-playlist-status.js.map +1 -0
- package/build-ngc/angular/inject-audio-playlist.d.ts +5 -0
- package/build-ngc/angular/inject-audio-playlist.js +8 -0
- package/build-ngc/angular/inject-audio-playlist.js.map +1 -0
- package/build-ngc/angular/inject-audio-recorder-state.d.ts +5 -0
- package/build-ngc/angular/inject-audio-recorder-state.js +12 -0
- package/build-ngc/angular/inject-audio-recorder-state.js.map +1 -0
- package/build-ngc/angular/inject-audio-recorder.d.ts +5 -0
- package/build-ngc/angular/inject-audio-recorder.js +14 -0
- package/build-ngc/angular/inject-audio-recorder.js.map +1 -0
- package/build-ngc/angular/inject-audio-sample-listener.d.ts +4 -0
- package/build-ngc/angular/inject-audio-sample-listener.js +8 -0
- package/build-ngc/angular/inject-audio-sample-listener.js.map +1 -0
- package/build-ngc/angular/inject-audio-stream.d.ts +4 -0
- package/build-ngc/angular/inject-audio-stream.js +18 -0
- package/build-ngc/angular/inject-audio-stream.js.map +1 -0
- package/build-ngc/core/audio-module.js +1 -1
- package/build-ngc/core/audio-module.js.map +1 -1
- package/build-ngc/core/audio-player-controller.d.ts +7 -0
- package/build-ngc/core/audio-player-controller.js +11 -0
- package/build-ngc/core/audio-player-controller.js.map +1 -0
- package/build-ngc/core/audio-player.js +16 -4
- package/build-ngc/core/audio-player.js.map +1 -1
- package/build-ngc/core/audio-playlist-controller.d.ts +4 -0
- package/build-ngc/core/audio-playlist-controller.js +6 -0
- package/build-ngc/core/audio-playlist-controller.js.map +1 -0
- package/build-ngc/core/audio-recorder-controller.d.ts +4 -0
- package/build-ngc/core/audio-recorder-controller.js +6 -0
- package/build-ngc/core/audio-recorder-controller.js.map +1 -0
- package/build-ngc/core/audio-recorder-polling.d.ts +5 -0
- package/build-ngc/core/audio-recorder-polling.js +11 -0
- package/build-ngc/core/audio-recorder-polling.js.map +1 -0
- package/build-ngc/core/audio-recorder-state.d.ts +2 -0
- package/build-ngc/core/audio-recorder-state.js +19 -0
- package/build-ngc/core/audio-recorder-state.js.map +1 -0
- package/build-ngc/core/audio-recorder-status.d.ts +8 -0
- package/build-ngc/core/audio-recorder-status.js +7 -0
- package/build-ngc/core/audio-recorder-status.js.map +1 -0
- package/build-ngc/core/audio-recorder.d.ts +2 -0
- package/build-ngc/core/audio-recorder.js +4 -0
- package/build-ngc/core/audio-recorder.js.map +1 -1
- package/build-ngc/core/audio-sample-listener.d.ts +11 -0
- package/build-ngc/core/audio-sample-listener.js +10 -0
- package/build-ngc/core/audio-sample-listener.js.map +1 -0
- package/build-ngc/core/audio-stream-controller.d.ts +4 -0
- package/build-ngc/core/audio-stream-controller.js +6 -0
- package/build-ngc/core/audio-stream-controller.js.map +1 -0
- package/build-ngc/core/audio-stream-hooks.d.ts +8 -0
- package/build-ngc/core/audio-stream-hooks.js +14 -0
- package/build-ngc/core/audio-stream-hooks.js.map +1 -0
- package/build-ngc/core/audio-stream-lifecycle.d.ts +3 -0
- package/build-ngc/core/audio-stream-lifecycle.js +10 -0
- package/build-ngc/core/audio-stream-lifecycle.js.map +1 -0
- package/build-ngc/core/audio-stream-subscription.d.ts +10 -0
- package/build-ngc/core/audio-stream-subscription.js +13 -0
- package/build-ngc/core/audio-stream-subscription.js.map +1 -0
- package/build-ngc/core/audio-stream.d.ts +9 -10
- package/build-ngc/core/audio-stream.js +1 -9
- package/build-ngc/core/audio-stream.js.map +1 -1
- package/build-ngc/core/index.d.ts +14 -2
- package/build-ngc/core/index.js +9 -1
- package/build-ngc/core/index.js.map +1 -1
- package/build-ngc/core/json-keyed-resource-controller.d.ts +2 -0
- package/build-ngc/core/json-keyed-resource-controller.js +6 -0
- package/build-ngc/core/json-keyed-resource-controller.js.map +1 -0
- package/build-ngc/core/resolve-source.d.ts +2 -7
- package/build-ngc/core/resolve-source.js +69 -15
- package/build-ngc/core/resolve-source.js.map +1 -1
- package/build-ngc/core/subscribe-single-event.d.ts +5 -0
- package/build-ngc/core/subscribe-single-event.js +9 -0
- package/build-ngc/core/subscribe-single-event.js.map +1 -0
- package/build-ngc/core/types.d.ts +11 -5
- package/build-ngc/core/types.js.map +1 -1
- package/package.json +24 -23
- package/src/angular/index.ts +8 -3
- package/src/angular/inject-audio-player-status.ts +11 -0
- package/src/angular/inject-audio-player.ts +17 -0
- package/src/angular/inject-audio-playlist-status.ts +11 -0
- package/src/angular/inject-audio-playlist.ts +16 -0
- package/src/angular/inject-audio-recorder-state.ts +21 -0
- package/src/angular/inject-audio-recorder.ts +24 -0
- package/src/angular/inject-audio-sample-listener.ts +13 -0
- package/src/angular/inject-audio-stream.ts +41 -0
- package/src/core/audio-module.ts +2 -1
- package/src/core/audio-player-controller.ts +25 -0
- package/src/core/audio-player.ts +17 -4
- package/src/core/audio-playlist-controller.ts +14 -0
- package/src/core/audio-recorder-controller.ts +14 -0
- package/src/core/audio-recorder-polling.ts +20 -0
- package/src/core/audio-recorder-state.ts +26 -0
- package/src/core/audio-recorder-status.ts +22 -0
- package/src/core/audio-recorder.ts +5 -0
- package/src/core/audio-sample-listener.ts +23 -0
- package/src/core/audio-stream-controller.ts +14 -0
- package/src/core/audio-stream-hooks.ts +31 -0
- package/src/core/audio-stream-lifecycle.ts +19 -0
- package/src/core/audio-stream-subscription.ts +28 -0
- package/src/core/audio-stream.ts +11 -10
- package/src/core/index.ts +20 -1
- package/src/core/json-keyed-resource-controller.ts +16 -0
- package/src/core/resolve-source.ts +80 -18
- package/src/core/subscribe-single-event.ts +17 -0
- package/src/core/types.ts +13 -14
- package/src/react/index.ts +9 -0
- package/src/react/use-audio-player-status.ts +11 -0
- package/src/react/use-audio-player.ts +14 -0
- package/src/react/use-audio-playlist-status.ts +11 -0
- package/src/react/use-audio-playlist.ts +13 -0
- package/src/react/use-audio-recorder-state.ts +23 -0
- package/src/react/use-audio-recorder.ts +23 -0
- package/src/react/use-audio-sample-listener.ts +15 -0
- package/src/react/use-audio-stream.ts +39 -0
- package/src/solid/index.ts +9 -0
- package/src/solid/use-audio-player-status.ts +11 -0
- package/src/solid/use-audio-player.ts +15 -0
- package/src/solid/use-audio-playlist-status.ts +11 -0
- package/src/solid/use-audio-playlist.ts +14 -0
- package/src/solid/use-audio-recorder-state.ts +18 -0
- package/src/solid/use-audio-recorder.ts +22 -0
- package/src/solid/use-audio-sample-listener.ts +14 -0
- package/src/solid/use-audio-stream.ts +34 -0
- package/src/svelte/index.ts +9 -0
- package/src/svelte/svelte-ambient.d.ts +3 -0
- package/src/svelte/svelte-compile.test-helper.ts +7 -0
- package/src/svelte/use-audio-player-status.svelte.ts +11 -0
- package/src/svelte/use-audio-player.svelte.ts +20 -0
- package/src/svelte/use-audio-playlist-status.svelte.ts +11 -0
- package/src/svelte/use-audio-playlist.svelte.ts +19 -0
- package/src/svelte/use-audio-recorder-state.svelte.ts +29 -0
- package/src/svelte/use-audio-recorder.svelte.ts +25 -0
- package/src/svelte/use-audio-sample-listener.svelte.ts +11 -0
- package/src/svelte/use-audio-stream.svelte.ts +44 -0
- package/src/vue/index.ts +9 -0
- package/src/vue/use-audio-player-status.ts +11 -0
- package/src/vue/use-audio-player.ts +19 -0
- package/src/vue/use-audio-playlist-status.ts +11 -0
- package/src/vue/use-audio-playlist.ts +15 -0
- package/src/vue/use-audio-recorder-state.ts +21 -0
- package/src/vue/use-audio-recorder.ts +30 -0
- package/src/vue/use-audio-sample-listener.ts +22 -0
- package/src/vue/use-audio-stream.ts +40 -0
package/src/core/audio-stream.ts
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { expoAudio } from './native-module';
|
|
2
|
-
import type { IAudioStreamOptions } from './types';
|
|
2
|
+
import type { IAudioStreamBuffer, IAudioStreamOptions } from './types';
|
|
3
3
|
|
|
4
4
|
// Plain re-export — upstream has no prototype shim for `AudioStream` either.
|
|
5
5
|
export const AudioStream = expoAudio.AudioStream;
|
|
6
6
|
export type AudioStream = InstanceType<typeof AudioStream>;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
export type IUseAudioStreamOptions = IAudioStreamOptions & {
|
|
9
|
+
onBuffer?: (buffer: IAudioStreamBuffer) => void;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type IAudioStreamResult = {
|
|
13
|
+
stream: AudioStream;
|
|
14
|
+
isStreaming: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/** Requires microphone permission - see `requestRecordingPermissionsAsync`. */
|
|
17
18
|
export function createAudioStream(
|
|
18
19
|
options: IAudioStreamOptions = {},
|
|
19
20
|
): AudioStream {
|
package/src/core/index.ts
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
export { AudioPlayer, createAudioPlayer } from './audio-player';
|
|
2
|
-
export { AudioRecorder } from './audio-recorder';
|
|
2
|
+
export { AudioRecorder, createAudioRecorder } from './audio-recorder';
|
|
3
3
|
export { AudioPlaylist, createAudioPlaylist } from './audio-playlist';
|
|
4
4
|
export { AudioStream, createAudioStream } from './audio-stream';
|
|
5
|
+
export type {
|
|
6
|
+
IUseAudioStreamOptions,
|
|
7
|
+
IAudioStreamResult,
|
|
8
|
+
} from './audio-stream';
|
|
9
|
+
export { createAudioStreamController } from './audio-stream-controller';
|
|
10
|
+
export {
|
|
11
|
+
subscribeAudioStreamBuffer,
|
|
12
|
+
toAudioStreamKey,
|
|
13
|
+
} from './audio-stream-subscription';
|
|
14
|
+
export type { IAudioStreamBufferSource } from './audio-stream-subscription';
|
|
15
|
+
export { runAudioStreamBufferEffect } from './audio-stream-lifecycle';
|
|
16
|
+
export { createAudioStreamHooks } from './audio-stream-hooks';
|
|
5
17
|
export {
|
|
6
18
|
setIsAudioActiveAsync,
|
|
7
19
|
setAudioModeAsync,
|
|
@@ -14,6 +26,12 @@ export {
|
|
|
14
26
|
getPreloadedSources,
|
|
15
27
|
} from './audio-module';
|
|
16
28
|
export { resolveSource, resolveSources } from './resolve-source';
|
|
29
|
+
export { subscribeAudioSampleListener } from './audio-sample-listener';
|
|
30
|
+
export type { IAudioSamplePlayer } from './audio-sample-listener';
|
|
31
|
+
export { subscribeRecordingStatus } from './audio-recorder-status';
|
|
32
|
+
export type { IStatusRecorder } from './audio-recorder-status';
|
|
33
|
+
export { shouldUpdateRecorderState } from './audio-recorder-state';
|
|
34
|
+
export { pollRecorderState } from './audio-recorder-polling';
|
|
17
35
|
export {
|
|
18
36
|
RecordingPresets,
|
|
19
37
|
IOSOutputFormat,
|
|
@@ -32,6 +50,7 @@ export type {
|
|
|
32
50
|
IAudioSource,
|
|
33
51
|
IAudioSourceInfo,
|
|
34
52
|
IAudioPlayerOptions,
|
|
53
|
+
IAudioLoadOptions,
|
|
35
54
|
IPreloadOptions,
|
|
36
55
|
IRecordingInput,
|
|
37
56
|
IPitchCorrectionQuality,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createResourceController,
|
|
3
|
+
type IResourceController,
|
|
4
|
+
} from '@symbiote-native/engine';
|
|
5
|
+
|
|
6
|
+
// Shared shape behind the player/playlist/recorder controllers, keyed by JSON.stringify
|
|
7
|
+
export function createJsonKeyedResourceController<TKey, TResource>(
|
|
8
|
+
create: (key: TKey) => TResource,
|
|
9
|
+
dispose: (resource: TResource) => void,
|
|
10
|
+
): IResourceController<TKey, TResource> {
|
|
11
|
+
return createResourceController<TKey, TResource>(
|
|
12
|
+
create,
|
|
13
|
+
dispose,
|
|
14
|
+
(a, b) => JSON.stringify(a) === JSON.stringify(b),
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -1,34 +1,74 @@
|
|
|
1
|
-
|
|
1
|
+
// Ported from expo-audio/src/utils/resolveSource.ts (sdk-57), against @symbiote-native/asset's
|
|
2
|
+
// Asset class instead of importing expo-asset directly (same pattern as packages/font).
|
|
3
|
+
import { Asset } from '@symbiote-native/asset';
|
|
4
|
+
|
|
2
5
|
import type { IAudioSource } from './types';
|
|
3
6
|
|
|
4
|
-
type IResolvedAudioSourceObject = Exclude<
|
|
7
|
+
type IResolvedAudioSourceObject = Exclude<
|
|
8
|
+
IAudioSource,
|
|
9
|
+
string | number | Asset | null
|
|
10
|
+
>;
|
|
11
|
+
|
|
12
|
+
function getAssetFromSource(source?: IAudioSource): Asset | null {
|
|
13
|
+
if (!source) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
if (source instanceof Asset) {
|
|
17
|
+
return source;
|
|
18
|
+
}
|
|
19
|
+
if (typeof source === 'number') {
|
|
20
|
+
return Asset.fromModule(source);
|
|
21
|
+
}
|
|
22
|
+
if (typeof source === 'object') {
|
|
23
|
+
if ('assetId' in source && typeof source.assetId === 'number') {
|
|
24
|
+
return Asset.fromModule(source.assetId);
|
|
25
|
+
}
|
|
26
|
+
if ('uri' in source && typeof source.uri === 'string') {
|
|
27
|
+
return Asset.fromURI(source.uri);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (typeof source === 'string') {
|
|
31
|
+
return Asset.fromURI(source);
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
5
35
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
36
|
+
function createSourceFromAsset(
|
|
37
|
+
asset: Asset,
|
|
38
|
+
extras: { assetId?: number; headers?: Record<string, string> } = {},
|
|
39
|
+
): IResolvedAudioSourceObject {
|
|
40
|
+
const result: IResolvedAudioSourceObject = {
|
|
41
|
+
uri: asset.localUri ?? asset.uri,
|
|
42
|
+
};
|
|
43
|
+
if (asset.name) {
|
|
44
|
+
result.name = asset.name;
|
|
45
|
+
}
|
|
46
|
+
if (extras.assetId != null) {
|
|
47
|
+
result.assetId = extras.assetId;
|
|
48
|
+
}
|
|
49
|
+
if (extras.headers) {
|
|
50
|
+
result.headers = extras.headers;
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
12
53
|
}
|
|
13
54
|
|
|
14
|
-
/**
|
|
15
|
-
* Normalizes a source into the shape the native player accepts. A `number` (a `require()`'d
|
|
16
|
-
* local asset) resolves via `@symbiote-native/engine`'s `resolveAssetSource` seam — RN's own
|
|
17
|
-
* generic asset-registry lookup, wired by `bootstrapHost`. An actual `expo-asset` `Asset`
|
|
18
|
-
* instance is still not ported, see `types.ts`'s header comment on `IAudioSource`. A plain
|
|
19
|
-
* string is treated as a URI, matching upstream.
|
|
20
|
-
*/
|
|
21
55
|
export function resolveSource(source?: IAudioSource): IAudioSource | null {
|
|
22
56
|
if (source == null) {
|
|
23
57
|
return null;
|
|
24
58
|
}
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
return isAudioSourceObject(resolved) ? resolved : null;
|
|
59
|
+
if (source instanceof Asset) {
|
|
60
|
+
return createSourceFromAsset(source);
|
|
28
61
|
}
|
|
29
62
|
if (typeof source === 'string') {
|
|
30
63
|
return { uri: source };
|
|
31
64
|
}
|
|
65
|
+
if (typeof source === 'number') {
|
|
66
|
+
return createSourceFromAsset(Asset.fromModule(source), { assetId: source });
|
|
67
|
+
}
|
|
68
|
+
if ('assetId' in source && typeof source.assetId === 'number') {
|
|
69
|
+
const asset = Asset.fromModule(source.assetId);
|
|
70
|
+
return { ...source, uri: asset.localUri ?? asset.uri };
|
|
71
|
+
}
|
|
32
72
|
return source;
|
|
33
73
|
}
|
|
34
74
|
|
|
@@ -39,3 +79,25 @@ export function resolveSources(
|
|
|
39
79
|
.map(source => resolveSource(source))
|
|
40
80
|
.filter((source): source is NonNullable<IAudioSource> => source != null);
|
|
41
81
|
}
|
|
82
|
+
|
|
83
|
+
/** Resolves `source` and, unlike `resolveSource`, downloads it to a local cache file first. */
|
|
84
|
+
export async function resolveSourceWithDownload(
|
|
85
|
+
source?: IAudioSource,
|
|
86
|
+
): Promise<IAudioSource | null> {
|
|
87
|
+
const asset = getAssetFromSource(source);
|
|
88
|
+
const fallback = resolveSource(source);
|
|
89
|
+
if (!asset) {
|
|
90
|
+
return fallback;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
await asset.downloadAsync();
|
|
94
|
+
if (asset.localUri) {
|
|
95
|
+
return fallback && typeof fallback === 'object'
|
|
96
|
+
? { ...fallback, uri: asset.localUri }
|
|
97
|
+
: { uri: asset.localUri };
|
|
98
|
+
}
|
|
99
|
+
} catch {
|
|
100
|
+
// Falls through to the un-downloaded source below, matching upstream's own recovery path.
|
|
101
|
+
}
|
|
102
|
+
return fallback;
|
|
103
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Shared shape behind `subscribeRecordingStatus`/`subscribeAudioStreamBuffer`: one optional
|
|
2
|
+
// listener over one named event, unsubscribed via the returned cleanup
|
|
3
|
+
export function subscribeSingleEvent<TEvent extends string, TPayload>(
|
|
4
|
+
source: {
|
|
5
|
+
addListener: (
|
|
6
|
+
event: TEvent,
|
|
7
|
+
listener: (payload: TPayload) => void,
|
|
8
|
+
) => { remove: () => void };
|
|
9
|
+
},
|
|
10
|
+
event: TEvent,
|
|
11
|
+
listener: ((payload: TPayload) => void) | undefined,
|
|
12
|
+
): () => void {
|
|
13
|
+
const subscription = source.addListener(event, payload => {
|
|
14
|
+
listener?.(payload);
|
|
15
|
+
});
|
|
16
|
+
return () => subscription.remove();
|
|
17
|
+
}
|
package/src/core/types.ts
CHANGED
|
@@ -2,16 +2,8 @@
|
|
|
2
2
|
// RecordingConstants.ts / AudioStream.types.ts / AudioEventKeys.ts, renamed with this repo's
|
|
3
3
|
// `I`-prefix convention for object/union-shaped exported types (enums keep their upstream name,
|
|
4
4
|
// matching packages/local-auth's AuthenticationType/SecurityLevel).
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// `@symbiote-native/engine`'s `resolveAssetSource` seam, which wraps RN's own generic
|
|
8
|
-
// `Image.resolveAssetSource` — an ordinary Metro asset-registry lookup, nothing image-specific
|
|
9
|
-
// despite the name, and `mp3` is already in Metro's default `assetExts`. Only an actual `Asset`
|
|
10
|
-
// CLASS instance (as opposed to the plain numeric id `require()` returns) is deliberately NOT
|
|
11
|
-
// ported, along with the `downloadFirst` player option — both need `expo-asset`'s own
|
|
12
|
-
// remote-caching layer, which pulls in `expo-constants` and peers on the `expo` meta-package this
|
|
13
|
-
// project never depends on (root CLAUDE.md's dependency-scope invariant, and the
|
|
14
|
-
// `symbiote-expo-native-module` skill §1). See the package README.
|
|
5
|
+
import type { Asset } from '@symbiote-native/asset';
|
|
6
|
+
|
|
15
7
|
import type { AudioQuality, IOSOutputFormat } from './recording-presets';
|
|
16
8
|
|
|
17
9
|
/** Audio source information returned from native when reading sources from a queue. */
|
|
@@ -20,16 +12,16 @@ export type IAudioSourceInfo = {
|
|
|
20
12
|
name?: string;
|
|
21
13
|
};
|
|
22
14
|
|
|
23
|
-
/**
|
|
24
|
-
* A URI string, an object describing a remote/local (by URI) audio source, or the numeric asset
|
|
25
|
-
* id `require('./song.mp3')` produces — resolved via `resolveSource`/`resolveSources`.
|
|
26
|
-
*/
|
|
15
|
+
/** A URI, a `require()` module id, an `Asset`, or a source object — see resolve-source.ts. */
|
|
27
16
|
export type IAudioSource =
|
|
28
17
|
| string
|
|
29
18
|
| number
|
|
19
|
+
| Asset
|
|
30
20
|
| null
|
|
31
21
|
| {
|
|
32
22
|
uri?: string;
|
|
23
|
+
/** id of a local asset from `require()`; ignored if `uri` is set. */
|
|
24
|
+
assetId?: number;
|
|
33
25
|
headers?: Record<string, string>;
|
|
34
26
|
name?: string;
|
|
35
27
|
};
|
|
@@ -52,8 +44,13 @@ export type IAudioPlayerOptions = {
|
|
|
52
44
|
* @default 0
|
|
53
45
|
*/
|
|
54
46
|
preferredForwardBufferDuration?: number;
|
|
47
|
+
/** Downloads the source via `Asset` before the native player loads it. @default false */
|
|
48
|
+
downloadFirst?: boolean;
|
|
55
49
|
};
|
|
56
50
|
|
|
51
|
+
/** @deprecated Use `IAudioPlayerOptions` instead */
|
|
52
|
+
export type IAudioLoadOptions = IAudioPlayerOptions;
|
|
53
|
+
|
|
57
54
|
export type IPreloadOptions = {
|
|
58
55
|
/** @default 10 */
|
|
59
56
|
preferredForwardBufferDuration?: number;
|
|
@@ -190,6 +187,8 @@ export type IAudioMode = {
|
|
|
190
187
|
playsInSilentMode: boolean;
|
|
191
188
|
/** @default 'mixWithOthers' */
|
|
192
189
|
interruptionMode: IInterruptionMode;
|
|
190
|
+
/** @platform android @deprecated Use `interruptionMode`, which now works on both platforms */
|
|
191
|
+
interruptionModeAndroid?: IInterruptionMode;
|
|
193
192
|
/** @default false @platform ios */
|
|
194
193
|
allowsRecording: boolean;
|
|
195
194
|
/** @default false */
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../core';
|
|
2
|
+
export { useAudioPlayer } from './use-audio-player';
|
|
3
|
+
export { useAudioPlayerStatus } from './use-audio-player-status';
|
|
4
|
+
export { useAudioSampleListener } from './use-audio-sample-listener';
|
|
5
|
+
export { useAudioPlaylist } from './use-audio-playlist';
|
|
6
|
+
export { useAudioPlaylistStatus } from './use-audio-playlist-status';
|
|
7
|
+
export { useAudioRecorder } from './use-audio-recorder';
|
|
8
|
+
export { useAudioRecorderState } from './use-audio-recorder-state';
|
|
9
|
+
export { useAudioStream } from './use-audio-stream';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createEventValueHook } from '@symbiote-native/react';
|
|
2
|
+
import { PLAYBACK_STATUS_UPDATE } from '../core/types';
|
|
3
|
+
import type { AudioPlayer } from '../core';
|
|
4
|
+
import type { IAudioStatus } from '../core';
|
|
5
|
+
|
|
6
|
+
/** React twin of `expo-audio`'s `useAudioPlayerStatus` */
|
|
7
|
+
export const useAudioPlayerStatus = createEventValueHook<
|
|
8
|
+
AudioPlayer,
|
|
9
|
+
IAudioStatus,
|
|
10
|
+
typeof PLAYBACK_STATUS_UPDATE
|
|
11
|
+
>(PLAYBACK_STATUS_UPDATE, player => player.currentStatus);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createResourceHook } from '@symbiote-native/react';
|
|
2
|
+
import { createAudioPlayerController } from '../core/audio-player-controller';
|
|
3
|
+
import type { AudioPlayer } from '../core';
|
|
4
|
+
import type { IAudioPlayerOptions, IAudioSource } from '../core';
|
|
5
|
+
|
|
6
|
+
const usePlayerResource = createResourceHook(createAudioPlayerController);
|
|
7
|
+
|
|
8
|
+
// React twin of `expo-audio`'s `useAudioPlayer`
|
|
9
|
+
export function useAudioPlayer(
|
|
10
|
+
source: IAudioSource = null,
|
|
11
|
+
options: IAudioPlayerOptions = {},
|
|
12
|
+
): AudioPlayer {
|
|
13
|
+
return usePlayerResource(source, options);
|
|
14
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createEventValueHook } from '@symbiote-native/react';
|
|
2
|
+
import { PLAYLIST_STATUS_UPDATE } from '../core/types';
|
|
3
|
+
import type { AudioPlaylist } from '../core';
|
|
4
|
+
import type { IAudioPlaylistStatus } from '../core';
|
|
5
|
+
|
|
6
|
+
/** React twin of `expo-audio`'s `useAudioPlaylistStatus` */
|
|
7
|
+
export const useAudioPlaylistStatus = createEventValueHook<
|
|
8
|
+
AudioPlaylist,
|
|
9
|
+
IAudioPlaylistStatus,
|
|
10
|
+
typeof PLAYLIST_STATUS_UPDATE
|
|
11
|
+
>(PLAYLIST_STATUS_UPDATE, playlist => playlist.currentStatus);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createResourceHook } from '@symbiote-native/react';
|
|
2
|
+
import { createAudioPlaylistController } from '../core/audio-playlist-controller';
|
|
3
|
+
import type { AudioPlaylist } from '../core';
|
|
4
|
+
import type { IAudioPlaylistOptions } from '../core';
|
|
5
|
+
|
|
6
|
+
const usePlaylistResource = createResourceHook(createAudioPlaylistController);
|
|
7
|
+
|
|
8
|
+
/** React twin of `expo-audio`'s `useAudioPlaylist` */
|
|
9
|
+
export function useAudioPlaylist(
|
|
10
|
+
options: IAudioPlaylistOptions = {},
|
|
11
|
+
): AudioPlaylist {
|
|
12
|
+
return usePlaylistResource(options);
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { pollRecorderState } from '../core/audio-recorder-polling';
|
|
3
|
+
import type { AudioRecorder } from '../core';
|
|
4
|
+
import type { IRecorderState } from '../core';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_MS = 500;
|
|
7
|
+
|
|
8
|
+
/** React twin of `expo-audio`'s `useAudioRecorderState` */
|
|
9
|
+
export function useAudioRecorderState(
|
|
10
|
+
recorder: AudioRecorder,
|
|
11
|
+
interval: number = DEFAULT_POLL_INTERVAL_MS,
|
|
12
|
+
): IRecorderState {
|
|
13
|
+
const [state, setState] = useState<IRecorderState>(() =>
|
|
14
|
+
recorder.getStatus(),
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
useEffect(
|
|
18
|
+
() => pollRecorderState(recorder, interval, setState),
|
|
19
|
+
[recorder, interval],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return state;
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { createResourceHook } from '@symbiote-native/react';
|
|
3
|
+
import { createAudioRecorderController } from '../core/audio-recorder-controller';
|
|
4
|
+
import { subscribeRecordingStatus } from '../core/audio-recorder-status';
|
|
5
|
+
import type { AudioRecorder } from '../core';
|
|
6
|
+
import type { IRecordingOptions, IRecordingStatus } from '../core';
|
|
7
|
+
|
|
8
|
+
const useRecorderResource = createResourceHook(createAudioRecorderController);
|
|
9
|
+
|
|
10
|
+
/** React twin of `expo-audio`'s `useAudioRecorder` */
|
|
11
|
+
export function useAudioRecorder(
|
|
12
|
+
options: IRecordingOptions,
|
|
13
|
+
statusListener?: (status: IRecordingStatus) => void,
|
|
14
|
+
): AudioRecorder {
|
|
15
|
+
const recorder = useRecorderResource(options);
|
|
16
|
+
|
|
17
|
+
useEffect(
|
|
18
|
+
() => subscribeRecordingStatus(recorder, statusListener),
|
|
19
|
+
[recorder, statusListener],
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return recorder;
|
|
23
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { subscribeAudioSampleListener } from '../core/audio-sample-listener';
|
|
3
|
+
import type { IAudioSamplePlayer } from '../core/audio-sample-listener';
|
|
4
|
+
import type { IAudioSample } from '../core/types';
|
|
5
|
+
|
|
6
|
+
/** React twin of `expo-audio`'s `useAudioSampleListener` */
|
|
7
|
+
export function useAudioSampleListener(
|
|
8
|
+
player: IAudioSamplePlayer,
|
|
9
|
+
listener: (data: IAudioSample) => void,
|
|
10
|
+
): void {
|
|
11
|
+
useEffect(
|
|
12
|
+
() => subscribeAudioSampleListener(player, listener),
|
|
13
|
+
[player, listener],
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
createResourceHook,
|
|
4
|
+
createEventValueHook,
|
|
5
|
+
} from '@symbiote-native/react';
|
|
6
|
+
import { createAudioStreamController } from '../core/audio-stream-controller';
|
|
7
|
+
import {
|
|
8
|
+
subscribeAudioStreamBuffer,
|
|
9
|
+
toAudioStreamKey,
|
|
10
|
+
} from '../core/audio-stream-subscription';
|
|
11
|
+
import { AUDIO_STREAM_STATUS } from '../core/types';
|
|
12
|
+
import type {
|
|
13
|
+
AudioStream,
|
|
14
|
+
IAudioStreamResult,
|
|
15
|
+
IAudioStreamStatus,
|
|
16
|
+
IUseAudioStreamOptions,
|
|
17
|
+
} from '../core';
|
|
18
|
+
|
|
19
|
+
const useStreamResource = createResourceHook(createAudioStreamController);
|
|
20
|
+
const useStreamStatus = createEventValueHook<
|
|
21
|
+
AudioStream,
|
|
22
|
+
IAudioStreamStatus,
|
|
23
|
+
typeof AUDIO_STREAM_STATUS
|
|
24
|
+
>(AUDIO_STREAM_STATUS, stream => ({ isStreaming: stream.isStreaming }));
|
|
25
|
+
|
|
26
|
+
/** React twin of `expo-audio`'s `useAudioStream` */
|
|
27
|
+
export function useAudioStream(
|
|
28
|
+
options: IUseAudioStreamOptions = {},
|
|
29
|
+
): IAudioStreamResult {
|
|
30
|
+
const stream = useStreamResource(toAudioStreamKey(options));
|
|
31
|
+
const status = useStreamStatus(stream);
|
|
32
|
+
|
|
33
|
+
useEffect(
|
|
34
|
+
() => subscribeAudioStreamBuffer(stream, options.onBuffer),
|
|
35
|
+
[stream, options.onBuffer],
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return { stream, isStreaming: status.isStreaming };
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../core';
|
|
2
|
+
export { useAudioPlayer } from './use-audio-player';
|
|
3
|
+
export { useAudioPlayerStatus } from './use-audio-player-status';
|
|
4
|
+
export { useAudioSampleListener } from './use-audio-sample-listener';
|
|
5
|
+
export { useAudioPlaylist } from './use-audio-playlist';
|
|
6
|
+
export { useAudioPlaylistStatus } from './use-audio-playlist-status';
|
|
7
|
+
export { useAudioRecorder } from './use-audio-recorder';
|
|
8
|
+
export { useAudioRecorderState } from './use-audio-recorder-state';
|
|
9
|
+
export { useAudioStream } from './use-audio-stream';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createEventValueHook } from '@symbiote-native/solid';
|
|
2
|
+
import { PLAYBACK_STATUS_UPDATE } from '../core/types';
|
|
3
|
+
import type { AudioPlayer } from '../core';
|
|
4
|
+
import type { IAudioStatus } from '../core';
|
|
5
|
+
|
|
6
|
+
/** Solid twin of `expo-audio`'s `useAudioPlayerStatus` */
|
|
7
|
+
export const useAudioPlayerStatus = createEventValueHook<
|
|
8
|
+
AudioPlayer,
|
|
9
|
+
IAudioStatus,
|
|
10
|
+
typeof PLAYBACK_STATUS_UPDATE
|
|
11
|
+
>(PLAYBACK_STATUS_UPDATE, player => player.currentStatus);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import { createResourceHook } from '@symbiote-native/solid';
|
|
3
|
+
import { createAudioPlayerController } from '../core/audio-player-controller';
|
|
4
|
+
import type { AudioPlayer } from '../core';
|
|
5
|
+
import type { IAudioPlayerOptions, IAudioSource } from '../core';
|
|
6
|
+
|
|
7
|
+
const usePlayerResource = createResourceHook(createAudioPlayerController);
|
|
8
|
+
|
|
9
|
+
/** Solid twin of `expo-audio`'s `useAudioPlayer` */
|
|
10
|
+
export function useAudioPlayer(
|
|
11
|
+
source: Accessor<IAudioSource>,
|
|
12
|
+
options: Accessor<IAudioPlayerOptions> = () => ({}),
|
|
13
|
+
): Accessor<AudioPlayer> {
|
|
14
|
+
return usePlayerResource(() => [source(), options()]);
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createEventValueHook } from '@symbiote-native/solid';
|
|
2
|
+
import { PLAYLIST_STATUS_UPDATE } from '../core/types';
|
|
3
|
+
import type { AudioPlaylist } from '../core';
|
|
4
|
+
import type { IAudioPlaylistStatus } from '../core';
|
|
5
|
+
|
|
6
|
+
/** Solid twin of `expo-audio`'s `useAudioPlaylistStatus` */
|
|
7
|
+
export const useAudioPlaylistStatus = createEventValueHook<
|
|
8
|
+
AudioPlaylist,
|
|
9
|
+
IAudioPlaylistStatus,
|
|
10
|
+
typeof PLAYLIST_STATUS_UPDATE
|
|
11
|
+
>(PLAYLIST_STATUS_UPDATE, playlist => playlist.currentStatus);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import { createResourceHook } from '@symbiote-native/solid';
|
|
3
|
+
import { createAudioPlaylistController } from '../core/audio-playlist-controller';
|
|
4
|
+
import type { AudioPlaylist } from '../core';
|
|
5
|
+
import type { IAudioPlaylistOptions } from '../core';
|
|
6
|
+
|
|
7
|
+
const usePlaylistResource = createResourceHook(createAudioPlaylistController);
|
|
8
|
+
|
|
9
|
+
/** Solid twin of `expo-audio`'s `useAudioPlaylist` */
|
|
10
|
+
export function useAudioPlaylist(
|
|
11
|
+
getOptions: Accessor<IAudioPlaylistOptions>,
|
|
12
|
+
): Accessor<AudioPlaylist> {
|
|
13
|
+
return usePlaylistResource(() => [getOptions()]);
|
|
14
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { createSignal, onCleanup, type Accessor } from 'solid-js';
|
|
2
|
+
import { pollRecorderState } from '../core/audio-recorder-polling';
|
|
3
|
+
import type { AudioRecorder } from '../core';
|
|
4
|
+
import type { IRecorderState } from '../core';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_POLL_INTERVAL_MS = 500;
|
|
7
|
+
|
|
8
|
+
/** Solid twin of `expo-audio`'s `useAudioRecorderState` */
|
|
9
|
+
export function useAudioRecorderState(
|
|
10
|
+
recorder: AudioRecorder,
|
|
11
|
+
interval: number = DEFAULT_POLL_INTERVAL_MS,
|
|
12
|
+
): Accessor<IRecorderState> {
|
|
13
|
+
const [state, setState] = createSignal(recorder.getStatus());
|
|
14
|
+
|
|
15
|
+
onCleanup(pollRecorderState(recorder, interval, setState));
|
|
16
|
+
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createEffect, onCleanup, type Accessor } from 'solid-js';
|
|
2
|
+
import { createResourceHook } from '@symbiote-native/solid';
|
|
3
|
+
import { createAudioRecorderController } from '../core/audio-recorder-controller';
|
|
4
|
+
import { subscribeRecordingStatus } from '../core/audio-recorder-status';
|
|
5
|
+
import type { AudioRecorder } from '../core';
|
|
6
|
+
import type { IRecordingOptions, IRecordingStatus } from '../core';
|
|
7
|
+
|
|
8
|
+
const useRecorderResource = createResourceHook(createAudioRecorderController);
|
|
9
|
+
|
|
10
|
+
/** Solid twin of `expo-audio`'s `useAudioRecorder` */
|
|
11
|
+
export function useAudioRecorder(
|
|
12
|
+
getOptions: Accessor<IRecordingOptions>,
|
|
13
|
+
statusListener?: (status: IRecordingStatus) => void,
|
|
14
|
+
): Accessor<AudioRecorder> {
|
|
15
|
+
const recorder = useRecorderResource(() => [getOptions()]);
|
|
16
|
+
|
|
17
|
+
createEffect(() => {
|
|
18
|
+
onCleanup(subscribeRecordingStatus(recorder(), statusListener));
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return recorder;
|
|
22
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createEffect, onCleanup } from 'solid-js';
|
|
2
|
+
import { subscribeAudioSampleListener } from '../core/audio-sample-listener';
|
|
3
|
+
import type { IAudioSamplePlayer } from '../core/audio-sample-listener';
|
|
4
|
+
import type { IAudioSample } from '../core/types';
|
|
5
|
+
|
|
6
|
+
/** Solid twin of `expo-audio`'s `useAudioSampleListener` */
|
|
7
|
+
export function useAudioSampleListener(
|
|
8
|
+
player: IAudioSamplePlayer,
|
|
9
|
+
listener: (data: IAudioSample) => void,
|
|
10
|
+
): void {
|
|
11
|
+
createEffect(() => {
|
|
12
|
+
onCleanup(subscribeAudioSampleListener(player, listener));
|
|
13
|
+
});
|
|
14
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { createMemo, onCleanup, type Accessor } from 'solid-js';
|
|
2
|
+
import {
|
|
3
|
+
createResourceHook,
|
|
4
|
+
createEventValueHook,
|
|
5
|
+
} from '@symbiote-native/solid';
|
|
6
|
+
import { createAudioStreamHooks } from '../core/audio-stream-hooks';
|
|
7
|
+
import { toAudioStreamKey } from '../core/audio-stream-subscription';
|
|
8
|
+
import { runAudioStreamBufferEffect } from '../core/audio-stream-lifecycle';
|
|
9
|
+
import type { IAudioStreamResult, IUseAudioStreamOptions } from '../core';
|
|
10
|
+
|
|
11
|
+
const { useStreamResource, useStreamStatus } = createAudioStreamHooks(
|
|
12
|
+
createResourceHook,
|
|
13
|
+
createEventValueHook,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
/** Solid twin of `expo-audio`'s `useAudioStream` */
|
|
17
|
+
export function useAudioStream(
|
|
18
|
+
getOptions: Accessor<IUseAudioStreamOptions>,
|
|
19
|
+
): Accessor<IAudioStreamResult> {
|
|
20
|
+
const stream = useStreamResource(() => [toAudioStreamKey(getOptions())]);
|
|
21
|
+
const status = useStreamStatus(stream);
|
|
22
|
+
|
|
23
|
+
runAudioStreamBufferEffect(
|
|
24
|
+
stream,
|
|
25
|
+
() => getOptions().onBuffer,
|
|
26
|
+
fn => fn(),
|
|
27
|
+
onCleanup,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
return createMemo(() => ({
|
|
31
|
+
stream: stream(),
|
|
32
|
+
isStreaming: status().isStreaming,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../core';
|
|
2
|
+
export { useAudioPlayer } from './use-audio-player.svelte';
|
|
3
|
+
export { useAudioPlayerStatus } from './use-audio-player-status.svelte';
|
|
4
|
+
export { useAudioSampleListener } from './use-audio-sample-listener.svelte';
|
|
5
|
+
export { useAudioPlaylist } from './use-audio-playlist.svelte';
|
|
6
|
+
export { useAudioPlaylistStatus } from './use-audio-playlist-status.svelte';
|
|
7
|
+
export { useAudioRecorder } from './use-audio-recorder.svelte';
|
|
8
|
+
export { useAudioRecorderState } from './use-audio-recorder-state.svelte';
|
|
9
|
+
export { useAudioStream } from './use-audio-stream.svelte';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Re-exports the existing harness instead of a third copy (packages/sqlite and
|
|
2
|
+
// packages/navigation already carry one, not part of either package's public exports)
|
|
3
|
+
export {
|
|
4
|
+
createSvelteHarness,
|
|
5
|
+
loadComponent,
|
|
6
|
+
type ISvelteHarness,
|
|
7
|
+
} from '../../../sqlite/src/svelte/svelte-compile.test-helper';
|