expo-audio 0.2.0 → 0.2.1
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/CHANGELOG.md +4 -0
- package/android/build.gradle +2 -2
- package/android/src/main/java/expo/modules/audio/AudioPlayer.kt +5 -2
- package/android/src/main/java/expo/modules/audio/AudioRecorder.kt +9 -15
- package/android/src/main/java/expo/modules/audio/AudioRecords.kt +4 -4
- package/app.plugin.js +1 -0
- package/build/AudioModule.types.d.ts +4 -4
- package/build/AudioModule.types.d.ts.map +1 -1
- package/build/AudioModule.types.js.map +1 -1
- package/build/AudioModule.web.d.ts.map +1 -1
- package/build/AudioModule.web.js +4 -3
- package/build/AudioModule.web.js.map +1 -1
- package/build/ExpoAudio.d.ts +3 -0
- package/build/ExpoAudio.d.ts.map +1 -1
- package/build/ExpoAudio.js +7 -5
- package/build/ExpoAudio.js.map +1 -1
- package/build/ExpoAudio.web.d.ts.map +1 -1
- package/build/ExpoAudio.web.js +4 -3
- package/build/ExpoAudio.web.js.map +1 -1
- package/build/utils/options.js +6 -6
- package/build/utils/options.js.map +1 -1
- package/ios/AudioModule.swift +18 -15
- package/ios/AudioPlayer.swift +18 -14
- package/ios/AudioRecorder.swift +57 -11
- package/ios/AudioRecords.swift +2 -2
- package/ios/AudioUtils.swift +2 -2
- package/package.json +2 -2
- package/plugin/build/withAudio.d.ts +5 -0
- package/plugin/build/withAudio.js +17 -0
- package/plugin/src/withAudio.ts +26 -0
- package/plugin/tsconfig.json +9 -0
- package/src/AudioModule.types.ts +4 -4
- package/src/AudioModule.web.ts +4 -3
- package/src/ExpoAudio.ts +8 -6
- package/src/ExpoAudio.web.ts +4 -3
- package/src/utils/options.ts +6 -6
package/CHANGELOG.md
CHANGED
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'expo.modules.audio'
|
|
4
|
-
version = '0.2.
|
|
4
|
+
version = '0.2.1'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -14,7 +14,7 @@ android {
|
|
|
14
14
|
namespace "expo.modules.audio"
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 1
|
|
17
|
-
versionName "0.2.
|
|
17
|
+
versionName "0.2.1"
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
compileOptions {
|
|
@@ -18,6 +18,9 @@ import kotlinx.coroutines.launch
|
|
|
18
18
|
import kotlinx.coroutines.withContext
|
|
19
19
|
import java.util.UUID
|
|
20
20
|
|
|
21
|
+
private const val PLAYBACK_STATUS_UPDATE = "playbackStatusUpdate"
|
|
22
|
+
private const val AUDIO_SAMPLE_UPDATE = "audioSampleUpdate"
|
|
23
|
+
|
|
21
24
|
@UnstableApi
|
|
22
25
|
class AudioPlayer(
|
|
23
26
|
context: Context,
|
|
@@ -135,7 +138,7 @@ class AudioPlayer(
|
|
|
135
138
|
withContext(Dispatchers.Main) {
|
|
136
139
|
val data = currentStatus()
|
|
137
140
|
val body = map?.let { data + it } ?: data
|
|
138
|
-
emit(
|
|
141
|
+
emit(PLAYBACK_STATUS_UPDATE, body)
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
private fun sendAudioSampleUpdate(sample: List<Float>) {
|
|
@@ -145,7 +148,7 @@ class AudioPlayer(
|
|
|
145
148
|
),
|
|
146
149
|
"timestamp" to player.currentPosition
|
|
147
150
|
)
|
|
148
|
-
emit(
|
|
151
|
+
emit(AUDIO_SAMPLE_UPDATE, body)
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
private fun playbackStateToString(state: Int): String {
|
|
@@ -18,6 +18,8 @@ import java.io.IOException
|
|
|
18
18
|
import java.util.UUID
|
|
19
19
|
import kotlin.math.ln
|
|
20
20
|
|
|
21
|
+
private const val RECORDING_STATUS_UPDATE = "recordingStatusUpdate"
|
|
22
|
+
|
|
21
23
|
class AudioRecorder(
|
|
22
24
|
private val context: Context,
|
|
23
25
|
appContext: AppContext,
|
|
@@ -63,12 +65,8 @@ class AudioRecorder(
|
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
fun record() {
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
recorder.resume()
|
|
69
|
-
} else {
|
|
70
|
-
recorder.start()
|
|
71
|
-
}
|
|
68
|
+
if (isPaused) {
|
|
69
|
+
recorder.resume()
|
|
72
70
|
} else {
|
|
73
71
|
recorder.start()
|
|
74
72
|
}
|
|
@@ -78,14 +76,10 @@ class AudioRecorder(
|
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
fun pauseRecording() {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
isPaused = true
|
|
86
|
-
} else {
|
|
87
|
-
stopRecording()
|
|
88
|
-
}
|
|
79
|
+
recorder.pause()
|
|
80
|
+
durationAlreadyRecorded = getAudioRecorderDurationMillis()
|
|
81
|
+
isRecording = false
|
|
82
|
+
isPaused = true
|
|
89
83
|
}
|
|
90
84
|
|
|
91
85
|
fun stopRecording(): Bundle {
|
|
@@ -183,7 +177,7 @@ class AudioRecorder(
|
|
|
183
177
|
else -> "An unknown recording error occurred"
|
|
184
178
|
}
|
|
185
179
|
emit(
|
|
186
|
-
|
|
180
|
+
RECORDING_STATUS_UPDATE,
|
|
187
181
|
mapOf(
|
|
188
182
|
"isFinished" to true,
|
|
189
183
|
"hasError" to true,
|
|
@@ -27,12 +27,12 @@ enum class InterruptionMode(val value: String) : Enumerable {
|
|
|
27
27
|
// Data class because we want `equals`
|
|
28
28
|
data class RecordingOptions(
|
|
29
29
|
@Field val extension: String,
|
|
30
|
+
@Field val sampleRate: Double?,
|
|
31
|
+
@Field val numberOfChannels: Double?,
|
|
32
|
+
@Field val bitRate: Double?,
|
|
30
33
|
@Field val outputFormat: AndroidOutputFormat?,
|
|
31
34
|
@Field val audioEncoder: AndroidAudioEncoder?,
|
|
32
|
-
@Field val
|
|
33
|
-
@Field val maxFileSize: Int?,
|
|
34
|
-
@Field val numberOfChannels: Double?,
|
|
35
|
-
@Field val sampleRate: Double?
|
|
35
|
+
@Field val maxFileSize: Int?
|
|
36
36
|
) : Record
|
|
37
37
|
|
|
38
38
|
enum class AndroidOutputFormat(val value: String) : Enumerable {
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./plugin/build/withAudio');
|
|
@@ -108,8 +108,8 @@ type AudioSample = {
|
|
|
108
108
|
timestamp: number;
|
|
109
109
|
};
|
|
110
110
|
export type AudioEvents = {
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
playbackStatusUpdate(status: AudioStatus): void;
|
|
112
|
+
audioSampleUpdate(data: AudioSample): void;
|
|
113
113
|
};
|
|
114
114
|
export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
115
115
|
/**
|
|
@@ -173,7 +173,7 @@ export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
|
173
173
|
/**
|
|
174
174
|
* Prepares the recording for recording.
|
|
175
175
|
*/
|
|
176
|
-
prepareToRecordAsync(options?: RecordingOptions): Promise<void>;
|
|
176
|
+
prepareToRecordAsync(options?: Partial<RecordingOptions>): Promise<void>;
|
|
177
177
|
/**
|
|
178
178
|
* Stops the recording once the specified time has elapsed.
|
|
179
179
|
* @param seconds The time in seconds to stop recording at.
|
|
@@ -181,7 +181,7 @@ export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
|
181
181
|
recordForDuration(seconds: number): void;
|
|
182
182
|
}
|
|
183
183
|
export type RecordingEvents = {
|
|
184
|
-
|
|
184
|
+
recordingStatusUpdate: (status: RecordingStatus) => void;
|
|
185
185
|
};
|
|
186
186
|
export {};
|
|
187
187
|
//# sourceMappingURL=AudioModule.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioModule.types.d.ts","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,WAAW;IAC1B,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,gCAAgC,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACzE,4BAA4B,IAAI,OAAO,CAAC,2BAA2B,CAAC,CAAC;IAErE,QAAQ,CAAC,WAAW,EAAE,OAAO,WAAW,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,OAAO,aAAa,CAAC;CAC9C;AAED,MAAM,MAAM,2BAA2B,GAAG,kBAAkB,CAAC;AAE7D,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,YAAY,CAAC,WAAW,CAAC;IAChE;;;OAGG;gBACS,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM;IAEvD;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAElC;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,kBAAkB,EAAE,OAAO,CAAC;IAE5B;;;OAGG;IACH,aAAa,EAAE,WAAW,CAAC;IAE3B;;OAEG;IACH,IAAI,IAAI,IAAI;IAEZ;;OAEG;IACH,KAAK,IAAI,IAAI;IAEb;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAEtC;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI;IAEtF;;;OAGG;IACH,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAE/C;;OAEG;IACH,MAAM,IAAI,IAAI;CACf;AAED,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IACjC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,
|
|
1
|
+
{"version":3,"file":"AudioModule.types.d.ts","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioModule.types.js","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["import { PermissionResponse, SharedObject } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\n\nexport interface AudioModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<RecordingPermissionResponse>;\n getRecordingPermissionsAsync(): Promise<RecordingPermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\n\nexport type RecordingPermissionResponse = PermissionResponse;\n\nexport declare class AudioPlayer extends SharedObject<AudioEvents> {\n /**\n * Initializes a new audio player instance with the given source.\n * @hidden\n */\n constructor(source: AudioSource, updateInterval: number);\n\n /**\n * Unique identifier for the player object.\n */\n id: number;\n\n /**\n * Boolean value indicating whether the player is currently playing.\n */\n playing: boolean;\n\n /**\n * Boolean value indicating whether the player is currently muted.\n */\n muted: boolean;\n\n /**\n * Boolean value indicating whether the player is currently looping.\n */\n loop: boolean;\n\n /**\n * Boolean value indicating whether the player is currently paused.\n */\n paused: boolean;\n\n /**\n * Boolean value indicating whether the player is finished loading.\n */\n isLoaded: boolean;\n\n /**\n * Boolean value indicating whether audio sampling is supported on the platform.\n */\n isAudioSamplingSupported: boolean;\n\n /**\n * Boolean value indicating whether the player is buffering.\n */\n isBuffering: boolean;\n\n /**\n * The current position through the audio item, in seconds.\n */\n currentTime: number;\n\n /**\n * The total duration of the audio, in seconds.\n */\n duration: number;\n\n /**\n * The current volume of the audio.\n */\n volume: number;\n\n /**\n * The current playback rate of the audio.\n */\n playbackRate: number;\n\n /**\n * A boolean describing if we are correcting the pitch for a changed rate.\n */\n shouldCorrectPitch: boolean;\n\n /**\n * The current status of the audio player.\n * @hidden\n */\n currentStatus: AudioStatus;\n\n /**\n * Resumes the player.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Seeks the playback by the given number of seconds.\n * @param seconds The number of seconds to seek by.\n */\n seekTo(seconds: number): Promise<void>;\n\n /**\n * Sets the current playback rate of the audio.\n * @param rate The playback rate of the audio.\n * @param pitchCorrectionQuality The quality of the pitch correction.\n */\n setPlaybackRate(second: number, pitchCorrectionQuality?: PitchCorrectionQuality): void;\n\n /**\n *\n * @hidden\n */\n setAudioSamplingEnabled(enabled: boolean): void;\n\n /**\n * Remove the player from memory to free up resources.\n */\n remove(): void;\n}\n\ntype AudioSample = {\n channels: { frames: number[] }[];\n timestamp: number;\n};\n\nexport type AudioEvents = {\n
|
|
1
|
+
{"version":3,"file":"AudioModule.types.js","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["import { PermissionResponse, SharedObject } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\n\nexport interface AudioModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<RecordingPermissionResponse>;\n getRecordingPermissionsAsync(): Promise<RecordingPermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\n\nexport type RecordingPermissionResponse = PermissionResponse;\n\nexport declare class AudioPlayer extends SharedObject<AudioEvents> {\n /**\n * Initializes a new audio player instance with the given source.\n * @hidden\n */\n constructor(source: AudioSource, updateInterval: number);\n\n /**\n * Unique identifier for the player object.\n */\n id: number;\n\n /**\n * Boolean value indicating whether the player is currently playing.\n */\n playing: boolean;\n\n /**\n * Boolean value indicating whether the player is currently muted.\n */\n muted: boolean;\n\n /**\n * Boolean value indicating whether the player is currently looping.\n */\n loop: boolean;\n\n /**\n * Boolean value indicating whether the player is currently paused.\n */\n paused: boolean;\n\n /**\n * Boolean value indicating whether the player is finished loading.\n */\n isLoaded: boolean;\n\n /**\n * Boolean value indicating whether audio sampling is supported on the platform.\n */\n isAudioSamplingSupported: boolean;\n\n /**\n * Boolean value indicating whether the player is buffering.\n */\n isBuffering: boolean;\n\n /**\n * The current position through the audio item, in seconds.\n */\n currentTime: number;\n\n /**\n * The total duration of the audio, in seconds.\n */\n duration: number;\n\n /**\n * The current volume of the audio.\n */\n volume: number;\n\n /**\n * The current playback rate of the audio.\n */\n playbackRate: number;\n\n /**\n * A boolean describing if we are correcting the pitch for a changed rate.\n */\n shouldCorrectPitch: boolean;\n\n /**\n * The current status of the audio player.\n * @hidden\n */\n currentStatus: AudioStatus;\n\n /**\n * Resumes the player.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Seeks the playback by the given number of seconds.\n * @param seconds The number of seconds to seek by.\n */\n seekTo(seconds: number): Promise<void>;\n\n /**\n * Sets the current playback rate of the audio.\n * @param rate The playback rate of the audio.\n * @param pitchCorrectionQuality The quality of the pitch correction.\n */\n setPlaybackRate(second: number, pitchCorrectionQuality?: PitchCorrectionQuality): void;\n\n /**\n *\n * @hidden\n */\n setAudioSamplingEnabled(enabled: boolean): void;\n\n /**\n * Remove the player from memory to free up resources.\n */\n remove(): void;\n}\n\ntype AudioSample = {\n channels: { frames: number[] }[];\n timestamp: number;\n};\n\nexport type AudioEvents = {\n playbackStatusUpdate(status: AudioStatus): void;\n audioSampleUpdate(data: AudioSample): void;\n};\n\nexport declare class AudioRecorder extends SharedObject<RecordingEvents> {\n /**\n * Initializes a new audio recorder instance with the given source.\n * @hidden\n */\n constructor(options: Partial<RecordingOptions>);\n\n /**\n * Unique identifier for the recorder object.\n */\n id: number;\n\n /**\n * The current length of the recording, in seconds.\n */\n currentTime: number;\n\n /**\n * Boolean value indicating whether the recording is in progress.\n */\n isRecording: boolean;\n\n /**\n * The uri of the recording.\n */\n uri: string | null;\n\n /**\n * Starts the recording.\n */\n record(): void;\n\n /**\n * Stop the recording.\n */\n stop(): Promise<void>;\n\n /**\n * Pause the recording.\n */\n pause(): void;\n\n /**\n * Returns a list of available recording inputs. This method can only be called if the `Recording` has been prepared.\n * @return A `Promise` that is fulfilled with an array of `RecordingInput` objects.\n */\n getAvailableInputs(): RecordingInput[];\n\n /**\n * Returns the currently-selected recording input. This method can only be called if the `Recording` has been prepared.\n * @return A `Promise` that is fulfilled with a `RecordingInput` object.\n */\n getCurrentInput(): RecordingInput;\n\n /**\n * Sets the current recording input.\n * @param inputUid The uid of a `RecordingInput`.\n * @return A `Promise` that is resolved if successful or rejected if not.\n */\n setInput(input: string): void;\n\n /**\n * Status of the current recording.\n */\n getStatus(): RecorderState;\n\n /**\n * Starts the recording at the given time.\n * @param seconds The time in seconds to start recording at.\n */\n startRecordingAtTime(seconds: number): void;\n\n /**\n * Prepares the recording for recording.\n */\n prepareToRecordAsync(options?: Partial<RecordingOptions>): Promise<void>;\n\n /**\n * Stops the recording once the specified time has elapsed.\n * @param seconds The time in seconds to stop recording at.\n */\n recordForDuration(seconds: number): void;\n}\n\nexport type RecordingEvents = {\n recordingStatusUpdate: (status: RecordingStatus) => void;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioModule.web.d.ts","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAoB,MAAM,mBAAmB,CAAC;AAEzE,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,sBAAsB,EACtB,aAAa,EACb,cAAc,EACd,gBAAgB,EACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"AudioModule.web.d.ts","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"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"}
|
package/build/AudioModule.web.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PermissionStatus } from 'expo-modules-core';
|
|
2
|
+
import { PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
|
|
2
3
|
import { RecordingPresets } from './RecordingConstants';
|
|
3
4
|
const nextId = (() => {
|
|
4
5
|
let id = 0;
|
|
@@ -156,11 +157,11 @@ export class AudioPlayerWeb extends globalThis.expo.SharedObject {
|
|
|
156
157
|
const newSource = typeof this.src === 'string' ? this.src : (this.src?.uri ?? '');
|
|
157
158
|
const media = new Audio(newSource);
|
|
158
159
|
media.ontimeupdate = () => {
|
|
159
|
-
this.emit(
|
|
160
|
+
this.emit(PLAYBACK_STATUS_UPDATE, getStatusFromMedia(media, this.id));
|
|
160
161
|
};
|
|
161
162
|
media.onloadeddata = () => {
|
|
162
163
|
this.loaded = true;
|
|
163
|
-
this.emit(
|
|
164
|
+
this.emit(PLAYBACK_STATUS_UPDATE, {
|
|
164
165
|
...getStatusFromMedia(media, this.id),
|
|
165
166
|
isLoaded: this.loaded,
|
|
166
167
|
});
|
|
@@ -248,7 +249,7 @@ export class AudioRecorderWeb extends globalThis.expo.SharedObject {
|
|
|
248
249
|
const data = await dataPromise;
|
|
249
250
|
const url = URL.createObjectURL(data);
|
|
250
251
|
this.uri = url;
|
|
251
|
-
this.emit(
|
|
252
|
+
this.emit(RECORDING_STATUS_UPDATE, {
|
|
252
253
|
id: this.id,
|
|
253
254
|
isFinished: true,
|
|
254
255
|
hasError: false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AudioModule.web.js","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAYzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,MAAM,GAAG,CAAC,GAAG,EAAE;IACnB,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,OAAO,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;AACpB,CAAC,CAAC,EAAE,CAAC;AAEL,KAAK,UAAU,2BAA2B,CACxC,IAAwC;IAExC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,WAAW,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAEtF,IAAI;QACF,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,QAAQ,KAAK,EAAE;YACb,KAAK,SAAS;gBACZ,OAAO,gBAAgB,CAAC,OAAO,CAAC;YAClC,KAAK,QAAQ;gBACX,OAAO,gBAAgB,CAAC,MAAM,CAAC;YACjC;gBACE,OAAO,gBAAgB,CAAC,YAAY,CAAC;SACxC;KACF;IAAC,MAAM;QACN,0IAA0I;QAC1I,OAAO,gBAAgB,CAAC,YAAY,CAAC;KACtC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,WAAmC;IACvD,IAAI,SAAS,CAAC,YAAY,IAAI,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE;QACjE,OAAO,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;KACzD;IAED,iFAAiF;IACjF,+DAA+D;IAC/D,oEAAoE;IAEpE,yDAAyD;IACzD,MAAM,YAAY;IAChB,yHAAyH;IACzH,SAAS,CAAC,YAAY;QACtB,SAAS,CAAC,kBAAkB;QAC5B,SAAS,CAAC,eAAe;QACzB;YACE,MAAM,KAAK,GAAQ,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YACzD,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,GAAG,iBAAiB,CAAC;YAC/B,MAAM,KAAK,CAAC;QACd,CAAC,CAAC;IAEJ,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,kBAAkB,CAAC,KAAuB,EAAE,EAAU;IAC7D,MAAM,SAAS,GAAG,CAAC,CAAC,CAClB,KAAK,CAAC,WAAW,GAAG,CAAC;QACrB,CAAC,KAAK,CAAC,MAAM;QACb,CAAC,KAAK,CAAC,KAAK;QACZ,KAAK,CAAC,UAAU,GAAG,CAAC,CACrB,CAAC;IAEF,MAAM,MAAM,GAAgB;QAC1B,EAAE;QACF,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI;QAC/B,WAAW,EAAE,KAAK,CAAC,WAAW,GAAG,IAAI;QACrC,aAAa,EAAE,EAAE;QACjB,iBAAiB,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;QACnD,sBAAsB,EAAE,EAAE;QAC1B,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,kBAAkB,EAAE,KAAK;QACzB,IAAI,EAAE,KAAK,CAAC,KAAK;QACjB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,OAAO,cACX,SAAQ,UAAU,CAAC,IAAI,CAAC,YAAyB;IAGjD,YAAY,MAAmB,EAAE,QAAgB;QAC/C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC;QAClB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC1C,CAAC;IAED,EAAE,GAAW,MAAM,EAAE,CAAC;IACtB,wBAAwB,GAAG,KAAK,CAAC;IACjC,WAAW,GAAG,KAAK,CAAC;IACpB,kBAAkB,GAAG,KAAK,CAAC;IAEnB,GAAG,GAAgB,IAAI,CAAC;IACxB,KAAK,CAAmB;IACxB,QAAQ,GAAG,GAAG,CAAC;IACf,SAAS,GAAG,KAAK,CAAC;IAClB,MAAM,GAAG,KAAK,CAAC;IAEvB,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK,CAAC,KAAc;QACtB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IAC3B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED,IAAI,IAAI,CAAC,KAAc;QACrB,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;IACpC,CAAC;IAED,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;IACvC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;IACjC,CAAC;IAED,IAAI,YAAY,CAAC,KAAa;QAC5B,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC;IAClC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,MAAM,CAAC,KAAa;QACtB,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI;QACF,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,OAAO,GAAG,IAAI,CAAC;IAC1C,CAAC;IAED,uBAAuB;IACvB,uBAAuB,CAAC,OAAgB;QACtC,IAAI,CAAC,wBAAwB,GAAG,KAAK,CAAC;IACxC,CAAC;IAED,eAAe,CAAC,MAAc,EAAE,sBAA+C;QAC7E,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC;QACjC,IAAI,CAAC,kBAAkB,GAAG,sBAAsB,KAAK,MAAM,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC;IACtD,CAAC;IAED,MAAM;QACJ,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QAClB,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,mBAAmB;QACjB,MAAM,SAAS,GAAG,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAEnC,KAAK,CAAC,YAAY,GAAG,GAAG,EAAE;YACxB,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC;QAEF,KAAK,CAAC,YAAY,GAAG,GAAG,EAAE;YACxB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE;gBAClC,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,CAAC;gBACrC,QAAQ,EAAE,IAAI,CAAC,MAAM;aACtB,CAAC,CAAC;QACL,CAAC,CAAC;QAEF,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,OAAO,gBACX,SAAQ,UAAU,CAAC,IAAI,CAAC,YAA6B;IAGrD,YAAY,OAAkC;QAC5C,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,aAAa,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC;IAED,EAAE,GAAG,MAAM,EAAE,CAAC;IACd,WAAW,GAAG,CAAC,CAAC;IAChB,GAAG,GAAkB,IAAI,CAAC;IAElB,OAAO,CAA4B;IACnC,aAAa,GAAyB,IAAI,CAAC;IAC3C,oCAAoC,GAAG,CAAC,CAAC;IACzC,wBAAwB,GAAG,KAAK,CAAC;IACjC,UAAU,GAAa,EAAE,CAAC;IAElC,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,WAAW,CAAC;IACnD,CAAC;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,iJAAiJ,CAClJ,CAAC;SACH;QAED,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,QAAQ,EAAE;YAC1C,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;SAC7B;aAAM;YACL,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC;SAC7B;IACH,CAAC;IAED,kBAAkB;QAChB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,eAAe;QACb,OAAO;YACL,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,GAAG,EAAE,SAAS;SACf,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;IAED,SAAS;QACP,OAAO;YACL,SAAS,EACP,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,WAAW,IAAI,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,UAAU;YACvF,WAAW,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,KAAK,WAAW;YACtD,cAAc,EAAE,IAAI,CAAC,8BAA8B,EAAE;YACrD,qBAAqB,EAAE,KAAK;YAC5B,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,iJAAiJ,CAClJ,CAAC;SACH;QAED,IAAI,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IAED,iBAAiB,CAAC,OAAe;QAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,UAAU,CAAC,IAAI,CAClB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,CACnB,CAAC;IACJ,CAAC;IAED,QAAQ,CAAC,KAAa,IAAS,CAAC;IAEhC,oBAAoB,CAAC,OAAe;QAClC,IAAI,CAAC,UAAU,CAAC,IAAI,CAClB,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC,CACnB,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,aAAa,KAAK,IAAI,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,iJAAiJ,CAClJ,CAAC;SACH;QAED,MAAM,WAAW,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAChD,IAAI,CAAC,aAAa,EAAE,gBAAgB,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAC9E,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAE1B,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAEtC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QAEf,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE;YACnC,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,KAAK;YACf,KAAK,EAAE,IAAI;YACX,GAAG;SACJ,CAAC,CAAC;IACL,CAAC;IAED,aAAa;QACX,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,OAAkC;QAClE,IAAI,OAAO,SAAS,KAAK,WAAW,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE;YAC/D,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;SAC/C;QAED,IAAI,CAAC,oCAAoC,GAAG,CAAC,CAAC;QAC9C,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;QAErB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnD,MAAM,aAAa,GAAG,IAAK,MAAc,CAAC,aAAa,CACrD,MAAM,EACN,OAAO,EAAE,GAAG,IAAI,gBAAgB,CAAC,YAAY,CAAC,GAAG,CAClD,CAAC;QAEF,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YAC3C,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,8BAA8B,EAAE,CAAC;YACzD,IAAI,CAAC,wBAAwB,GAAG,KAAK,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,aAAa,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC5C,IAAI,CAAC,oCAAoC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvD,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YAC3C,IAAI,CAAC,oCAAoC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvD,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,aAAa,EAAE,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YAC3C,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YACrB,IAAI,CAAC,wBAAwB,GAAG,KAAK,CAAC;YAEtC,sCAAsC;YACtC,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QAEH,OAAO,aAAa,CAAC;IACvB,CAAC;IAEO,8BAA8B;QACpC,IAAI,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,IAAI,IAAI,CAAC,wBAAwB,IAAI,IAAI,CAAC,oCAAoC,GAAG,CAAC,EAAE;YAClF,QAAQ,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,oCAAoC,CAAC;SACpE;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAe,IAAG,CAAC;AAC3D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,MAAe,IAAG,CAAC;AAE/D,MAAM,CAAC,KAAK,UAAU,4BAA4B;IAChD,MAAM,WAAW,GAAG,MAAM,2BAA2B,CAAC,YAAY,CAAC,CAAC;IACpE,QAAQ,WAAW,EAAE;QACnB,KAAK,gBAAgB,CAAC,OAAO;YAC3B,OAAO;gBACL,MAAM,EAAE,gBAAgB,CAAC,OAAO;gBAChC,OAAO,EAAE,OAAO;gBAChB,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,KAAK,gBAAgB,CAAC,MAAM;YAC1B,OAAO;gBACL,MAAM,EAAE,gBAAgB,CAAC,MAAM;gBAC/B,OAAO,EAAE,OAAO;gBAChB,WAAW,EAAE,IAAI;gBACjB,OAAO,EAAE,KAAK;aACf,CAAC;QACJ;YACE,OAAO,MAAM,gCAAgC,EAAE,CAAC;KACnD;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gCAAgC;IACpD,IAAI;QACF,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,OAAO;YACL,MAAM,EAAE,gBAAgB,CAAC,OAAO;YAChC,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,IAAI;YACjB,OAAO,EAAE,IAAI;SACd,CAAC;KACH;IAAC,MAAM;QACN,OAAO;YACL,MAAM,EAAE,gBAAgB,CAAC,MAAM;YAC/B,OAAO,EAAE,OAAO;YAChB,WAAW,EAAE,IAAI;YACjB,OAAO,EAAE,KAAK;SACf,CAAC;KACH;AACH,CAAC","sourcesContent":["import { PermissionResponse, PermissionStatus } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n} from './Audio.types';\nimport { AudioPlayer, AudioEvents, RecordingEvents, AudioRecorder } from './AudioModule.types';\nimport { RecordingPresets } from './RecordingConstants';\n\nconst nextId = (() => {\n let id = 0;\n return () => id++;\n})();\n\nasync function getPermissionWithQueryAsync(\n name: PermissionNameWithAdditionalValues\n): Promise<PermissionStatus | null> {\n if (!navigator || !navigator.permissions || !navigator.permissions.query) return null;\n\n try {\n const { state } = await navigator.permissions.query({ name });\n switch (state) {\n case 'granted':\n return PermissionStatus.GRANTED;\n case 'denied':\n return PermissionStatus.DENIED;\n default:\n return PermissionStatus.UNDETERMINED;\n }\n } catch {\n // Firefox - TypeError: 'microphone' (value of 'name' member of PermissionDescriptor) is not a valid value for enumeration PermissionName.\n return PermissionStatus.UNDETERMINED;\n }\n}\n\nfunction getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream> {\n if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n return navigator.mediaDevices.getUserMedia(constraints);\n }\n\n // Some browsers partially implement mediaDevices. We can't just assign an object\n // with getUserMedia as it would overwrite existing properties.\n // Here, we will just add the getUserMedia property if it's missing.\n\n // First get ahold of the legacy getUserMedia, if present\n const getUserMedia =\n // TODO: this method is deprecated, migrate to https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia\n navigator.getUserMedia ||\n navigator.webkitGetUserMedia ||\n navigator.mozGetUserMedia ||\n function () {\n const error: any = new Error('Permission unimplemented');\n error.code = 0;\n error.name = 'NotAllowedError';\n throw error;\n };\n\n return new Promise((resolve, reject) => {\n getUserMedia.call(navigator, constraints, resolve, reject);\n });\n}\n\nfunction getStatusFromMedia(media: HTMLMediaElement, id: number): AudioStatus {\n const isPlaying = !!(\n media.currentTime > 0 &&\n !media.paused &&\n !media.ended &&\n media.readyState > 2\n );\n\n const status: AudioStatus = {\n id,\n isLoaded: true,\n duration: media.duration * 1000,\n currentTime: media.currentTime * 1000,\n playbackState: '',\n timeControlStatus: isPlaying ? 'playing' : 'paused',\n reasonForWaitingToPlay: '',\n playing: isPlaying,\n isBuffering: false,\n playbackRate: media.playbackRate,\n shouldCorrectPitch: false,\n mute: media.muted,\n loop: media.loop,\n };\n\n return status;\n}\n\nexport class AudioPlayerWeb\n extends globalThis.expo.SharedObject<AudioEvents>\n implements AudioPlayer\n{\n constructor(source: AudioSource, interval: number) {\n super();\n this.src = source;\n this.interval = interval;\n this.media = this._createMediaElement();\n }\n\n id: number = nextId();\n isAudioSamplingSupported = false;\n isBuffering = false;\n shouldCorrectPitch = false;\n\n private src: AudioSource = null;\n private media: HTMLAudioElement;\n private interval = 100;\n private isPlaying = false;\n private loaded = false;\n\n get playing(): boolean {\n return this.isPlaying;\n }\n\n get muted(): boolean {\n return this.media.muted;\n }\n\n set muted(value: boolean) {\n this.media.muted = value;\n }\n\n get loop(): boolean {\n return this.media.loop;\n }\n\n set loop(value: boolean) {\n this.media.loop = value;\n }\n\n get duration(): number {\n return this.media.duration * 1000;\n }\n\n get currentTime(): number {\n return this.media.currentTime * 1000;\n }\n\n get paused(): boolean {\n return this.media.paused;\n }\n\n get isLoaded(): boolean {\n return this.loaded;\n }\n\n get playbackRate(): number {\n return this.media.playbackRate;\n }\n\n set playbackRate(value: number) {\n this.media.playbackRate = value;\n }\n\n get volume(): number {\n return this.media.volume;\n }\n\n set volume(value: number) {\n this.media.volume = value;\n }\n\n get currentStatus(): AudioStatus {\n return getStatusFromMedia(this.media, this.id);\n }\n\n play(): void {\n this.media.play();\n this.isPlaying = true;\n }\n\n pause(): void {\n this.media.pause();\n this.isPlaying = false;\n }\n\n async seekTo(seconds: number): Promise<void> {\n this.media.currentTime = seconds / 1000;\n }\n\n // Not supported on web\n setAudioSamplingEnabled(enabled: boolean): void {\n this.isAudioSamplingSupported = false;\n }\n\n setPlaybackRate(second: number, pitchCorrectionQuality?: PitchCorrectionQuality): void {\n this.media.playbackRate = second;\n this.shouldCorrectPitch = pitchCorrectionQuality === 'high';\n this.media.preservesPitch = this.shouldCorrectPitch;\n }\n\n remove(): void {\n this.media.pause();\n this.media.removeAttribute('src');\n this.media.load();\n getStatusFromMedia(this.media, this.id);\n }\n\n _createMediaElement(): HTMLAudioElement {\n const newSource = typeof this.src === 'string' ? this.src : (this.src?.uri ?? '');\n const media = new Audio(newSource);\n\n media.ontimeupdate = () => {\n this.emit('onPlaybackStatusUpdate', getStatusFromMedia(media, this.id));\n };\n\n media.onloadeddata = () => {\n this.loaded = true;\n this.emit('onPlaybackStatusUpdate', {\n ...getStatusFromMedia(media, this.id),\n isLoaded: this.loaded,\n });\n };\n\n return media;\n }\n}\n\nexport class AudioRecorderWeb\n extends globalThis.expo.SharedObject<RecordingEvents>\n implements AudioRecorder\n{\n constructor(options: Partial<RecordingOptions>) {\n super();\n this.options = options;\n }\n\n async setup() {\n this.mediaRecorder = await this.createMediaRecorder(this.options);\n }\n\n id = nextId();\n currentTime = 0;\n uri: string | null = null;\n\n private options: Partial<RecordingOptions>;\n private mediaRecorder: MediaRecorder | null = null;\n private mediaRecorderUptimeOfLastStartResume = 0;\n private mediaRecorderIsRecording = false;\n private timeoutIds: number[] = [];\n\n get isRecording(): boolean {\n return this.mediaRecorder?.state === 'recording';\n }\n\n record(): void {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n if (this.mediaRecorder?.state === 'paused') {\n this.mediaRecorder.resume();\n } else {\n this.mediaRecorder?.start();\n }\n }\n\n getAvailableInputs(): RecordingInput[] {\n return [];\n }\n\n getCurrentInput(): RecordingInput {\n return {\n type: 'Default',\n name: 'Default',\n uid: 'Default',\n };\n }\n\n async prepareToRecordAsync(): Promise<void> {\n return this.setup();\n }\n\n getStatus(): RecorderState {\n return {\n canRecord:\n this.mediaRecorder?.state === 'recording' || this.mediaRecorder?.state === 'inactive',\n isRecording: this.mediaRecorder?.state === 'recording',\n durationMillis: this.getAudioRecorderDurationMillis(),\n mediaServicesDidReset: false,\n url: this.uri,\n };\n }\n\n pause(): void {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n this.mediaRecorder?.pause();\n }\n\n recordForDuration(seconds: number): void {\n this.record();\n this.timeoutIds.push(\n setTimeout(() => {\n this.stop();\n }, seconds * 1000)\n );\n }\n\n setInput(input: string): void {}\n\n startRecordingAtTime(seconds: number): void {\n this.timeoutIds.push(\n setTimeout(() => {\n this.record();\n }, seconds * 1000)\n );\n }\n\n async stop(): Promise<void> {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n const dataPromise = new Promise<Blob>((resolve) =>\n this.mediaRecorder?.addEventListener('dataavailable', (e) => resolve(e.data))\n );\n\n this.mediaRecorder?.stop();\n this.mediaRecorder = null;\n\n const data = await dataPromise;\n const url = URL.createObjectURL(data);\n\n this.uri = url;\n\n this.emit('onRecordingStatusUpdate', {\n id: this.id,\n isFinished: true,\n hasError: false,\n error: null,\n url,\n });\n }\n\n clearTimeouts() {\n this.timeoutIds.forEach((id) => clearTimeout(id));\n }\n\n private async createMediaRecorder(options: Partial<RecordingOptions>): Promise<MediaRecorder> {\n if (typeof navigator !== 'undefined' && !navigator.mediaDevices) {\n throw new Error('No media devices available');\n }\n\n this.mediaRecorderUptimeOfLastStartResume = 0;\n this.currentTime = 0;\n\n const stream = await getUserMedia({ audio: true });\n\n const mediaRecorder = new (window as any).MediaRecorder(\n stream,\n options?.web || RecordingPresets.HIGH_QUALITY.web\n );\n\n mediaRecorder.addEventListener('pause', () => {\n this.currentTime = this.getAudioRecorderDurationMillis();\n this.mediaRecorderIsRecording = false;\n });\n\n mediaRecorder.addEventListener('resume', () => {\n this.mediaRecorderUptimeOfLastStartResume = Date.now();\n this.mediaRecorderIsRecording = true;\n });\n\n mediaRecorder.addEventListener('start', () => {\n this.mediaRecorderUptimeOfLastStartResume = Date.now();\n this.currentTime = 0;\n this.mediaRecorderIsRecording = true;\n });\n\n mediaRecorder?.addEventListener('stop', () => {\n this.currentTime = 0;\n this.mediaRecorderIsRecording = false;\n\n // Clears recording icon in Chrome tab\n stream.getTracks().forEach((track) => track.stop());\n });\n\n return mediaRecorder;\n }\n\n private getAudioRecorderDurationMillis() {\n let duration = this.currentTime;\n if (this.mediaRecorderIsRecording && this.mediaRecorderUptimeOfLastStartResume > 0) {\n duration += Date.now() - this.mediaRecorderUptimeOfLastStartResume;\n }\n return duration;\n }\n}\n\nexport async function setAudioModeAsync(mode: AudioMode) {}\nexport async function setIsAudioActiveAsync(active: boolean) {}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n const maybeStatus = await getPermissionWithQueryAsync('microphone');\n switch (maybeStatus) {\n case PermissionStatus.GRANTED:\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n canAskAgain: true,\n granted: true,\n };\n case PermissionStatus.DENIED:\n return {\n status: PermissionStatus.DENIED,\n expires: 'never',\n canAskAgain: true,\n granted: false,\n };\n default:\n return await requestRecordingPermissionsAsync();\n }\n}\n\nexport async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n try {\n const stream = await getUserMedia({ audio: true });\n stream.getTracks().forEach((track) => track.stop());\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n canAskAgain: true,\n granted: true,\n };\n } catch {\n return {\n status: PermissionStatus.DENIED,\n expires: 'never',\n canAskAgain: true,\n granted: false,\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AudioModule.web.js","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"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","sourcesContent":["import { PermissionResponse, PermissionStatus } from 'expo-modules-core';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n PitchCorrectionQuality,\n RecorderState,\n RecordingInput,\n RecordingOptions,\n} from './Audio.types';\nimport { AudioPlayer, AudioEvents, RecordingEvents, AudioRecorder } from './AudioModule.types';\nimport { PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';\nimport { RecordingPresets } from './RecordingConstants';\n\nconst nextId = (() => {\n let id = 0;\n return () => id++;\n})();\n\nasync function getPermissionWithQueryAsync(\n name: PermissionNameWithAdditionalValues\n): Promise<PermissionStatus | null> {\n if (!navigator || !navigator.permissions || !navigator.permissions.query) return null;\n\n try {\n const { state } = await navigator.permissions.query({ name });\n switch (state) {\n case 'granted':\n return PermissionStatus.GRANTED;\n case 'denied':\n return PermissionStatus.DENIED;\n default:\n return PermissionStatus.UNDETERMINED;\n }\n } catch {\n // Firefox - TypeError: 'microphone' (value of 'name' member of PermissionDescriptor) is not a valid value for enumeration PermissionName.\n return PermissionStatus.UNDETERMINED;\n }\n}\n\nfunction getUserMedia(constraints: MediaStreamConstraints): Promise<MediaStream> {\n if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {\n return navigator.mediaDevices.getUserMedia(constraints);\n }\n\n // Some browsers partially implement mediaDevices. We can't just assign an object\n // with getUserMedia as it would overwrite existing properties.\n // Here, we will just add the getUserMedia property if it's missing.\n\n // First get ahold of the legacy getUserMedia, if present\n const getUserMedia =\n // TODO: this method is deprecated, migrate to https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia\n navigator.getUserMedia ||\n navigator.webkitGetUserMedia ||\n navigator.mozGetUserMedia ||\n function () {\n const error: any = new Error('Permission unimplemented');\n error.code = 0;\n error.name = 'NotAllowedError';\n throw error;\n };\n\n return new Promise((resolve, reject) => {\n getUserMedia.call(navigator, constraints, resolve, reject);\n });\n}\n\nfunction getStatusFromMedia(media: HTMLMediaElement, id: number): AudioStatus {\n const isPlaying = !!(\n media.currentTime > 0 &&\n !media.paused &&\n !media.ended &&\n media.readyState > 2\n );\n\n const status: AudioStatus = {\n id,\n isLoaded: true,\n duration: media.duration * 1000,\n currentTime: media.currentTime * 1000,\n playbackState: '',\n timeControlStatus: isPlaying ? 'playing' : 'paused',\n reasonForWaitingToPlay: '',\n playing: isPlaying,\n isBuffering: false,\n playbackRate: media.playbackRate,\n shouldCorrectPitch: false,\n mute: media.muted,\n loop: media.loop,\n };\n\n return status;\n}\n\nexport class AudioPlayerWeb\n extends globalThis.expo.SharedObject<AudioEvents>\n implements AudioPlayer\n{\n constructor(source: AudioSource, interval: number) {\n super();\n this.src = source;\n this.interval = interval;\n this.media = this._createMediaElement();\n }\n\n id: number = nextId();\n isAudioSamplingSupported = false;\n isBuffering = false;\n shouldCorrectPitch = false;\n\n private src: AudioSource = null;\n private media: HTMLAudioElement;\n private interval = 100;\n private isPlaying = false;\n private loaded = false;\n\n get playing(): boolean {\n return this.isPlaying;\n }\n\n get muted(): boolean {\n return this.media.muted;\n }\n\n set muted(value: boolean) {\n this.media.muted = value;\n }\n\n get loop(): boolean {\n return this.media.loop;\n }\n\n set loop(value: boolean) {\n this.media.loop = value;\n }\n\n get duration(): number {\n return this.media.duration * 1000;\n }\n\n get currentTime(): number {\n return this.media.currentTime * 1000;\n }\n\n get paused(): boolean {\n return this.media.paused;\n }\n\n get isLoaded(): boolean {\n return this.loaded;\n }\n\n get playbackRate(): number {\n return this.media.playbackRate;\n }\n\n set playbackRate(value: number) {\n this.media.playbackRate = value;\n }\n\n get volume(): number {\n return this.media.volume;\n }\n\n set volume(value: number) {\n this.media.volume = value;\n }\n\n get currentStatus(): AudioStatus {\n return getStatusFromMedia(this.media, this.id);\n }\n\n play(): void {\n this.media.play();\n this.isPlaying = true;\n }\n\n pause(): void {\n this.media.pause();\n this.isPlaying = false;\n }\n\n async seekTo(seconds: number): Promise<void> {\n this.media.currentTime = seconds / 1000;\n }\n\n // Not supported on web\n setAudioSamplingEnabled(enabled: boolean): void {\n this.isAudioSamplingSupported = false;\n }\n\n setPlaybackRate(second: number, pitchCorrectionQuality?: PitchCorrectionQuality): void {\n this.media.playbackRate = second;\n this.shouldCorrectPitch = pitchCorrectionQuality === 'high';\n this.media.preservesPitch = this.shouldCorrectPitch;\n }\n\n remove(): void {\n this.media.pause();\n this.media.removeAttribute('src');\n this.media.load();\n getStatusFromMedia(this.media, this.id);\n }\n\n _createMediaElement(): HTMLAudioElement {\n const newSource = typeof this.src === 'string' ? this.src : (this.src?.uri ?? '');\n const media = new Audio(newSource);\n\n media.ontimeupdate = () => {\n this.emit(PLAYBACK_STATUS_UPDATE, getStatusFromMedia(media, this.id));\n };\n\n media.onloadeddata = () => {\n this.loaded = true;\n this.emit(PLAYBACK_STATUS_UPDATE, {\n ...getStatusFromMedia(media, this.id),\n isLoaded: this.loaded,\n });\n };\n\n return media;\n }\n}\n\nexport class AudioRecorderWeb\n extends globalThis.expo.SharedObject<RecordingEvents>\n implements AudioRecorder\n{\n constructor(options: Partial<RecordingOptions>) {\n super();\n this.options = options;\n }\n\n async setup() {\n this.mediaRecorder = await this.createMediaRecorder(this.options);\n }\n\n id = nextId();\n currentTime = 0;\n uri: string | null = null;\n\n private options: Partial<RecordingOptions>;\n private mediaRecorder: MediaRecorder | null = null;\n private mediaRecorderUptimeOfLastStartResume = 0;\n private mediaRecorderIsRecording = false;\n private timeoutIds: number[] = [];\n\n get isRecording(): boolean {\n return this.mediaRecorder?.state === 'recording';\n }\n\n record(): void {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n if (this.mediaRecorder?.state === 'paused') {\n this.mediaRecorder.resume();\n } else {\n this.mediaRecorder?.start();\n }\n }\n\n getAvailableInputs(): RecordingInput[] {\n return [];\n }\n\n getCurrentInput(): RecordingInput {\n return {\n type: 'Default',\n name: 'Default',\n uid: 'Default',\n };\n }\n\n async prepareToRecordAsync(): Promise<void> {\n return this.setup();\n }\n\n getStatus(): RecorderState {\n return {\n canRecord:\n this.mediaRecorder?.state === 'recording' || this.mediaRecorder?.state === 'inactive',\n isRecording: this.mediaRecorder?.state === 'recording',\n durationMillis: this.getAudioRecorderDurationMillis(),\n mediaServicesDidReset: false,\n url: this.uri,\n };\n }\n\n pause(): void {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n this.mediaRecorder?.pause();\n }\n\n recordForDuration(seconds: number): void {\n this.record();\n this.timeoutIds.push(\n setTimeout(() => {\n this.stop();\n }, seconds * 1000)\n );\n }\n\n setInput(input: string): void {}\n\n startRecordingAtTime(seconds: number): void {\n this.timeoutIds.push(\n setTimeout(() => {\n this.record();\n }, seconds * 1000)\n );\n }\n\n async stop(): Promise<void> {\n if (this.mediaRecorder === null) {\n throw new Error(\n 'Cannot start an audio recording without initializing a MediaRecorder. Run prepareToRecordAsync() before attempting to start an audio recording.'\n );\n }\n\n const dataPromise = new Promise<Blob>((resolve) =>\n this.mediaRecorder?.addEventListener('dataavailable', (e) => resolve(e.data))\n );\n\n this.mediaRecorder?.stop();\n this.mediaRecorder = null;\n\n const data = await dataPromise;\n const url = URL.createObjectURL(data);\n\n this.uri = url;\n\n this.emit(RECORDING_STATUS_UPDATE, {\n id: this.id,\n isFinished: true,\n hasError: false,\n error: null,\n url,\n });\n }\n\n clearTimeouts() {\n this.timeoutIds.forEach((id) => clearTimeout(id));\n }\n\n private async createMediaRecorder(options: Partial<RecordingOptions>): Promise<MediaRecorder> {\n if (typeof navigator !== 'undefined' && !navigator.mediaDevices) {\n throw new Error('No media devices available');\n }\n\n this.mediaRecorderUptimeOfLastStartResume = 0;\n this.currentTime = 0;\n\n const stream = await getUserMedia({ audio: true });\n\n const mediaRecorder = new (window as any).MediaRecorder(\n stream,\n options?.web || RecordingPresets.HIGH_QUALITY.web\n );\n\n mediaRecorder.addEventListener('pause', () => {\n this.currentTime = this.getAudioRecorderDurationMillis();\n this.mediaRecorderIsRecording = false;\n });\n\n mediaRecorder.addEventListener('resume', () => {\n this.mediaRecorderUptimeOfLastStartResume = Date.now();\n this.mediaRecorderIsRecording = true;\n });\n\n mediaRecorder.addEventListener('start', () => {\n this.mediaRecorderUptimeOfLastStartResume = Date.now();\n this.currentTime = 0;\n this.mediaRecorderIsRecording = true;\n });\n\n mediaRecorder?.addEventListener('stop', () => {\n this.currentTime = 0;\n this.mediaRecorderIsRecording = false;\n\n // Clears recording icon in Chrome tab\n stream.getTracks().forEach((track) => track.stop());\n });\n\n return mediaRecorder;\n }\n\n private getAudioRecorderDurationMillis() {\n let duration = this.currentTime;\n if (this.mediaRecorderIsRecording && this.mediaRecorderUptimeOfLastStartResume > 0) {\n duration += Date.now() - this.mediaRecorderUptimeOfLastStartResume;\n }\n return duration;\n }\n}\n\nexport async function setAudioModeAsync(mode: AudioMode) {}\nexport async function setIsAudioActiveAsync(active: boolean) {}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n const maybeStatus = await getPermissionWithQueryAsync('microphone');\n switch (maybeStatus) {\n case PermissionStatus.GRANTED:\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n canAskAgain: true,\n granted: true,\n };\n case PermissionStatus.DENIED:\n return {\n status: PermissionStatus.DENIED,\n expires: 'never',\n canAskAgain: true,\n granted: false,\n };\n default:\n return await requestRecordingPermissionsAsync();\n }\n}\n\nexport async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n try {\n const stream = await getUserMedia({ audio: true });\n stream.getTracks().forEach((track) => track.stop());\n return {\n status: PermissionStatus.GRANTED,\n expires: 'never',\n canAskAgain: true,\n granted: true,\n };\n } catch {\n return {\n status: PermissionStatus.DENIED,\n expires: 'never',\n canAskAgain: true,\n granted: false,\n };\n }\n}\n"]}
|
package/build/ExpoAudio.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { AudioMode, AudioSource, AudioStatus, RecorderState, RecordingOptions, RecordingStatus } from './Audio.types';
|
|
2
2
|
import AudioModule from './AudioModule';
|
|
3
3
|
import { AudioPlayer, AudioRecorder } from './AudioModule.types';
|
|
4
|
+
export declare const PLAYBACK_STATUS_UPDATE = "playbackStatusUpdate";
|
|
5
|
+
export declare const AUDIO_SAMPLE_UPDATE = "audioSampleUpdate";
|
|
6
|
+
export declare const RECORDING_STATUS_UPDATE = "recordingStatusUpdate";
|
|
4
7
|
export declare function useAudioPlayer(source?: AudioSource | string | number | null, updateInterval?: number): AudioPlayer;
|
|
5
8
|
export declare function useAudioPlayerStatus(player: AudioPlayer): AudioStatus;
|
|
6
9
|
export declare function useAudioSampleListener(player: AudioPlayer, listener: (data: {
|
package/build/ExpoAudio.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIjE,wBAAgB,cAAc,CAC5B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,
|
|
1
|
+
{"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIjE,eAAO,MAAM,sBAAsB,yBAAyB,CAAC;AAC7D,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AACvD,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAE/D,wBAAgB,cAAc,CAC5B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,CAMb;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAGrE;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,QAYlF;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GACjD,aAAa,CAcf;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,GAAE,MAAY,iBAYpF;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/E;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AACnD,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
|
package/build/ExpoAudio.js
CHANGED
|
@@ -5,14 +5,16 @@ import AudioModule from './AudioModule';
|
|
|
5
5
|
import { AudioPlayer, AudioRecorder } from './AudioModule.types';
|
|
6
6
|
import { createRecordingOptions } from './utils/options';
|
|
7
7
|
import { resolveSource } from './utils/resolveSource';
|
|
8
|
+
export const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';
|
|
9
|
+
export const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';
|
|
10
|
+
export const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';
|
|
8
11
|
export function useAudioPlayer(source = null, updateInterval = 500) {
|
|
9
12
|
const parsedSource = resolveSource(source);
|
|
10
|
-
|
|
11
|
-
return player;
|
|
13
|
+
return useReleasingSharedObject(() => new AudioModule.AudioPlayer(parsedSource, updateInterval), [JSON.stringify(parsedSource)]);
|
|
12
14
|
}
|
|
13
15
|
export function useAudioPlayerStatus(player) {
|
|
14
16
|
const currentStatus = useMemo(() => player.currentStatus, [player.id]);
|
|
15
|
-
return useEvent(player,
|
|
17
|
+
return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);
|
|
16
18
|
}
|
|
17
19
|
export function useAudioSampleListener(player, listener) {
|
|
18
20
|
player.setAudioSamplingEnabled(true);
|
|
@@ -20,7 +22,7 @@ export function useAudioSampleListener(player, listener) {
|
|
|
20
22
|
if (!player.isAudioSamplingSupported) {
|
|
21
23
|
return;
|
|
22
24
|
}
|
|
23
|
-
const subscription = player.addListener(
|
|
25
|
+
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
24
26
|
return () => {
|
|
25
27
|
subscription.remove();
|
|
26
28
|
};
|
|
@@ -32,7 +34,7 @@ export function useAudioRecorder(options, statusListener) {
|
|
|
32
34
|
return new AudioModule.AudioRecorder(platformOptions);
|
|
33
35
|
}, [JSON.stringify(platformOptions)]);
|
|
34
36
|
useEffect(() => {
|
|
35
|
-
const subscription = recorder.addListener(
|
|
37
|
+
const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {
|
|
36
38
|
statusListener?.(status);
|
|
37
39
|
});
|
|
38
40
|
return () => subscription.remove();
|
package/build/ExpoAudio.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAUrD,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,UAAU,cAAc,CAC5B,SAA+C,IAAI,EACnD,iBAAyB,GAAG;IAE5B,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,
|
|
1
|
+
{"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEvent } from 'expo';\nimport { useReleasingSharedObject } from 'expo-modules-core';\nimport { useEffect, useState, useMemo } from 'react';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n RecorderState,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\nimport AudioModule from './AudioModule';\nimport { AudioPlayer, AudioRecorder } from './AudioModule.types';\nimport { createRecordingOptions } from './utils/options';\nimport { resolveSource } from './utils/resolveSource';\n\nexport const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';\nexport const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';\nexport const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';\n\nexport function useAudioPlayer(\n source: AudioSource | string | number | null = null,\n updateInterval: number = 500\n): AudioPlayer {\n const parsedSource = resolveSource(source);\n return useReleasingSharedObject(\n () => new AudioModule.AudioPlayer(parsedSource, updateInterval),\n [JSON.stringify(parsedSource)]\n );\n}\n\nexport function useAudioPlayerStatus(player: AudioPlayer): AudioStatus {\n const currentStatus = useMemo(() => player.currentStatus, [player.id]);\n return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);\n}\n\nexport function useAudioSampleListener(\n player: AudioPlayer,\n listener: (data: { channels: { frames: number[] }[]; timestamp: number }) => void\n) {\n player.setAudioSamplingEnabled(true);\n useEffect(() => {\n if (!player.isAudioSamplingSupported) {\n return;\n }\n const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);\n return () => {\n subscription.remove();\n };\n }, [player.id]);\n}\n\nexport function useAudioRecorder(\n options: RecordingOptions,\n statusListener?: (status: RecordingStatus) => void\n): AudioRecorder {\n const platformOptions = createRecordingOptions(options);\n const recorder = useReleasingSharedObject(() => {\n return new AudioModule.AudioRecorder(platformOptions);\n }, [JSON.stringify(platformOptions)]);\n\n useEffect(() => {\n const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {\n statusListener?.(status);\n });\n return () => subscription.remove();\n }, [recorder.id]);\n\n return recorder;\n}\n\nexport function useAudioRecorderState(recorder: AudioRecorder, interval: number = 500) {\n const [state, setState] = useState<RecorderState>(recorder.getStatus());\n\n useEffect(() => {\n const int = setInterval(() => {\n setState(recorder.getStatus());\n }, interval);\n\n return () => clearInterval(int);\n }, [recorder.id]);\n\n return state;\n}\n\nexport async function setIsAudioActiveAsync(active: boolean): Promise<void> {\n return await AudioModule.setIsAudioActiveAsync(active);\n}\n\nexport async function setAudioModeAsync(mode: Partial<AudioMode>): Promise<void> {\n return await AudioModule.setAudioModeAsync(mode);\n}\n\nexport { AudioModule, AudioPlayer, AudioRecorder };\nexport * from './Audio.types';\nexport * from './RecordingConstants';\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpoAudio.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAKjD,wBAAgB,cAAc,CAC5B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,CAAC,cAAc,CAY5B;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,CAAC,cAAc,GAAG,WAAW,CAGpF;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,WAAW,CAAC,cAAc,EAClC,QAAQ,EAAE,CAAC,IAAI,EAAE;IAAE,QAAQ,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KAAK,IAAI,QAUlF;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,gBAAgB,EACzB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,IAAI,GACjD,WAAW,CAAC,gBAAgB,CAiB9B;AAED,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,GAAE,MAAY,iBAYpF;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1E;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAEtE;AAED,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;AACnD,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
|
package/build/ExpoAudio.web.js
CHANGED
|
@@ -2,6 +2,7 @@ import { useEvent } from 'expo';
|
|
|
2
2
|
import { useEffect, useState, useMemo } from 'react';
|
|
3
3
|
import { AudioPlayer, AudioRecorder } from './AudioModule.types';
|
|
4
4
|
import * as AudioModule from './AudioModule.web';
|
|
5
|
+
import { AUDIO_SAMPLE_UPDATE, PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
|
|
5
6
|
import { createRecordingOptions } from './utils/options';
|
|
6
7
|
import { resolveSource } from './utils/resolveSource';
|
|
7
8
|
export function useAudioPlayer(source = null, updateInterval = 500) {
|
|
@@ -14,12 +15,12 @@ export function useAudioPlayer(source = null, updateInterval = 500) {
|
|
|
14
15
|
}
|
|
15
16
|
export function useAudioPlayerStatus(player) {
|
|
16
17
|
const currentStatus = useMemo(() => player.currentStatus, [player.id]);
|
|
17
|
-
return useEvent(player,
|
|
18
|
+
return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);
|
|
18
19
|
}
|
|
19
20
|
export function useAudioSampleListener(player, listener) {
|
|
20
21
|
player.setAudioSamplingEnabled(true);
|
|
21
22
|
useEffect(() => {
|
|
22
|
-
const subscription = player.addListener(
|
|
23
|
+
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
23
24
|
return () => {
|
|
24
25
|
player.setAudioSamplingEnabled(false);
|
|
25
26
|
subscription.remove();
|
|
@@ -32,7 +33,7 @@ export function useAudioRecorder(options, statusListener) {
|
|
|
32
33
|
return new AudioModule.AudioRecorderWeb(platformOptions);
|
|
33
34
|
}, [JSON.stringify(platformOptions)]);
|
|
34
35
|
useEffect(() => {
|
|
35
|
-
const subscription = recorder.addListener(
|
|
36
|
+
const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {
|
|
36
37
|
statusListener?.(status);
|
|
37
38
|
});
|
|
38
39
|
return () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoAudio.web.js","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAUrD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,UAAU,cAAc,CAC5B,SAA+C,IAAI,EACnD,iBAAyB,GAAG;IAE5B,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,IAAI,WAAW,CAAC,cAAc,CAAC,YAAY,EAAE,cAAc,CAAC,EAClE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAC/B,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IAC/B,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAkC;IACrE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACvE,OAAO,QAAQ,CAAC,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoAudio.web.js","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEvent } from 'expo';\nimport { useEffect, useState, useMemo } from 'react';\n\nimport {\n AudioMode,\n AudioSource,\n AudioStatus,\n RecorderState,\n RecordingOptions,\n RecordingStatus,\n} from './Audio.types';\nimport { AudioPlayer, AudioRecorder } from './AudioModule.types';\nimport * as AudioModule from './AudioModule.web';\nimport { AUDIO_SAMPLE_UPDATE, PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';\nimport { createRecordingOptions } from './utils/options';\nimport { resolveSource } from './utils/resolveSource';\n\nexport function useAudioPlayer(\n source: AudioSource | string | number | null = null,\n updateInterval: number = 500\n): AudioModule.AudioPlayerWeb {\n const parsedSource = resolveSource(source);\n const player = useMemo(\n () => new AudioModule.AudioPlayerWeb(parsedSource, updateInterval),\n [JSON.stringify(parsedSource)]\n );\n\n useEffect(() => {\n return () => player.remove();\n }, []);\n\n return player;\n}\n\nexport function useAudioPlayerStatus(player: AudioModule.AudioPlayerWeb): AudioStatus {\n const currentStatus = useMemo(() => player.currentStatus, [player.id]);\n return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);\n}\n\nexport function useAudioSampleListener(\n player: AudioModule.AudioPlayerWeb,\n listener: (data: { channels: { frames: number[] }[]; timestamp: number }) => void\n) {\n player.setAudioSamplingEnabled(true);\n useEffect(() => {\n const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);\n return () => {\n player.setAudioSamplingEnabled(false);\n subscription.remove();\n };\n }, [player.id]);\n}\n\nexport function useAudioRecorder(\n options: RecordingOptions,\n statusListener?: (status: RecordingStatus) => void\n): AudioModule.AudioRecorderWeb {\n const platformOptions = createRecordingOptions(options);\n const recorder = useMemo(() => {\n return new AudioModule.AudioRecorderWeb(platformOptions);\n }, [JSON.stringify(platformOptions)]);\n\n useEffect(() => {\n const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {\n statusListener?.(status);\n });\n return () => {\n recorder.clearTimeouts();\n subscription.remove();\n };\n }, [recorder.id]);\n\n return recorder;\n}\n\nexport function useAudioRecorderState(recorder: AudioRecorder, interval: number = 500) {\n const [state, setState] = useState<RecorderState>(recorder.getStatus());\n\n useEffect(() => {\n const id = setInterval(() => {\n setState(recorder.getStatus());\n }, interval);\n\n return () => clearInterval(id);\n }, [recorder.id]);\n\n return state;\n}\n\nexport async function setIsAudioActiveAsync(active: boolean): Promise<void> {\n return await AudioModule.setIsAudioActiveAsync(active);\n}\n\nexport async function setAudioModeAsync(mode: AudioMode): Promise<void> {\n return await AudioModule.setAudioModeAsync(mode);\n}\n\nexport { AudioModule, AudioPlayer, AudioRecorder };\nexport * from './Audio.types';\nexport * from './RecordingConstants';\n"]}
|
package/build/utils/options.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import { Platform } from 'expo-modules-core';
|
|
2
2
|
export function createRecordingOptions(options) {
|
|
3
|
-
let
|
|
3
|
+
let commonOptions = {
|
|
4
4
|
extension: options.extension,
|
|
5
5
|
sampleRate: options.sampleRate,
|
|
6
6
|
numberOfChannels: options.numberOfChannels,
|
|
7
7
|
bitRate: options.bitRate,
|
|
8
8
|
};
|
|
9
9
|
if (Platform.OS === 'ios') {
|
|
10
|
-
|
|
11
|
-
...
|
|
10
|
+
commonOptions = {
|
|
11
|
+
...commonOptions,
|
|
12
12
|
...options.ios,
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
else if (Platform.OS === 'android') {
|
|
16
|
-
|
|
17
|
-
...
|
|
16
|
+
commonOptions = {
|
|
17
|
+
...commonOptions,
|
|
18
18
|
...options.android,
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
return
|
|
21
|
+
return commonOptions;
|
|
22
22
|
}
|
|
23
23
|
//# sourceMappingURL=options.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI7C,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,IAAI,
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/utils/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAI7C,MAAM,UAAU,sBAAsB,CAAC,OAAyB;IAC9D,IAAI,aAAa,GAAG;QAClB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;IAEF,IAAI,QAAQ,CAAC,EAAE,KAAK,KAAK,EAAE;QACzB,aAAa,GAAG;YACd,GAAG,aAAa;YAChB,GAAG,OAAO,CAAC,GAAG;SACf,CAAC;KACH;SAAM,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,EAAE;QACpC,aAAa,GAAG;YACd,GAAG,aAAa;YAChB,GAAG,OAAO,CAAC,OAAO;SACnB,CAAC;KACH;IACD,OAAO,aAAa,CAAC;AACvB,CAAC","sourcesContent":["import { Platform } from 'expo-modules-core';\n\nimport { RecordingOptions } from '../Audio.types';\n\nexport function createRecordingOptions(options: RecordingOptions) {\n let commonOptions = {\n extension: options.extension,\n sampleRate: options.sampleRate,\n numberOfChannels: options.numberOfChannels,\n bitRate: options.bitRate,\n };\n\n if (Platform.OS === 'ios') {\n commonOptions = {\n ...commonOptions,\n ...options.ios,\n };\n } else if (Platform.OS === 'android') {\n commonOptions = {\n ...commonOptions,\n ...options.android,\n };\n }\n return commonOptions;\n}\n"]}
|
package/ios/AudioModule.swift
CHANGED
|
@@ -165,10 +165,8 @@ public class AudioModule: Module {
|
|
|
165
165
|
// swiftlint:disable:next closure_body_length
|
|
166
166
|
Class(AudioRecorder.self) {
|
|
167
167
|
Constructor { (options: RecordingOptions) -> AudioRecorder in
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
let avRecorder = AudioUtils.createRecorder(directory: directory, with: options)
|
|
168
|
+
let recordingDir = try recordingDirectory()
|
|
169
|
+
let avRecorder = AudioUtils.createRecorder(directory: recordingDir, with: options)
|
|
172
170
|
let recorder = AudioRecorder(avRecorder)
|
|
173
171
|
AudioComponentRegistry.shared.add(recorder)
|
|
174
172
|
|
|
@@ -191,26 +189,23 @@ public class AudioModule: Module {
|
|
|
191
189
|
recorder.uri
|
|
192
190
|
}
|
|
193
191
|
|
|
192
|
+
AsyncFunction("prepareToRecordAsync") { (recorder, options: RecordingOptions?) in
|
|
193
|
+
recorder.prepare(options: options)
|
|
194
|
+
}
|
|
195
|
+
|
|
194
196
|
Function("record") { (recorder: AudioRecorder) -> [String: Any] in
|
|
195
197
|
try checkPermissions()
|
|
196
|
-
recorder.
|
|
197
|
-
recorder.startTimestamp = Int(recorder.deviceCurrentTime)
|
|
198
|
-
return recorder.getRecordingStatus()
|
|
198
|
+
return recorder.startRecording()
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
Function("pause") { recorder in
|
|
202
202
|
try checkPermissions()
|
|
203
|
-
recorder.
|
|
204
|
-
let current = recorder.deviceCurrentTime
|
|
205
|
-
recorder.previousRecordingDuration += (current - recorder.startTimestamp)
|
|
206
|
-
recorder.startTimestamp = 0
|
|
203
|
+
recorder.pauseRecording()
|
|
207
204
|
}
|
|
208
205
|
|
|
209
|
-
|
|
206
|
+
AsyncFunction("stop") { recorder in
|
|
210
207
|
try checkPermissions()
|
|
211
|
-
recorder.
|
|
212
|
-
recorder.startTimestamp = 0
|
|
213
|
-
recorder.previousRecordingDuration = 0
|
|
208
|
+
recorder.stopRecording()
|
|
214
209
|
}
|
|
215
210
|
|
|
216
211
|
Function("getStatus") { recorder -> [String: Any] in
|
|
@@ -241,6 +236,13 @@ public class AudioModule: Module {
|
|
|
241
236
|
}
|
|
242
237
|
}
|
|
243
238
|
|
|
239
|
+
private func recordingDirectory() throws -> URL {
|
|
240
|
+
guard let cachesDir = appContext?.fileSystem?.cachesDirectory, let directory = URL(string: cachesDir) else {
|
|
241
|
+
throw Exceptions.AppContextLost()
|
|
242
|
+
}
|
|
243
|
+
return directory
|
|
244
|
+
}
|
|
245
|
+
|
|
244
246
|
private func setIsAudioActive(_ isActive: Bool) throws {
|
|
245
247
|
if !isActive {
|
|
246
248
|
for player in AudioComponentRegistry.shared.players.values {
|
|
@@ -265,6 +267,7 @@ public class AudioModule: Module {
|
|
|
265
267
|
AudioComponentRegistry.shared.recorders.values.forEach { recorder in
|
|
266
268
|
if recorder.isRecording {
|
|
267
269
|
recorder.ref.stop()
|
|
270
|
+
recorder.allowsRecording = false
|
|
268
271
|
}
|
|
269
272
|
}
|
|
270
273
|
}
|
package/ios/AudioPlayer.swift
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
2
|
import Combine
|
|
3
3
|
|
|
4
|
-
private
|
|
5
|
-
|
|
4
|
+
private enum AudioConstants {
|
|
5
|
+
static let playbackStatus = "playbackStatusUpdate"
|
|
6
|
+
static let audioSample = "audioSampleUpdate"
|
|
7
|
+
}
|
|
6
8
|
|
|
7
9
|
public class AudioPlayer: SharedRef<AVPlayer> {
|
|
8
10
|
let id = UUID().uuidString
|
|
@@ -21,6 +23,10 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
21
23
|
private var samplingEnabled = false
|
|
22
24
|
private var tapInstalled = false
|
|
23
25
|
|
|
26
|
+
private var duration: Double {
|
|
27
|
+
(ref.currentItem?.duration.seconds ?? 0.0) * 1000
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
init(_ ref: AVPlayer, interval: Double) {
|
|
25
31
|
self.interval = interval
|
|
26
32
|
super.init(ref)
|
|
@@ -56,8 +62,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
func currentStatus() -> [String: Any] {
|
|
59
|
-
let
|
|
60
|
-
let duration = ref.status == .readyToPlay ? (time?.seconds ?? 0.0) : 0.0
|
|
65
|
+
let duration = ref.status == .readyToPlay ? duration : 0.0
|
|
61
66
|
return [
|
|
62
67
|
"id": id,
|
|
63
68
|
"currentTime": (ref.currentItem?.currentTime().seconds ?? 0) * 1000,
|
|
@@ -65,7 +70,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
65
70
|
"timeControlStatus": timeControlStatusString(status: ref.timeControlStatus),
|
|
66
71
|
"reasonForWaitingToPlay": reasonForWaitingToPlayString(status: ref.reasonForWaitingToPlay),
|
|
67
72
|
"mute": ref.isMuted,
|
|
68
|
-
"duration": duration
|
|
73
|
+
"duration": duration,
|
|
69
74
|
"playing": ref.timeControlStatus == .playing,
|
|
70
75
|
"loop": isLooping,
|
|
71
76
|
"isLoaded": ref.currentItem?.status == .readyToPlay,
|
|
@@ -76,11 +81,11 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
76
81
|
}
|
|
77
82
|
|
|
78
83
|
func updateStatus(with dict: [String: Any]) {
|
|
79
|
-
var
|
|
80
|
-
|
|
84
|
+
var arguments = currentStatus()
|
|
85
|
+
arguments.merge(dict) { _, new in
|
|
81
86
|
new
|
|
82
87
|
}
|
|
83
|
-
self.emit(event: playbackStatus, arguments:
|
|
88
|
+
self.emit(event: AudioConstants.playbackStatus, arguments: arguments)
|
|
84
89
|
}
|
|
85
90
|
|
|
86
91
|
private func setupPublisher() {
|
|
@@ -99,9 +104,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
99
104
|
}
|
|
100
105
|
|
|
101
106
|
private func playerIsBuffering() -> Bool {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if isPlaying {
|
|
107
|
+
if ref.timeControlStatus == .playing {
|
|
105
108
|
return false
|
|
106
109
|
}
|
|
107
110
|
|
|
@@ -137,7 +140,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
137
140
|
return ["frames": channelData]
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
self.emit(event: audioSample, arguments: [
|
|
143
|
+
self.emit(event: AudioConstants.audioSample, arguments: [
|
|
141
144
|
"channels": channels,
|
|
142
145
|
"timestamp": timestamp
|
|
143
146
|
])
|
|
@@ -165,7 +168,8 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
165
168
|
self.ref.play()
|
|
166
169
|
} else {
|
|
167
170
|
self.updateStatus(with: [
|
|
168
|
-
"isPlaying": false
|
|
171
|
+
"isPlaying": false,
|
|
172
|
+
"currentTime": self.duration
|
|
169
173
|
])
|
|
170
174
|
}
|
|
171
175
|
}
|
|
@@ -176,7 +180,7 @@ public class AudioPlayer: SharedRef<AVPlayer> {
|
|
|
176
180
|
let interval = CMTime(seconds: updateInterval, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
|
|
177
181
|
timeToken = ref.addPeriodicTimeObserver(forInterval: interval, queue: nil) { time in
|
|
178
182
|
self.updateStatus(with: [
|
|
179
|
-
"
|
|
183
|
+
"currentTime": time.seconds * 1000
|
|
180
184
|
])
|
|
181
185
|
}
|
|
182
186
|
}
|
package/ios/AudioRecorder.swift
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import ExpoModulesCore
|
|
2
2
|
|
|
3
|
-
private let recordingStatus = "
|
|
3
|
+
private let recordingStatus = "recordingStatusUpdate"
|
|
4
4
|
|
|
5
5
|
class AudioRecorder: SharedRef<AVAudioRecorder>, RecordingResultHandler {
|
|
6
6
|
let id = UUID().uuidString
|
|
7
7
|
private lazy var recordingDelegate = {
|
|
8
8
|
RecordingDelegate(resultHandler: self)
|
|
9
9
|
}()
|
|
10
|
-
var startTimestamp = 0
|
|
11
|
-
var previousRecordingDuration = 0
|
|
10
|
+
private var startTimestamp = 0
|
|
11
|
+
private var previousRecordingDuration = 0
|
|
12
|
+
private var isPrepared = false
|
|
13
|
+
private lazy var recordingSession = AVAudioSession.sharedInstance()
|
|
14
|
+
var allowsRecording = true
|
|
12
15
|
|
|
13
|
-
override init(_
|
|
14
|
-
super.init(
|
|
15
|
-
|
|
16
|
+
override init(_ ref: AVAudioRecorder) {
|
|
17
|
+
super.init(ref)
|
|
18
|
+
ref.delegate = recordingDelegate
|
|
16
19
|
|
|
17
20
|
do {
|
|
18
|
-
try
|
|
21
|
+
try recordingSession.setCategory(.playAndRecord, mode: .default)
|
|
22
|
+
try recordingSession.setActive(true)
|
|
19
23
|
} catch {
|
|
20
|
-
|
|
24
|
+
log.info("Failed to update the recording session")
|
|
21
25
|
}
|
|
22
|
-
ref.prepareToRecord()
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
var isRecording: Bool {
|
|
@@ -38,12 +41,48 @@ class AudioRecorder: SharedRef<AVAudioRecorder>, RecordingResultHandler {
|
|
|
38
41
|
ref.url.absoluteString
|
|
39
42
|
}
|
|
40
43
|
|
|
44
|
+
private var currentDuration: Int {
|
|
45
|
+
deviceCurrentTime - startTimestamp
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func prepare(options: RecordingOptions?) {
|
|
49
|
+
if let options {
|
|
50
|
+
ref = AudioUtils.createRecorder(directory: recordingDirectory, with: options)
|
|
51
|
+
ref.delegate = recordingDelegate
|
|
52
|
+
}
|
|
53
|
+
ref.prepareToRecord()
|
|
54
|
+
isPrepared = true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func startRecording() -> [String: Any] {
|
|
58
|
+
if !allowsRecording {
|
|
59
|
+
log.info("Recording is currently disabled")
|
|
60
|
+
return [:]
|
|
61
|
+
}
|
|
62
|
+
ref.record()
|
|
63
|
+
startTimestamp = Int(deviceCurrentTime)
|
|
64
|
+
return getRecordingStatus()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
func stopRecording() {
|
|
68
|
+
ref.stop()
|
|
69
|
+
startTimestamp = 0
|
|
70
|
+
previousRecordingDuration = 0
|
|
71
|
+
isPrepared = false
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func pauseRecording() {
|
|
75
|
+
ref.pause()
|
|
76
|
+
previousRecordingDuration += currentDuration
|
|
77
|
+
startTimestamp = 0
|
|
78
|
+
}
|
|
79
|
+
|
|
41
80
|
func getRecordingStatus() -> [String: Any] {
|
|
42
|
-
let currentDuration = isRecording ?
|
|
81
|
+
let currentDuration = isRecording ? currentDuration : 0
|
|
43
82
|
let duration = previousRecordingDuration + Int(currentDuration)
|
|
44
83
|
|
|
45
84
|
var result: [String: Any] = [
|
|
46
|
-
"canRecord":
|
|
85
|
+
"canRecord": isPrepared,
|
|
47
86
|
"isRecording": isRecording,
|
|
48
87
|
"durationMillis": duration,
|
|
49
88
|
"mediaServicesDidReset": false,
|
|
@@ -79,6 +118,13 @@ class AudioRecorder: SharedRef<AVAudioRecorder>, RecordingResultHandler {
|
|
|
79
118
|
])
|
|
80
119
|
}
|
|
81
120
|
|
|
121
|
+
private var recordingDirectory: URL? {
|
|
122
|
+
guard let cachesDir = appContext?.fileSystem?.cachesDirectory, let directory = URL(string: cachesDir) else {
|
|
123
|
+
return nil
|
|
124
|
+
}
|
|
125
|
+
return directory
|
|
126
|
+
}
|
|
127
|
+
|
|
82
128
|
override func sharedObjectWillRelease() {
|
|
83
129
|
AudioComponentRegistry.shared.remove(self)
|
|
84
130
|
ref.stop()
|
package/ios/AudioRecords.swift
CHANGED
|
@@ -32,11 +32,11 @@ enum PitchCorrectionQuality: String, Enumerable {
|
|
|
32
32
|
|
|
33
33
|
struct RecordingOptions: Record {
|
|
34
34
|
@Field var `extension`: String
|
|
35
|
-
@Field var outputFormat: String?
|
|
36
|
-
@Field var audioQuality: Int
|
|
37
35
|
@Field var sampleRate: Double
|
|
38
36
|
@Field var numberOfChannels: Double
|
|
39
37
|
@Field var bitRate: Double
|
|
38
|
+
@Field var outputFormat: String?
|
|
39
|
+
@Field var audioQuality: Int
|
|
40
40
|
@Field var bitRateStrategy: BitRateStrategy?
|
|
41
41
|
@Field var bitDepthHint: Double?
|
|
42
42
|
@Field var linearPCMBitDepth: Double?
|
package/ios/AudioUtils.swift
CHANGED
|
@@ -73,7 +73,7 @@ struct AudioUtils {
|
|
|
73
73
|
if let directory {
|
|
74
74
|
let fileUrl = createRecordingUrl(from: directory, with: options)
|
|
75
75
|
do {
|
|
76
|
-
return try AVAudioRecorder(url: fileUrl, settings: AudioUtils.
|
|
76
|
+
return try AVAudioRecorder(url: fileUrl, settings: AudioUtils.createRecordingOptions(options))
|
|
77
77
|
} catch {
|
|
78
78
|
return AVAudioRecorder()
|
|
79
79
|
}
|
|
@@ -90,7 +90,7 @@ struct AudioUtils {
|
|
|
90
90
|
return AVPlayer()
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
static func
|
|
93
|
+
static func createRecordingOptions(_ options: RecordingOptions) -> [String: Any] {
|
|
94
94
|
let strategy = options.bitRateStrategy?.toAVBitRateStrategy() ?? AVAudioBitRateStrategy_Variable
|
|
95
95
|
|
|
96
96
|
var settings = [String: Any]()
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-audio",
|
|
3
3
|
"title": "Expo Audio",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "A cross-platform audio library for React Native and Expo apps.",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"types": "build/index.d.ts",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"react": "*",
|
|
41
41
|
"react-native": "*"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "0a07b965c4bef67e7718355a0dc770d524ad3cee"
|
|
44
44
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("expo/config-plugins");
|
|
4
|
+
const pkg = require('expo-audio/package.json');
|
|
5
|
+
const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone';
|
|
6
|
+
const withAudio = (config, { microphonePermission } = {}) => {
|
|
7
|
+
config_plugins_1.IOSConfig.Permissions.createPermissionsPlugin({
|
|
8
|
+
NSMicrophoneUsageDescription: MICROPHONE_USAGE,
|
|
9
|
+
})(config, {
|
|
10
|
+
NSMicrophoneUsageDescription: microphonePermission,
|
|
11
|
+
});
|
|
12
|
+
return config_plugins_1.AndroidConfig.Permissions.withPermissions(config, [
|
|
13
|
+
microphonePermission !== false && 'android.permission.RECORD_AUDIO',
|
|
14
|
+
'android.permission.MODIFY_AUDIO_SETTINGS',
|
|
15
|
+
].filter(Boolean));
|
|
16
|
+
};
|
|
17
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withAudio, pkg.name, pkg.version);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { AndroidConfig, ConfigPlugin, IOSConfig, createRunOncePlugin } from 'expo/config-plugins';
|
|
2
|
+
|
|
3
|
+
const pkg = require('expo-audio/package.json');
|
|
4
|
+
|
|
5
|
+
const MICROPHONE_USAGE = 'Allow $(PRODUCT_NAME) to access your microphone';
|
|
6
|
+
|
|
7
|
+
const withAudio: ConfigPlugin<{ microphonePermission?: string | false } | void> = (
|
|
8
|
+
config,
|
|
9
|
+
{ microphonePermission } = {}
|
|
10
|
+
) => {
|
|
11
|
+
IOSConfig.Permissions.createPermissionsPlugin({
|
|
12
|
+
NSMicrophoneUsageDescription: MICROPHONE_USAGE,
|
|
13
|
+
})(config, {
|
|
14
|
+
NSMicrophoneUsageDescription: microphonePermission,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return AndroidConfig.Permissions.withPermissions(
|
|
18
|
+
config,
|
|
19
|
+
[
|
|
20
|
+
microphonePermission !== false && 'android.permission.RECORD_AUDIO',
|
|
21
|
+
'android.permission.MODIFY_AUDIO_SETTINGS',
|
|
22
|
+
].filter(Boolean) as string[]
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default createRunOncePlugin(withAudio, pkg.name, pkg.version);
|
package/src/AudioModule.types.ts
CHANGED
|
@@ -142,8 +142,8 @@ type AudioSample = {
|
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
export type AudioEvents = {
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
playbackStatusUpdate(status: AudioStatus): void;
|
|
146
|
+
audioSampleUpdate(data: AudioSample): void;
|
|
147
147
|
};
|
|
148
148
|
|
|
149
149
|
export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
@@ -221,7 +221,7 @@ export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
|
221
221
|
/**
|
|
222
222
|
* Prepares the recording for recording.
|
|
223
223
|
*/
|
|
224
|
-
prepareToRecordAsync(options?: RecordingOptions): Promise<void>;
|
|
224
|
+
prepareToRecordAsync(options?: Partial<RecordingOptions>): Promise<void>;
|
|
225
225
|
|
|
226
226
|
/**
|
|
227
227
|
* Stops the recording once the specified time has elapsed.
|
|
@@ -231,5 +231,5 @@ export declare class AudioRecorder extends SharedObject<RecordingEvents> {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
export type RecordingEvents = {
|
|
234
|
-
|
|
234
|
+
recordingStatusUpdate: (status: RecordingStatus) => void;
|
|
235
235
|
};
|
package/src/AudioModule.web.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
RecordingOptions,
|
|
11
11
|
} from './Audio.types';
|
|
12
12
|
import { AudioPlayer, AudioEvents, RecordingEvents, AudioRecorder } from './AudioModule.types';
|
|
13
|
+
import { PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
|
|
13
14
|
import { RecordingPresets } from './RecordingConstants';
|
|
14
15
|
|
|
15
16
|
const nextId = (() => {
|
|
@@ -207,12 +208,12 @@ export class AudioPlayerWeb
|
|
|
207
208
|
const media = new Audio(newSource);
|
|
208
209
|
|
|
209
210
|
media.ontimeupdate = () => {
|
|
210
|
-
this.emit(
|
|
211
|
+
this.emit(PLAYBACK_STATUS_UPDATE, getStatusFromMedia(media, this.id));
|
|
211
212
|
};
|
|
212
213
|
|
|
213
214
|
media.onloadeddata = () => {
|
|
214
215
|
this.loaded = true;
|
|
215
|
-
this.emit(
|
|
216
|
+
this.emit(PLAYBACK_STATUS_UPDATE, {
|
|
216
217
|
...getStatusFromMedia(media, this.id),
|
|
217
218
|
isLoaded: this.loaded,
|
|
218
219
|
});
|
|
@@ -338,7 +339,7 @@ export class AudioRecorderWeb
|
|
|
338
339
|
|
|
339
340
|
this.uri = url;
|
|
340
341
|
|
|
341
|
-
this.emit(
|
|
342
|
+
this.emit(RECORDING_STATUS_UPDATE, {
|
|
342
343
|
id: this.id,
|
|
343
344
|
isFinished: true,
|
|
344
345
|
hasError: false,
|
package/src/ExpoAudio.ts
CHANGED
|
@@ -15,22 +15,24 @@ import { AudioPlayer, AudioRecorder } from './AudioModule.types';
|
|
|
15
15
|
import { createRecordingOptions } from './utils/options';
|
|
16
16
|
import { resolveSource } from './utils/resolveSource';
|
|
17
17
|
|
|
18
|
+
export const PLAYBACK_STATUS_UPDATE = 'playbackStatusUpdate';
|
|
19
|
+
export const AUDIO_SAMPLE_UPDATE = 'audioSampleUpdate';
|
|
20
|
+
export const RECORDING_STATUS_UPDATE = 'recordingStatusUpdate';
|
|
21
|
+
|
|
18
22
|
export function useAudioPlayer(
|
|
19
23
|
source: AudioSource | string | number | null = null,
|
|
20
24
|
updateInterval: number = 500
|
|
21
25
|
): AudioPlayer {
|
|
22
26
|
const parsedSource = resolveSource(source);
|
|
23
|
-
|
|
27
|
+
return useReleasingSharedObject(
|
|
24
28
|
() => new AudioModule.AudioPlayer(parsedSource, updateInterval),
|
|
25
29
|
[JSON.stringify(parsedSource)]
|
|
26
30
|
);
|
|
27
|
-
|
|
28
|
-
return player;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export function useAudioPlayerStatus(player: AudioPlayer): AudioStatus {
|
|
32
34
|
const currentStatus = useMemo(() => player.currentStatus, [player.id]);
|
|
33
|
-
return useEvent(player,
|
|
35
|
+
return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export function useAudioSampleListener(
|
|
@@ -42,7 +44,7 @@ export function useAudioSampleListener(
|
|
|
42
44
|
if (!player.isAudioSamplingSupported) {
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
45
|
-
const subscription = player.addListener(
|
|
47
|
+
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
46
48
|
return () => {
|
|
47
49
|
subscription.remove();
|
|
48
50
|
};
|
|
@@ -59,7 +61,7 @@ export function useAudioRecorder(
|
|
|
59
61
|
}, [JSON.stringify(platformOptions)]);
|
|
60
62
|
|
|
61
63
|
useEffect(() => {
|
|
62
|
-
const subscription = recorder.addListener(
|
|
64
|
+
const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {
|
|
63
65
|
statusListener?.(status);
|
|
64
66
|
});
|
|
65
67
|
return () => subscription.remove();
|
package/src/ExpoAudio.web.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from './Audio.types';
|
|
12
12
|
import { AudioPlayer, AudioRecorder } from './AudioModule.types';
|
|
13
13
|
import * as AudioModule from './AudioModule.web';
|
|
14
|
+
import { AUDIO_SAMPLE_UPDATE, PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
|
|
14
15
|
import { createRecordingOptions } from './utils/options';
|
|
15
16
|
import { resolveSource } from './utils/resolveSource';
|
|
16
17
|
|
|
@@ -33,7 +34,7 @@ export function useAudioPlayer(
|
|
|
33
34
|
|
|
34
35
|
export function useAudioPlayerStatus(player: AudioModule.AudioPlayerWeb): AudioStatus {
|
|
35
36
|
const currentStatus = useMemo(() => player.currentStatus, [player.id]);
|
|
36
|
-
return useEvent(player,
|
|
37
|
+
return useEvent(player, PLAYBACK_STATUS_UPDATE, currentStatus);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function useAudioSampleListener(
|
|
@@ -42,7 +43,7 @@ export function useAudioSampleListener(
|
|
|
42
43
|
) {
|
|
43
44
|
player.setAudioSamplingEnabled(true);
|
|
44
45
|
useEffect(() => {
|
|
45
|
-
const subscription = player.addListener(
|
|
46
|
+
const subscription = player.addListener(AUDIO_SAMPLE_UPDATE, listener);
|
|
46
47
|
return () => {
|
|
47
48
|
player.setAudioSamplingEnabled(false);
|
|
48
49
|
subscription.remove();
|
|
@@ -60,7 +61,7 @@ export function useAudioRecorder(
|
|
|
60
61
|
}, [JSON.stringify(platformOptions)]);
|
|
61
62
|
|
|
62
63
|
useEffect(() => {
|
|
63
|
-
const subscription = recorder.addListener(
|
|
64
|
+
const subscription = recorder.addListener(RECORDING_STATUS_UPDATE, (status) => {
|
|
64
65
|
statusListener?.(status);
|
|
65
66
|
});
|
|
66
67
|
return () => {
|
package/src/utils/options.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Platform } from 'expo-modules-core';
|
|
|
3
3
|
import { RecordingOptions } from '../Audio.types';
|
|
4
4
|
|
|
5
5
|
export function createRecordingOptions(options: RecordingOptions) {
|
|
6
|
-
let
|
|
6
|
+
let commonOptions = {
|
|
7
7
|
extension: options.extension,
|
|
8
8
|
sampleRate: options.sampleRate,
|
|
9
9
|
numberOfChannels: options.numberOfChannels,
|
|
@@ -11,15 +11,15 @@ export function createRecordingOptions(options: RecordingOptions) {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
if (Platform.OS === 'ios') {
|
|
14
|
-
|
|
15
|
-
...
|
|
14
|
+
commonOptions = {
|
|
15
|
+
...commonOptions,
|
|
16
16
|
...options.ios,
|
|
17
17
|
};
|
|
18
18
|
} else if (Platform.OS === 'android') {
|
|
19
|
-
|
|
20
|
-
...
|
|
19
|
+
commonOptions = {
|
|
20
|
+
...commonOptions,
|
|
21
21
|
...options.android,
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
|
-
return
|
|
24
|
+
return commonOptions;
|
|
25
25
|
}
|