expo-audio 0.2.3 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,22 @@
10
10
 
11
11
  ### 💡 Others
12
12
 
13
+ ## 0.3.0 — 2024-12-02
14
+
15
+ ### 🎉 New features
16
+
17
+ - Support creating an `AudioPlayer` instance without using the `useAudioPlayer` hook. ([#33331](https://github.com/expo/expo/pull/33331) by [@alanjhughes](https://github.com/alanjhughes))
18
+
19
+ ## 0.2.4 — 2024-11-19
20
+
21
+ ### 🎉 New features
22
+
23
+ - Add support for replacing the auido source without recreating the player. ([#32981](https://github.com/expo/expo/pull/32981) by [@alanjhughes](https://github.com/alanjhughes))
24
+
25
+ ### 💡 Others
26
+
27
+ - [Android] Imporve handling of `Visulaizer`. ([#33018](https://github.com/expo/expo/pull/33018) by [@alanjhughes](https://github.com/alanjhughes))
28
+
13
29
  ## 0.2.3 — 2024-10-28
14
30
 
15
31
  _This version does not introduce any user-facing changes._
@@ -1,7 +1,7 @@
1
1
  apply plugin: 'com.android.library'
2
2
 
3
3
  group = 'expo.modules.audio'
4
- version = '0.2.3'
4
+ version = '0.3.0'
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.3"
17
+ versionName "0.3.0"
18
18
  }
19
19
 
20
20
  compileOptions {
@@ -27,6 +27,7 @@ repositories {
27
27
  }
28
28
 
29
29
  dependencies {
30
+ implementation 'androidx.appcompat:appcompat:1.7.0'
30
31
  implementation("androidx.media3:media3-exoplayer:1.4.0")
31
32
  implementation("androidx.media3:media3-exoplayer-dash:1.4.0")
32
33
  implementation("androidx.media3:media3-datasource-okhttp:1.4.0")
@@ -128,31 +128,20 @@ class AudioModule : Module() {
128
128
  }
129
129
 
130
130
  OnDestroy {
131
- for (player in players.values) {
132
- player.player.stop()
133
- }
131
+ appContext.mainQueue.launch {
132
+ for (player in players.values) {
133
+ player.player.stop()
134
+ }
134
135
 
135
- for (recorder in recorders.values) {
136
- recorder.stopRecording()
136
+ for (recorder in recorders.values) {
137
+ recorder.stopRecording()
138
+ }
137
139
  }
138
140
  }
139
141
 
140
142
  Class(AudioPlayer::class) {
141
143
  Constructor { source: AudioSource?, updateInterval: Double ->
142
- val isLocal = Util.isLocalFileUri(Uri.parse(source?.uri))
143
- val factory = if (isLocal) {
144
- DefaultDataSource.Factory(context)
145
- } else {
146
- OkHttpDataSource.Factory(httpClient).apply {
147
- source?.headers?.let {
148
- setDefaultRequestProperties(it)
149
- }
150
- DefaultDataSource.Factory(context, this)
151
- }
152
- }
153
-
154
- val item = MediaItem.fromUri(source?.uri ?: "")
155
- val mediaSource = buildMediaSourceFactory(factory, item)
144
+ val mediaSource = createMediaItem(source)
156
145
  runOnMain {
157
146
  val player = AudioPlayer(
158
147
  context,
@@ -271,8 +260,17 @@ class AudioModule : Module() {
271
260
  }
272
261
  }
273
262
 
263
+ Function("replace") { ref: AudioPlayer, source: AudioSource ->
264
+ if (ref.player.availableCommands.contains(Player.COMMAND_CHANGE_MEDIA_ITEMS)) {
265
+ val mediaSource = createMediaItem(source)
266
+ ref.player.replaceMediaItem(0, mediaSource.mediaItem)
267
+ }
268
+ }
269
+
274
270
  Function("setAudioSamplingEnabled") { ref: AudioPlayer, enabled: Boolean ->
275
- ref.setSamplingEnabled(enabled)
271
+ appContext.mainQueue.launch {
272
+ ref.setSamplingEnabled(enabled)
273
+ }
276
274
  }
277
275
 
278
276
  AsyncFunction("seekTo") { ref: AudioPlayer, seekTime: Double ->
@@ -357,6 +355,23 @@ class AudioModule : Module() {
357
355
  }
358
356
  }
359
357
 
358
+ private fun createMediaItem(source: AudioSource?): MediaSource {
359
+ val isLocal = Util.isLocalFileUri(Uri.parse(source?.uri))
360
+ val factory = if (isLocal) {
361
+ DefaultDataSource.Factory(context)
362
+ } else {
363
+ OkHttpDataSource.Factory(httpClient).apply {
364
+ source?.headers?.let {
365
+ setDefaultRequestProperties(it)
366
+ }
367
+ DefaultDataSource.Factory(context, this)
368
+ }
369
+ }
370
+
371
+ val item = MediaItem.fromUri(source?.uri ?: "")
372
+ return buildMediaSourceFactory(factory, item)
373
+ }
374
+
360
375
  private fun updatePlaySoundThroughEarpiece(playThroughEarpiece: Boolean) {
361
376
  audioManager.setMode(if (playThroughEarpiece) AudioManager.MODE_IN_COMMUNICATION else AudioManager.MODE_NORMAL)
362
377
  audioManager.setSpeakerphoneOn(!playThroughEarpiece)
@@ -1,7 +1,11 @@
1
1
  package expo.modules.audio
2
2
 
3
+ import android.Manifest
3
4
  import android.content.Context
5
+ import android.content.pm.PackageManager
4
6
  import android.media.audiofx.Visualizer
7
+ import android.util.Log
8
+ import androidx.core.content.ContextCompat
5
9
  import androidx.media3.common.AudioAttributes
6
10
  import androidx.media3.common.Player
7
11
  import androidx.media3.common.util.UnstableApi
@@ -45,29 +49,7 @@ class AudioPlayer(
45
49
 
46
50
  private var playerScope = CoroutineScope(Dispatchers.Default)
47
51
  private var samplingEnabled = false
48
-
49
- private val visualizer = Visualizer(player.audioSessionId).apply {
50
- captureSize = Visualizer.getCaptureSizeRange()[1]
51
- setDataCaptureListener(
52
- object : Visualizer.OnDataCaptureListener {
53
- override fun onWaveFormDataCapture(visualizer: Visualizer?, waveform: ByteArray?, samplingRate: Int) {
54
- waveform?.let {
55
- if (samplingEnabled) {
56
- val data = extractAmplitudes(it)
57
- sendAudioSampleUpdate(data)
58
- }
59
- }
60
- }
61
-
62
- override fun onFftDataCapture(visualizer: Visualizer?, fft: ByteArray?, samplingRate: Int) {
63
- }
64
- },
65
- Visualizer.getMaxCaptureRate() / 2,
66
- true,
67
- false
68
- )
69
- enabled = true
70
- }
52
+ private var visualizer: Visualizer? = null
71
53
 
72
54
  init {
73
55
  addPlayerListeners()
@@ -104,6 +86,12 @@ class AudioPlayer(
104
86
 
105
87
  fun setSamplingEnabled(enabled: Boolean) {
106
88
  samplingEnabled = enabled
89
+ if (enabled) {
90
+ createVisualizer()
91
+ } else {
92
+ visualizer?.release()
93
+ visualizer = null
94
+ }
107
95
  }
108
96
 
109
97
  private fun extractAmplitudes(chunk: ByteArray): List<Float> = chunk.map { byte ->
@@ -161,11 +149,49 @@ class AudioPlayer(
161
149
  }
162
150
  }
163
151
 
164
- override fun deallocate() {
152
+ private fun createVisualizer() {
153
+ appContext?.reactContext?.let {
154
+ if (ContextCompat.checkSelfPermission(it, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
155
+ Log.d(TAG, "\'android.permission.RECORD_AUDIO\' is required to use audio sampling. Please request this permission and try again.")
156
+ return
157
+ }
158
+ }
159
+
160
+ // It must only be created once, otherwise the app will crash
161
+ if (visualizer == null) {
162
+ visualizer = Visualizer(player.audioSessionId).apply {
163
+ captureSize = Visualizer.getCaptureSizeRange()[1]
164
+ setDataCaptureListener(
165
+ object : Visualizer.OnDataCaptureListener {
166
+ override fun onWaveFormDataCapture(visualizer: Visualizer?, waveform: ByteArray?, samplingRate: Int) {
167
+ waveform?.let {
168
+ if (samplingEnabled) {
169
+ val data = extractAmplitudes(it)
170
+ sendAudioSampleUpdate(data)
171
+ }
172
+ }
173
+ }
174
+
175
+ override fun onFftDataCapture(visualizer: Visualizer?, fft: ByteArray?, samplingRate: Int) = Unit
176
+ },
177
+ Visualizer.getMaxCaptureRate() / 2,
178
+ true,
179
+ false
180
+ )
181
+ enabled = true
182
+ }
183
+ }
184
+ }
185
+
186
+ override fun sharedObjectDidRelease() {
165
187
  appContext?.mainQueue?.launch {
166
188
  playerScope.cancel()
167
- visualizer.release()
189
+ visualizer?.release()
168
190
  player.release()
169
191
  }
170
192
  }
193
+
194
+ companion object {
195
+ val TAG = AudioPlayer::class.simpleName
196
+ }
171
197
  }
@@ -82,6 +82,10 @@ export declare class AudioPlayer extends SharedObject<AudioEvents> {
82
82
  * Pauses the player.
83
83
  */
84
84
  pause(): void;
85
+ /**
86
+ * Replaces the current audio source with a new one.
87
+ */
88
+ replace(source: AudioSource): void;
85
89
  /**
86
90
  * Seeks the playback by the given number of seconds.
87
91
  * @param seconds The number of seconds to seek by.
@@ -1 +1 @@
1
- {"version":3,"file":"AudioModule.types.d.ts","sourceRoot":"","sources":["../src/AudioModule.types.ts"],"names":[],"mappings":"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"}
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\n/**\n * @hidden\n */\nexport declare class NativeAudioModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<PermissionResponse>;\n getRecordingPermissionsAsync(): Promise<PermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\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 * Start playing audio.\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(rate: 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\nexport type AudioSample = {\n channels: AudioSampleChannel[];\n timestamp: number;\n};\n\nexport type AudioSampleChannel = { frames: number[] };\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(inputUid: 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
+ {"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\n/**\n * @hidden\n */\nexport declare class NativeAudioModule {\n setIsAudioActiveAsync(active: boolean): Promise<void>;\n setAudioModeAsync(category: Partial<AudioMode>): Promise<void>;\n requestRecordingPermissionsAsync(): Promise<PermissionResponse>;\n getRecordingPermissionsAsync(): Promise<PermissionResponse>;\n\n readonly AudioPlayer: typeof AudioPlayer;\n readonly AudioRecorder: typeof AudioRecorder;\n}\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 * Start playing audio.\n */\n play(): void;\n\n /**\n * Pauses the player.\n */\n pause(): void;\n\n /**\n * Replaces the current audio source with a new one.\n */\n replace(source: AudioSource): 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(rate: 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\nexport type AudioSample = {\n channels: AudioSampleChannel[];\n timestamp: number;\n};\n\nexport type AudioSampleChannel = { frames: number[] };\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(inputUid: 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"]}
@@ -28,6 +28,7 @@ export declare class AudioPlayerWeb extends globalThis.expo.SharedObject<AudioEv
28
28
  get currentStatus(): AudioStatus;
29
29
  play(): void;
30
30
  pause(): void;
31
+ replace(source: AudioSource): void;
31
32
  seekTo(seconds: number): Promise<void>;
32
33
  setAudioSamplingEnabled(enabled: boolean): void;
33
34
  setPlaybackRate(second: number, pitchCorrectionQuality?: PitchCorrectionQuality): void;
@@ -1 +1 @@
1
- {"version":3,"file":"AudioModule.web.d.ts","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"AudioModule.web.d.ts","sourceRoot":"","sources":["../src/AudioModule.web.ts"],"names":[],"mappings":"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"}
@@ -135,6 +135,10 @@ export class AudioPlayerWeb extends globalThis.expo.SharedObject {
135
135
  this.media.pause();
136
136
  this.isPlaying = false;
137
137
  }
138
+ replace(source) {
139
+ this.src = source;
140
+ this.media = this._createMediaElement();
141
+ }
138
142
  async seekTo(seconds) {
139
143
  this.media.currentTime = seconds / 1000;
140
144
  }
@@ -1 +1 @@
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"]}
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 replace(source: AudioSource): void {\n this.src = source;\n this.media = this._createMediaElement();\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"]}
@@ -10,6 +10,13 @@ export declare function useAudioPlayerStatus(player: AudioPlayer): AudioStatus;
10
10
  export declare function useAudioSampleListener(player: AudioPlayer, listener: (data: AudioSample) => void): void;
11
11
  export declare function useAudioRecorder(options: RecordingOptions, statusListener?: (status: RecordingStatus) => void): AudioRecorder;
12
12
  export declare function useAudioRecorderState(recorder: AudioRecorder, interval?: number): RecorderState;
13
+ /**
14
+ * Creates an instance of an `AudioPlayer` that doesn't release automatically.
15
+ *
16
+ * > **info** For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-updateinterval) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.
17
+ * @param source
18
+ */
19
+ export declare function createAudioPlayer(source?: AudioSource | string | number | null, updateInterval?: number): AudioPlayer;
13
20
  export declare function setIsAudioActiveAsync(active: boolean): Promise<void>;
14
21
  export declare function setAudioModeAsync(mode: Partial<AudioMode>): Promise<void>;
15
22
  export declare function requestRecordingPermissionsAsync(): Promise<PermissionResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AAGjF,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,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI9E,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,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,QAWhG;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,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEpF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEhF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"ExpoAudio.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,mBAAmB,CAAC;AAGjF,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,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAI9E,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,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,QAWhG;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;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,CAGb;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,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEpF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEhF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -50,6 +50,16 @@ export function useAudioRecorderState(recorder, interval = 500) {
50
50
  }, [recorder.id]);
51
51
  return state;
52
52
  }
53
+ /**
54
+ * Creates an instance of an `AudioPlayer` that doesn't release automatically.
55
+ *
56
+ * > **info** For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-updateinterval) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.
57
+ * @param source
58
+ */
59
+ export function createAudioPlayer(source = null, updateInterval = 500) {
60
+ const parsedSource = resolveSource(source);
61
+ return new AudioModule.AudioPlayer(parsedSource, updateInterval);
62
+ }
53
63
  export async function setIsAudioActiveAsync(active) {
54
64
  return await AudioModule.setIsAudioActiveAsync(active);
55
65
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEvent } from 'expo';\nimport { PermissionResponse, 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, AudioSample } 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(player: AudioPlayer, listener: (data: AudioSample) => void) {\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 async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.requestRecordingPermissionsAsync();\n}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.getRecordingPermissionsAsync();\n}\n\nexport { AudioModule };\n"]}
1
+ {"version":3,"file":"ExpoAudio.js","sourceRoot":"","sources":["../src/ExpoAudio.ts"],"names":[],"mappings":"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","sourcesContent":["import { useEvent } from 'expo';\nimport { PermissionResponse, 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, AudioSample } 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(player: AudioPlayer, listener: (data: AudioSample) => void) {\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\n/**\n * Creates an instance of an `AudioPlayer` that doesn't release automatically.\n *\n * > **info** For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-updateinterval) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.\n * @param source\n */\nexport function createAudioPlayer(\n source: AudioSource | string | number | null = null,\n updateInterval: number = 500\n): AudioPlayer {\n const parsedSource = resolveSource(source);\n return new AudioModule.AudioPlayer(parsedSource, updateInterval);\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 async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.requestRecordingPermissionsAsync();\n}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.getRecordingPermissionsAsync();\n}\n\nexport { AudioModule };\n"]}
@@ -1,7 +1,8 @@
1
1
  import { PermissionResponse } from 'expo-modules-core';
2
2
  import { AudioMode, AudioSource, AudioStatus, RecorderState, RecordingOptions, RecordingStatus } from './Audio.types';
3
- import { AudioRecorder, AudioSample } from './AudioModule.types';
3
+ import { AudioPlayer, AudioRecorder, AudioSample } from './AudioModule.types';
4
4
  import * as AudioModule from './AudioModule.web';
5
+ export declare function createAudioPlayer(source?: AudioSource | string | number | null, updateInterval?: number): AudioPlayer;
5
6
  export declare function useAudioPlayer(source?: AudioSource | string | number | null, updateInterval?: number): AudioModule.AudioPlayerWeb;
6
7
  export declare function useAudioPlayerStatus(player: AudioModule.AudioPlayerWeb): AudioStatus;
7
8
  export declare function useAudioSampleListener(player: AudioModule.AudioPlayerWeb, listener: (data: AudioSample) => void): void;
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoAudio.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,WAAW,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,WAAW,KAAK,IAAI,QAUtC;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,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEpF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEhF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"ExpoAudio.web.d.ts","sourceRoot":"","sources":["../src/ExpoAudio.web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EACL,SAAS,EACT,WAAW,EACX,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,KAAK,WAAW,MAAM,mBAAmB,CAAC;AAKjD,wBAAgB,iBAAiB,CAC/B,MAAM,GAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAW,EACnD,cAAc,GAAE,MAAY,GAC3B,WAAW,CAGb;AAED,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,WAAW,KAAK,IAAI,QAUtC;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,wBAAsB,gCAAgC,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEpF;AAED,wBAAsB,4BAA4B,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEhF;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
@@ -4,6 +4,10 @@ import * as AudioModule from './AudioModule.web';
4
4
  import { AUDIO_SAMPLE_UPDATE, PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
5
5
  import { createRecordingOptions } from './utils/options';
6
6
  import { resolveSource } from './utils/resolveSource';
7
+ export function createAudioPlayer(source = null, updateInterval = 500) {
8
+ const parsedSource = resolveSource(source);
9
+ return new AudioModule.AudioPlayerWeb(parsedSource, updateInterval);
10
+ }
7
11
  export function useAudioPlayer(source = null, updateInterval = 500) {
8
12
  const parsedSource = resolveSource(source);
9
13
  const player = useMemo(() => new AudioModule.AudioPlayerWeb(parsedSource, updateInterval), [JSON.stringify(parsedSource)]);
@@ -1 +1 @@
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 { PermissionResponse } 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 { AudioRecorder, AudioSample } 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: AudioSample) => 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 async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.requestRecordingPermissionsAsync();\n}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.getRecordingPermissionsAsync();\n}\n\nexport { AudioModule };\n"]}
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 { PermissionResponse } 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 { AudioPlayer, AudioRecorder, AudioSample } 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 createAudioPlayer(\n source: AudioSource | string | number | null = null,\n updateInterval: number = 500\n): AudioPlayer {\n const parsedSource = resolveSource(source);\n return new AudioModule.AudioPlayerWeb(parsedSource, updateInterval);\n}\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: AudioSample) => 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 async function requestRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.requestRecordingPermissionsAsync();\n}\n\nexport async function getRecordingPermissionsAsync(): Promise<PermissionResponse> {\n return await AudioModule.getRecordingPermissionsAsync();\n}\n\nexport { AudioModule };\n"]}
@@ -46,7 +46,7 @@ public class AudioModule: Module {
46
46
  // swiftlint:disable:next closure_body_length
47
47
  Class(AudioPlayer.self) {
48
48
  Constructor { (source: AudioSource?, updateInterval: Double) -> AudioPlayer in
49
- let avPlayer = AudioUtils.createAVPlayer(source: source)
49
+ let avPlayer = AudioUtils.createAVPlayer(from: source)
50
50
  let player = AudioPlayer(avPlayer, interval: updateInterval)
51
51
  AudioComponentRegistry.shared.add(player)
52
52
  return player
@@ -107,7 +107,7 @@ public class AudioModule: Module {
107
107
  }
108
108
 
109
109
  Property("paused") { player in
110
- return player.ref.rate == 0.0
110
+ player.isPaused
111
111
  }
112
112
 
113
113
  Property("volume") { player in
@@ -140,6 +140,10 @@ public class AudioModule: Module {
140
140
  }
141
141
  }
142
142
 
143
+ Function("replace") { (player, source: AudioSource) in
144
+ player.ref.replaceCurrentItem(with: AudioUtils.createAVPlayerItem(from: source))
145
+ }
146
+
143
147
  Function("pause") { player in
144
148
  player.ref.pause()
145
149
  }
@@ -13,6 +13,9 @@ public class AudioPlayer: SharedRef<AVPlayer> {
13
13
  var pitchCorrectionQuality: AVAudioTimePitchAlgorithm = .varispeed
14
14
  var currentRate: Float = 0.0
15
15
  let interval: Double
16
+ var isPaused: Bool {
17
+ ref.rate != 0.0
18
+ }
16
19
 
17
20
  // MARK: Observers
18
21
  private var timeToken: Any?
@@ -81,7 +81,7 @@ struct AudioUtils {
81
81
  return AVAudioRecorder()
82
82
  }
83
83
 
84
- static func createAVPlayer(source: AudioSource?) -> AVPlayer {
84
+ static func createAVPlayer(from source: AudioSource?) -> AVPlayer {
85
85
  if let source, let url = source.uri {
86
86
  let asset = AVURLAsset(url: url, options: source.headers)
87
87
  let item = AVPlayerItem(asset: asset)
@@ -90,6 +90,14 @@ struct AudioUtils {
90
90
  return AVPlayer()
91
91
  }
92
92
 
93
+ static func createAVPlayerItem(from source: AudioSource?) -> AVPlayerItem? {
94
+ guard let source, let url = source.uri else {
95
+ return nil
96
+ }
97
+ let asset = AVURLAsset(url: url, options: source.headers)
98
+ return AVPlayerItem(asset: asset)
99
+ }
100
+
93
101
  static func createRecordingOptions(_ options: RecordingOptions) -> [String: Any] {
94
102
  let strategy = options.bitRateStrategy?.toAVBitRateStrategy() ?? AVAudioBitRateStrategy_Variable
95
103
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "expo-audio",
3
3
  "title": "Expo Audio",
4
- "version": "0.2.3",
4
+ "version": "0.3.0",
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": "fc8a1408cab82e003dd2424db2994d7dea958067"
43
+ "gitHead": "bc1fea6bcab47889e2922d543920397691b200f3"
44
44
  }
@@ -112,6 +112,11 @@ export declare class AudioPlayer extends SharedObject<AudioEvents> {
112
112
  */
113
113
  pause(): void;
114
114
 
115
+ /**
116
+ * Replaces the current audio source with a new one.
117
+ */
118
+ replace(source: AudioSource): void;
119
+
115
120
  /**
116
121
  * Seeks the playback by the given number of seconds.
117
122
  * @param seconds The number of seconds to seek by.
@@ -181,6 +181,11 @@ export class AudioPlayerWeb
181
181
  this.isPlaying = false;
182
182
  }
183
183
 
184
+ replace(source: AudioSource): void {
185
+ this.src = source;
186
+ this.media = this._createMediaElement();
187
+ }
188
+
184
189
  async seekTo(seconds: number): Promise<void> {
185
190
  this.media.currentTime = seconds / 1000;
186
191
  }
package/src/ExpoAudio.ts CHANGED
@@ -81,6 +81,20 @@ export function useAudioRecorderState(recorder: AudioRecorder, interval: number
81
81
  return state;
82
82
  }
83
83
 
84
+ /**
85
+ * Creates an instance of an `AudioPlayer` that doesn't release automatically.
86
+ *
87
+ * > **info** For most use cases you should use the [`useAudioPlayer`](#useaudioplayersource-updateinterval) hook instead. See the [Using the `AudioPlayer` directly](#using-the-audioplayer-directly) section for more details.
88
+ * @param source
89
+ */
90
+ export function createAudioPlayer(
91
+ source: AudioSource | string | number | null = null,
92
+ updateInterval: number = 500
93
+ ): AudioPlayer {
94
+ const parsedSource = resolveSource(source);
95
+ return new AudioModule.AudioPlayer(parsedSource, updateInterval);
96
+ }
97
+
84
98
  export async function setIsAudioActiveAsync(active: boolean): Promise<void> {
85
99
  return await AudioModule.setIsAudioActiveAsync(active);
86
100
  }
@@ -10,12 +10,20 @@ import {
10
10
  RecordingOptions,
11
11
  RecordingStatus,
12
12
  } from './Audio.types';
13
- import { AudioRecorder, AudioSample } from './AudioModule.types';
13
+ import { AudioPlayer, AudioRecorder, AudioSample } from './AudioModule.types';
14
14
  import * as AudioModule from './AudioModule.web';
15
15
  import { AUDIO_SAMPLE_UPDATE, PLAYBACK_STATUS_UPDATE, RECORDING_STATUS_UPDATE } from './ExpoAudio';
16
16
  import { createRecordingOptions } from './utils/options';
17
17
  import { resolveSource } from './utils/resolveSource';
18
18
 
19
+ export function createAudioPlayer(
20
+ source: AudioSource | string | number | null = null,
21
+ updateInterval: number = 500
22
+ ): AudioPlayer {
23
+ const parsedSource = resolveSource(source);
24
+ return new AudioModule.AudioPlayerWeb(parsedSource, updateInterval);
25
+ }
26
+
19
27
  export function useAudioPlayer(
20
28
  source: AudioSource | string | number | null = null,
21
29
  updateInterval: number = 500