react-native-audio-api 0.6.1-rc.1 → 0.6.1-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -11
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.cpp +13 -8
- package/android/src/main/cpp/audioapi/android/core/AudioPlayer.h +3 -2
- package/android/src/main/java/com/swmansion/audioapi/AudioAPIModule.kt +27 -10
- package/android/src/main/java/com/swmansion/audioapi/system/LockScreenManager.kt +12 -3
- package/android/src/main/java/com/swmansion/audioapi/system/MediaNotificationManager.kt +2 -2
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionCallback.kt +4 -6
- package/android/src/main/java/com/swmansion/audioapi/system/MediaSessionManager.kt +1 -1
- package/android/src/main/res/drawable/skip_backward_10.xml +9 -0
- package/android/src/main/res/drawable/skip_forward_10.xml +9 -0
- package/android/src/oldarch/NativeAudioAPIModuleSpec.java +68 -64
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +2 -1
- package/common/cpp/audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h +94 -0
- package/common/cpp/audioapi/HostObjects/AudioContextHostObject.h +7 -7
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +9 -0
- package/common/cpp/audioapi/core/AudioContext.cpp +29 -4
- package/common/cpp/audioapi/core/AudioContext.h +2 -1
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +12 -0
- package/common/cpp/audioapi/core/BaseAudioContext.h +4 -3
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.cpp +236 -0
- package/common/cpp/audioapi/core/sources/AudioBufferQueueSourceNode.h +72 -0
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.h +1 -1
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +2 -2
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +3 -4
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.h +2 -1
- package/ios/audioapi/ios/AudioAPIModule.mm +23 -11
- package/ios/audioapi/ios/core/IOSAudioPlayer.h +3 -2
- package/ios/audioapi/ios/core/IOSAudioPlayer.mm +21 -10
- package/ios/audioapi/ios/core/NativeAudioPlayer.h +4 -0
- package/ios/audioapi/ios/core/NativeAudioPlayer.m +15 -0
- package/ios/audioapi/ios/system/AudioEngine.h +1 -0
- package/ios/audioapi/ios/system/AudioEngine.mm +11 -1
- package/ios/audioapi/ios/system/AudioSessionManager.mm +1 -1
- package/ios/audioapi/ios/system/LockScreenManager.mm +13 -1
- package/ios/audioapi/ios/system/NotificationManager.mm +1 -1
- package/lib/commonjs/api.js +7 -0
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js +46 -0
- package/lib/commonjs/core/AudioBufferQueueSourceNode.js.map +1 -0
- package/lib/commonjs/core/AudioContext.js +2 -2
- package/lib/commonjs/core/AudioContext.js.map +1 -1
- package/lib/commonjs/core/AudioNode.js +5 -1
- package/lib/commonjs/core/AudioNode.js.map +1 -1
- package/lib/commonjs/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +4 -0
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/commonjs/hooks/useSytemVolume.js +1 -1
- package/lib/commonjs/hooks/useSytemVolume.js.map +1 -1
- package/lib/commonjs/plugin/withAudioAPI.js +15 -14
- package/lib/commonjs/plugin/withAudioAPI.js.map +1 -1
- package/lib/commonjs/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/commonjs/system/AudioManager.js +12 -10
- package/lib/commonjs/system/AudioManager.js.map +1 -1
- package/lib/commonjs/web-core/AudioBufferSourceNode.js +4 -4
- package/lib/commonjs/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/commonjs/web-core/AudioContext.js +5 -3
- package/lib/commonjs/web-core/AudioContext.js.map +1 -1
- package/lib/commonjs/web-core/AudioNode.js +8 -2
- package/lib/commonjs/web-core/AudioNode.js.map +1 -1
- package/lib/commonjs/web-core/AudioParam.js +2 -1
- package/lib/commonjs/web-core/AudioParam.js.map +1 -1
- package/lib/commonjs/web-core/BiquadFilterNode.js +4 -4
- package/lib/commonjs/web-core/BiquadFilterNode.js.map +1 -1
- package/lib/commonjs/web-core/GainNode.js +1 -1
- package/lib/commonjs/web-core/GainNode.js.map +1 -1
- package/lib/commonjs/web-core/OscillatorNode.js +2 -2
- package/lib/commonjs/web-core/OscillatorNode.js.map +1 -1
- package/lib/commonjs/web-core/StereoPannerNode.js +1 -1
- package/lib/commonjs/web-core/StereoPannerNode.js.map +1 -1
- package/lib/module/api.js +1 -0
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/AudioBufferQueueSourceNode.js +40 -0
- package/lib/module/core/AudioBufferQueueSourceNode.js.map +1 -0
- package/lib/module/core/AudioContext.js +2 -2
- package/lib/module/core/AudioContext.js.map +1 -1
- package/lib/module/core/AudioNode.js +5 -1
- package/lib/module/core/AudioNode.js.map +1 -1
- package/lib/module/core/AudioScheduledSourceNode.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +4 -0
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/module/hooks/useSytemVolume.js +1 -1
- package/lib/module/hooks/useSytemVolume.js.map +1 -1
- package/lib/module/plugin/withAudioAPI.js +15 -14
- package/lib/module/plugin/withAudioAPI.js.map +1 -1
- package/lib/module/specs/NativeAudioAPIModule.js.map +1 -1
- package/lib/module/system/AudioManager.js +12 -10
- package/lib/module/system/AudioManager.js.map +1 -1
- package/lib/module/web-core/AudioBufferSourceNode.js +4 -4
- package/lib/module/web-core/AudioBufferSourceNode.js.map +1 -1
- package/lib/module/web-core/AudioContext.js +5 -3
- package/lib/module/web-core/AudioContext.js.map +1 -1
- package/lib/module/web-core/AudioNode.js +7 -2
- package/lib/module/web-core/AudioNode.js.map +1 -1
- package/lib/module/web-core/AudioParam.js +2 -1
- package/lib/module/web-core/AudioParam.js.map +1 -1
- package/lib/module/web-core/BiquadFilterNode.js +4 -4
- package/lib/module/web-core/BiquadFilterNode.js.map +1 -1
- package/lib/module/web-core/GainNode.js +1 -1
- package/lib/module/web-core/GainNode.js.map +1 -1
- package/lib/module/web-core/OscillatorNode.js +2 -2
- package/lib/module/web-core/OscillatorNode.js.map +1 -1
- package/lib/module/web-core/StereoPannerNode.js +1 -1
- package/lib/module/web-core/StereoPannerNode.js.map +1 -1
- package/lib/typescript/api.d.ts +2 -1
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts +16 -0
- package/lib/typescript/core/AudioBufferQueueSourceNode.d.ts.map +1 -0
- package/lib/typescript/core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/core/AudioNode.d.ts +1 -1
- package/lib/typescript/core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts +4 -3
- package/lib/typescript/core/AudioScheduledSourceNode.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +2 -0
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/events/types.d.ts +18 -9
- package/lib/typescript/events/types.d.ts.map +1 -1
- package/lib/typescript/hooks/useSytemVolume.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +9 -0
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/lib/typescript/plugin/withAudioAPI.d.ts +7 -6
- package/lib/typescript/plugin/withAudioAPI.d.ts.map +1 -1
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts +3 -2
- package/lib/typescript/specs/NativeAudioAPIModule.d.ts.map +1 -1
- package/lib/typescript/system/AudioManager.d.ts +6 -4
- package/lib/typescript/system/AudioManager.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +2 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioBufferSourceNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts +1 -1
- package/lib/typescript/web-core/AudioContext.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioNode.d.ts +2 -1
- package/lib/typescript/web-core/AudioNode.d.ts.map +1 -1
- package/lib/typescript/web-core/AudioParam.d.ts +4 -2
- package/lib/typescript/web-core/AudioParam.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/api.ts +5 -1
- package/src/core/AudioBufferQueueSourceNode.ts +71 -0
- package/src/core/AudioContext.ts +7 -2
- package/src/core/AudioNode.ts +6 -2
- package/src/core/AudioScheduledSourceNode.ts +3 -3
- package/src/core/BaseAudioContext.ts +8 -0
- package/src/events/types.ts +29 -9
- package/src/hooks/useSytemVolume.ts +6 -3
- package/src/interfaces.ts +18 -0
- package/src/plugin/withAudioAPI.ts +36 -29
- package/src/specs/NativeAudioAPIModule.ts +14 -6
- package/src/system/AudioManager.ts +21 -16
- package/src/types.ts +2 -1
- package/src/web-core/AudioBufferSourceNode.tsx +9 -4
- package/src/web-core/AudioContext.tsx +7 -3
- package/src/web-core/AudioNode.tsx +10 -3
- package/src/web-core/AudioParam.tsx +5 -2
- package/src/web-core/BiquadFilterNode.tsx +4 -4
- package/src/web-core/GainNode.tsx +1 -1
- package/src/web-core/OscillatorNode.tsx +2 -2
- package/src/web-core/StereoPannerNode.tsx +1 -1
- package/android/src/main/res/drawable/skip_backward_5.xml +0 -9
- package/android/src/main/res/drawable/skip_forward_5.xml +0 -9
package/README.md
CHANGED
|
@@ -34,17 +34,12 @@ check out the [Getting Started](https://docs.swmansion.com/react-native-audio-ap
|
|
|
34
34
|
Ability to modify playback speed without affecting pitch of the sound
|
|
35
35
|
<br />
|
|
36
36
|
|
|
37
|
-
- <sub
|
|
38
|
-
Full control of system audio settings, remote controls, lock screen integration and most importantly configurable background modes
|
|
39
|
-
<br />
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<br />
|
|
44
|
-
|
|
45
|
-
- **Connect audio param** 🤞 <br />
|
|
46
|
-
Ability to connect Audio nodes to audio params, which will allow for powerful and efficient modulation of audio parameters, creating effects like tremolo, vibrato or complex envelope followers.
|
|
47
|
-
<br />
|
|
37
|
+
- <sub>[](https://github.com/software-mansion/react-native-audio-api/releases/tag/0.6.0)</sub> <br/> **System configuration** 🛠️ <br />
|
|
38
|
+
Full control of system audio settings, remote controls, lock screen integration and most importantly configurable background modes <br />
|
|
39
|
+
<br /> **Microphone support** 🎙️ <br />
|
|
40
|
+
Grab audio data from device microphone or connected device, connect it to the audio graph or stream through the internet <br />
|
|
41
|
+
<br /> **Connect audio param** 🤞 <br />
|
|
42
|
+
Ability to connect Audio nodes to audio params, which will allow for powerful and efficient modulation of audio parameters, creating effects like tremolo, vibrato or complex envelope followers. <br />
|
|
48
43
|
|
|
49
44
|
- **JS Audio Worklets** 🐎 <br />
|
|
50
45
|
Ability to run JS functions connected to the audio graph running on audio thread allowing for full customization of what happens to the audio signal.
|
|
@@ -33,25 +33,30 @@ void AudioPlayer::start() {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
void AudioPlayer::stop() {
|
|
37
|
+
if (mStream_) {
|
|
38
|
+
mStream_->requestStop();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
void AudioPlayer::resume() {
|
|
37
43
|
if (mStream_) {
|
|
38
44
|
mStream_->requestStart();
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
47
|
|
|
42
|
-
void AudioPlayer::
|
|
43
|
-
isInitialized_ = false;
|
|
44
|
-
|
|
48
|
+
void AudioPlayer::suspend() {
|
|
45
49
|
if (mStream_) {
|
|
46
|
-
mStream_->
|
|
47
|
-
mStream_->close();
|
|
48
|
-
mStream_.reset();
|
|
50
|
+
mStream_->requestPause();
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
void AudioPlayer::
|
|
54
|
+
void AudioPlayer::cleanup() {
|
|
55
|
+
isInitialized_ = false;
|
|
56
|
+
|
|
53
57
|
if (mStream_) {
|
|
54
|
-
mStream_->
|
|
58
|
+
mStream_->close();
|
|
59
|
+
mStream_.reset();
|
|
55
60
|
}
|
|
56
61
|
}
|
|
57
62
|
|
|
@@ -19,9 +19,10 @@ class AudioPlayer : public AudioStreamDataCallback {
|
|
|
19
19
|
float sampleRate);
|
|
20
20
|
|
|
21
21
|
void start();
|
|
22
|
-
void resume();
|
|
23
22
|
void stop();
|
|
24
|
-
void
|
|
23
|
+
void resume();
|
|
24
|
+
void suspend();
|
|
25
|
+
void cleanup();
|
|
25
26
|
|
|
26
27
|
DataCallbackResult onAudioReady(
|
|
27
28
|
AudioStream *oboeStream,
|
|
@@ -53,14 +53,37 @@ class AudioAPIModule(
|
|
|
53
53
|
return true
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
@Synchronized
|
|
57
|
+
override fun getDevicePreferredSampleRate(): Double = MediaSessionManager.getDevicePreferredSampleRate()
|
|
58
|
+
|
|
59
|
+
@Synchronized
|
|
60
|
+
override fun setAudioSessionActivity(
|
|
61
|
+
enabled: Boolean,
|
|
62
|
+
promise: Promise?,
|
|
63
|
+
) {
|
|
64
|
+
// noting to do here
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Synchronized
|
|
68
|
+
override fun setAudioSessionOptions(
|
|
69
|
+
category: String?,
|
|
70
|
+
mode: String?,
|
|
71
|
+
options: ReadableArray?,
|
|
72
|
+
) {
|
|
73
|
+
// noting to do here
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Synchronized
|
|
56
77
|
override fun setLockScreenInfo(info: ReadableMap?) {
|
|
57
78
|
MediaSessionManager.setLockScreenInfo(info)
|
|
58
79
|
}
|
|
59
80
|
|
|
81
|
+
@Synchronized
|
|
60
82
|
override fun resetLockScreenInfo() {
|
|
61
83
|
MediaSessionManager.resetLockScreenInfo()
|
|
62
84
|
}
|
|
63
85
|
|
|
86
|
+
@Synchronized
|
|
64
87
|
override fun enableRemoteCommand(
|
|
65
88
|
name: String?,
|
|
66
89
|
enabled: Boolean,
|
|
@@ -68,29 +91,23 @@ class AudioAPIModule(
|
|
|
68
91
|
MediaSessionManager.enableRemoteCommand(name!!, enabled)
|
|
69
92
|
}
|
|
70
93
|
|
|
71
|
-
|
|
72
|
-
category: String?,
|
|
73
|
-
mode: String?,
|
|
74
|
-
options: ReadableArray?,
|
|
75
|
-
) {
|
|
76
|
-
// noting to do here
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
override fun getDevicePreferredSampleRate(): Double = MediaSessionManager.getDevicePreferredSampleRate()
|
|
80
|
-
|
|
94
|
+
@Synchronized
|
|
81
95
|
override fun observeAudioInterruptions(enabled: Boolean) {
|
|
82
96
|
MediaSessionManager.observeAudioInterruptions(enabled)
|
|
83
97
|
}
|
|
84
98
|
|
|
99
|
+
@Synchronized
|
|
85
100
|
override fun observeVolumeChanges(enabled: Boolean) {
|
|
86
101
|
MediaSessionManager.observeVolumeChanges(enabled)
|
|
87
102
|
}
|
|
88
103
|
|
|
104
|
+
@Synchronized
|
|
89
105
|
override fun requestRecordingPermissions(promise: Promise?) {
|
|
90
106
|
val res = MediaSessionManager.requestRecordingPermissions(currentActivity)
|
|
91
107
|
promise!!.resolve(res)
|
|
92
108
|
}
|
|
93
109
|
|
|
110
|
+
@Synchronized
|
|
94
111
|
override fun checkRecordingPermissions(promise: Promise?) {
|
|
95
112
|
val res = MediaSessionManager.checkRecordingPermissions()
|
|
96
113
|
promise!!.resolve(res)
|
|
@@ -35,7 +35,7 @@ class LockScreenManager(
|
|
|
35
35
|
private var artist: String? = null
|
|
36
36
|
private var album: String? = null
|
|
37
37
|
private var description: String? = null
|
|
38
|
-
private var duration: Long =
|
|
38
|
+
private var duration: Long = 0L
|
|
39
39
|
private var speed: Float = 1.0F
|
|
40
40
|
private var elapsedTime: Long = 0L
|
|
41
41
|
private var artwork: String? = null
|
|
@@ -142,9 +142,13 @@ class LockScreenManager(
|
|
|
142
142
|
state.playbackSpeed
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
if (isPlaying && speed == 0F) {
|
|
146
|
+
speed = 1F
|
|
147
|
+
}
|
|
148
|
+
|
|
145
149
|
elapsedTime =
|
|
146
150
|
if (info.hasKey("elapsedTime")) {
|
|
147
|
-
info.getDouble("elapsedTime").toLong()
|
|
151
|
+
(info.getDouble("elapsedTime") * 1000).toLong()
|
|
148
152
|
} else {
|
|
149
153
|
state.position
|
|
150
154
|
}
|
|
@@ -250,7 +254,7 @@ class LockScreenManager(
|
|
|
250
254
|
return bitmap
|
|
251
255
|
}
|
|
252
256
|
|
|
253
|
-
fun updatePlaybackState(playbackState: Int) {
|
|
257
|
+
private fun updatePlaybackState(playbackState: Int) {
|
|
254
258
|
isPlaying = playbackState == PlaybackStateCompat.STATE_PLAYING
|
|
255
259
|
|
|
256
260
|
pb.setState(playbackState, elapsedTime, speed)
|
|
@@ -285,6 +289,11 @@ class LockScreenManager(
|
|
|
285
289
|
if (hasControl(PlaybackStateCompat.ACTION_REWIND)) {
|
|
286
290
|
controlCount += 1
|
|
287
291
|
}
|
|
292
|
+
|
|
293
|
+
if (hasControl(PlaybackStateCompat.ACTION_SEEK_TO)) {
|
|
294
|
+
controlCount += 1
|
|
295
|
+
}
|
|
296
|
+
|
|
288
297
|
val actions = IntArray(controlCount)
|
|
289
298
|
for (i in actions.indices) {
|
|
290
299
|
actions[i] = i
|
|
@@ -154,7 +154,7 @@ class MediaNotificationManager(
|
|
|
154
154
|
|
|
155
155
|
skipForward =
|
|
156
156
|
createAction(
|
|
157
|
-
"
|
|
157
|
+
"skip_forward_10",
|
|
158
158
|
"Skip Forward",
|
|
159
159
|
mask,
|
|
160
160
|
PlaybackStateCompat.ACTION_FAST_FORWARD,
|
|
@@ -163,7 +163,7 @@ class MediaNotificationManager(
|
|
|
163
163
|
|
|
164
164
|
skipBackward =
|
|
165
165
|
createAction(
|
|
166
|
-
"
|
|
166
|
+
"skip_backward_10",
|
|
167
167
|
"Skip Backward",
|
|
168
168
|
mask,
|
|
169
169
|
PlaybackStateCompat.ACTION_REWIND,
|
|
@@ -3,7 +3,6 @@ package com.swmansion.audioapi.system
|
|
|
3
3
|
import android.content.Intent
|
|
4
4
|
import android.os.Build
|
|
5
5
|
import android.support.v4.media.session.MediaSessionCompat
|
|
6
|
-
import android.support.v4.media.session.PlaybackStateCompat
|
|
7
6
|
import androidx.core.app.NotificationManagerCompat
|
|
8
7
|
import com.swmansion.audioapi.AudioAPIModule
|
|
9
8
|
import java.lang.ref.WeakReference
|
|
@@ -11,15 +10,12 @@ import java.util.HashMap
|
|
|
11
10
|
|
|
12
11
|
class MediaSessionCallback(
|
|
13
12
|
private val audioAPIModule: WeakReference<AudioAPIModule>,
|
|
14
|
-
private val lockScreenManager: WeakReference<LockScreenManager>,
|
|
15
13
|
) : MediaSessionCompat.Callback() {
|
|
16
14
|
override fun onPlay() {
|
|
17
|
-
lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PLAYING)
|
|
18
15
|
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePlay", mapOf())
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
override fun onPause() {
|
|
22
|
-
lockScreenManager.get()?.updatePlaybackState(PlaybackStateCompat.STATE_PAUSED)
|
|
23
19
|
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remotePause", mapOf())
|
|
24
20
|
}
|
|
25
21
|
|
|
@@ -44,11 +40,13 @@ class MediaSessionCallback(
|
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
override fun onFastForward() {
|
|
47
|
-
|
|
43
|
+
val body = HashMap<String, Any>().apply { put("value", 10) }
|
|
44
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipForward", body)
|
|
48
45
|
}
|
|
49
46
|
|
|
50
47
|
override fun onRewind() {
|
|
51
|
-
|
|
48
|
+
val body = HashMap<String, Any>().apply { put("value", 10) }
|
|
49
|
+
audioAPIModule.get()?.invokeHandlerWithEventNameAndEventBody("remoteSkipBackward", body)
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
override fun onSeekTo(pos: Long) {
|
|
@@ -81,7 +81,7 @@ object MediaSessionManager {
|
|
|
81
81
|
this.lockScreenManager = LockScreenManager(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager))
|
|
82
82
|
this.mediaReceiver =
|
|
83
83
|
MediaReceiver(this.reactContext, WeakReference(this.mediaSession), WeakReference(mediaNotificationManager), this.audioAPIModule)
|
|
84
|
-
this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule
|
|
84
|
+
this.mediaSession.setCallback(MediaSessionCallback(this.audioAPIModule))
|
|
85
85
|
|
|
86
86
|
val filter = IntentFilter()
|
|
87
87
|
filter.addAction(MediaNotificationManager.REMOVE_NOTIFICATION)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
android:width="24dp"
|
|
3
|
+
android:height="24dp"
|
|
4
|
+
android:viewportWidth="24.0"
|
|
5
|
+
android:viewportHeight="24.0">
|
|
6
|
+
<path
|
|
7
|
+
android:fillColor="#FFFFFFFF"
|
|
8
|
+
android:pathData="M12,5L12,1L7,6l5,5L12,7c3.3,0 6,2.7 6,6s-2.7,6 -6,6 -6,-2.7 -6,-6L4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8 -3.6,-8 -8,-8zM10.9,16L10,16v-3.3L9,13v-0.7l1.8,-0.6h0.1L10.9,16zM15.2,14.2c0,0.3 0,0.6 -0.1,0.8l-0.3,0.6s-0.3,0.3 -0.5,0.3 -0.4,0.1 -0.6,0.1 -0.4,0 -0.6,-0.1 -0.3,-0.2 -0.5,-0.3 -0.2,-0.3 -0.3,-0.6 -0.1,-0.5 -0.1,-0.8v-0.7c0,-0.3 0,-0.6 0.1,-0.8l0.3,-0.6s0.3,-0.3 0.5,-0.3 0.4,-0.1 0.6,-0.1 0.4,0 0.6,0.1c0.2,0.1 0.3,0.2 0.5,0.3s0.2,0.3 0.3,0.6 0.1,0.5 0.1,0.8v0.7zM14.3,13.4v-0.5s-0.1,-0.2 -0.1,-0.3 -0.1,-0.1 -0.2,-0.2 -0.2,-0.1 -0.3,-0.1 -0.2,0 -0.3,0.1l-0.2,0.2s-0.1,0.2 -0.1,0.3v2s0.1,0.2 0.1,0.3 0.1,0.1 0.2,0.2 0.2,0.1 0.3,0.1 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-1.5z"/>
|
|
9
|
+
</vector>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
|
+
android:width="24dp"
|
|
3
|
+
android:height="24dp"
|
|
4
|
+
android:viewportWidth="24.0"
|
|
5
|
+
android:viewportHeight="24.0">
|
|
6
|
+
<path
|
|
7
|
+
android:fillColor="#FFFFFFFF"
|
|
8
|
+
android:pathData="M4,13c0,4.4 3.6,8 8,8s8,-3.6 8,-8h-2c0,3.3 -2.7,6 -6,6s-6,-2.7 -6,-6 2.7,-6 6,-6v4l5,-5 -5,-5v4c-4.4,0 -8,3.6 -8,8zM10.8,16L10,16v-3.3L9,13v-0.7l1.8,-0.6h0.1L10.9,16zM15.1,14.2c0,0.3 0,0.6 -0.1,0.8l-0.3,0.6s-0.3,0.3 -0.5,0.3 -0.4,0.1 -0.6,0.1 -0.4,0 -0.6,-0.1 -0.3,-0.2 -0.5,-0.3 -0.2,-0.3 -0.3,-0.6 -0.1,-0.5 -0.1,-0.8v-0.7c0,-0.3 0,-0.6 0.1,-0.8l0.3,-0.6s0.3,-0.3 0.5,-0.3 0.4,-0.1 0.6,-0.1 0.4,0 0.6,0.1 0.3,0.2 0.5,0.3 0.2,0.3 0.3,0.6 0.1,0.5 0.1,0.8v0.7zM14.3,13.4v-0.5s-0.1,-0.2 -0.1,-0.3 -0.1,-0.1 -0.2,-0.2 -0.2,-0.1 -0.3,-0.1 -0.2,0 -0.3,0.1l-0.2,0.2s-0.1,0.2 -0.1,0.3v2s0.1,0.2 0.1,0.3 0.1,0.1 0.2,0.2 0.2,0.1 0.3,0.1 0.2,0 0.3,-0.1l0.2,-0.2s0.1,-0.2 0.1,-0.3v-1.5z"/>
|
|
9
|
+
</vector>
|
|
@@ -10,67 +10,71 @@
|
|
|
10
10
|
* @nolint
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
package com.swmansion.audioapi;
|
|
14
|
-
|
|
15
|
-
import com.facebook.proguard.annotations.DoNotStrip;
|
|
16
|
-
import com.facebook.react.bridge.Promise;
|
|
17
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
19
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
20
|
-
import com.facebook.react.bridge.ReadableArray;
|
|
21
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
22
|
-
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
|
23
|
-
import javax.annotation.Nonnull;
|
|
24
|
-
|
|
25
|
-
public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
13
|
+
package com.swmansion.audioapi;
|
|
14
|
+
|
|
15
|
+
import com.facebook.proguard.annotations.DoNotStrip;
|
|
16
|
+
import com.facebook.react.bridge.Promise;
|
|
17
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
19
|
+
import com.facebook.react.bridge.ReactMethod;
|
|
20
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
21
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
22
|
+
import com.facebook.react.turbomodule.core.interfaces.TurboModule;
|
|
23
|
+
import javax.annotation.Nonnull;
|
|
24
|
+
|
|
25
|
+
public abstract class NativeAudioAPIModuleSpec extends ReactContextBaseJavaModule implements TurboModule {
|
|
26
|
+
public static final String NAME = "AudioAPIModule";
|
|
27
|
+
|
|
28
|
+
public NativeAudioAPIModuleSpec(ReactApplicationContext reactContext) {
|
|
29
|
+
super(reactContext);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Override
|
|
33
|
+
public @Nonnull String getName() {
|
|
34
|
+
return NAME;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
38
|
+
@DoNotStrip
|
|
39
|
+
public abstract boolean install();
|
|
40
|
+
|
|
41
|
+
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
42
|
+
@DoNotStrip
|
|
43
|
+
public abstract double getDevicePreferredSampleRate();
|
|
44
|
+
|
|
45
|
+
@ReactMethod
|
|
46
|
+
@DoNotStrip
|
|
47
|
+
public abstract void setAudioSessionActivity(boolean enabled, Promise promise);
|
|
48
|
+
|
|
49
|
+
@ReactMethod
|
|
50
|
+
@DoNotStrip
|
|
51
|
+
public abstract void setAudioSessionOptions(String category, String mode, ReadableArray options);
|
|
52
|
+
|
|
53
|
+
@ReactMethod
|
|
54
|
+
@DoNotStrip
|
|
55
|
+
public abstract void setLockScreenInfo(ReadableMap info);
|
|
56
|
+
|
|
57
|
+
@ReactMethod
|
|
58
|
+
@DoNotStrip
|
|
59
|
+
public abstract void resetLockScreenInfo();
|
|
60
|
+
|
|
61
|
+
@ReactMethod
|
|
62
|
+
@DoNotStrip
|
|
63
|
+
public abstract void enableRemoteCommand(String name, boolean enabled);
|
|
64
|
+
|
|
65
|
+
@ReactMethod
|
|
66
|
+
@DoNotStrip
|
|
67
|
+
public abstract void observeAudioInterruptions(boolean enabled);
|
|
68
|
+
|
|
69
|
+
@ReactMethod
|
|
70
|
+
@DoNotStrip
|
|
71
|
+
public abstract void observeVolumeChanges(boolean enabled);
|
|
72
|
+
|
|
73
|
+
@ReactMethod
|
|
74
|
+
@DoNotStrip
|
|
75
|
+
public abstract void requestRecordingPermissions(Promise promise);
|
|
76
|
+
|
|
77
|
+
@ReactMethod
|
|
78
|
+
@DoNotStrip
|
|
79
|
+
public abstract void checkRecordingPermissions(Promise promise);
|
|
80
|
+
}
|
|
@@ -45,7 +45,8 @@ class AudioAPIModuleInstaller {
|
|
|
45
45
|
size_t count) -> jsi::Value {
|
|
46
46
|
std::shared_ptr<AudioContext> audioContext;
|
|
47
47
|
auto sampleRate = static_cast<float>(args[0].getNumber());
|
|
48
|
-
|
|
48
|
+
auto initSuspended = args[1].getBool();
|
|
49
|
+
audioContext = std::make_shared<AudioContext>(sampleRate, initSuspended, audioEventHandlerRegistry);
|
|
49
50
|
|
|
50
51
|
auto audioContextHostObject = std::make_shared<AudioContextHostObject>(
|
|
51
52
|
audioContext, &runtime, jsCallInvoker);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <audioapi/HostObjects/AudioBufferHostObject.h>
|
|
4
|
+
#include <audioapi/core/sources/AudioBufferQueueSourceNode.h>
|
|
5
|
+
#include <audioapi/HostObjects/AudioParamHostObject.h>
|
|
6
|
+
#include <audioapi/HostObjects/AudioScheduledSourceNodeHostObject.h>
|
|
7
|
+
|
|
8
|
+
#include <memory>
|
|
9
|
+
#include <vector>
|
|
10
|
+
|
|
11
|
+
namespace audioapi {
|
|
12
|
+
using namespace facebook;
|
|
13
|
+
|
|
14
|
+
class AudioBufferQueueSourceNodeHostObject
|
|
15
|
+
: public AudioScheduledSourceNodeHostObject {
|
|
16
|
+
public:
|
|
17
|
+
explicit AudioBufferQueueSourceNodeHostObject(
|
|
18
|
+
const std::shared_ptr<AudioBufferQueueSourceNode> &node)
|
|
19
|
+
: AudioScheduledSourceNodeHostObject(node) {
|
|
20
|
+
addGetters(
|
|
21
|
+
JSI_EXPORT_PROPERTY_GETTER(AudioBufferQueueSourceNodeHostObject, detune),
|
|
22
|
+
JSI_EXPORT_PROPERTY_GETTER(AudioBufferQueueSourceNodeHostObject, playbackRate));
|
|
23
|
+
|
|
24
|
+
addSetters(
|
|
25
|
+
JSI_EXPORT_PROPERTY_SETTER(AudioBufferQueueSourceNodeHostObject, onPositionChanged),
|
|
26
|
+
JSI_EXPORT_PROPERTY_SETTER(AudioBufferQueueSourceNodeHostObject, onPositionChangedInterval));
|
|
27
|
+
|
|
28
|
+
// start method is overridden in this class
|
|
29
|
+
functions_->erase("start");
|
|
30
|
+
|
|
31
|
+
addFunctions(
|
|
32
|
+
JSI_EXPORT_FUNCTION(AudioBufferQueueSourceNodeHostObject, start),
|
|
33
|
+
JSI_EXPORT_FUNCTION(AudioBufferQueueSourceNodeHostObject, enqueueBuffer));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
JSI_PROPERTY_GETTER(detune) {
|
|
37
|
+
auto audioBufferSourceNode =
|
|
38
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
39
|
+
auto detune = audioBufferSourceNode->getDetuneParam();
|
|
40
|
+
auto detuneHostObject = std::make_shared<AudioParamHostObject>(detune);
|
|
41
|
+
return jsi::Object::createFromHostObject(runtime, detuneHostObject);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
JSI_PROPERTY_GETTER(playbackRate) {
|
|
45
|
+
auto audioBufferSourceNode =
|
|
46
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
47
|
+
auto playbackRate = audioBufferSourceNode->getPlaybackRateParam();
|
|
48
|
+
auto playbackRateHostObject =
|
|
49
|
+
std::make_shared<AudioParamHostObject>(playbackRate);
|
|
50
|
+
return jsi::Object::createFromHostObject(runtime, playbackRateHostObject);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
JSI_PROPERTY_SETTER(onPositionChanged) {
|
|
54
|
+
auto audioBufferQueueSourceNode =
|
|
55
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
56
|
+
|
|
57
|
+
audioBufferQueueSourceNode->setOnPositionChangedCallbackId(std::stoull(value.getString(runtime).utf8(runtime)));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
JSI_PROPERTY_SETTER(onPositionChangedInterval) {
|
|
61
|
+
auto audioBufferQueueSourceNode =
|
|
62
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
63
|
+
|
|
64
|
+
audioBufferQueueSourceNode->setOnPositionChangedInterval(value.getNumber());
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
JSI_HOST_FUNCTION(start) {
|
|
68
|
+
auto when = args[0].getNumber();
|
|
69
|
+
auto offset = args[1].getNumber();
|
|
70
|
+
|
|
71
|
+
auto audioBufferQueueSourceNode =
|
|
72
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
73
|
+
|
|
74
|
+
audioBufferQueueSourceNode->start(when, offset);
|
|
75
|
+
|
|
76
|
+
return jsi::Value::undefined();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
JSI_HOST_FUNCTION(enqueueBuffer) {
|
|
80
|
+
auto audioBufferQueueSourceNode =
|
|
81
|
+
std::static_pointer_cast<AudioBufferQueueSourceNode>(node_);
|
|
82
|
+
|
|
83
|
+
auto audioBufferHostObject =
|
|
84
|
+
args[0].getObject(runtime).asHostObject<AudioBufferHostObject>(runtime);
|
|
85
|
+
int bufferId = args[1].asNumber();
|
|
86
|
+
auto isLastBuffer = args[2].asBool();
|
|
87
|
+
|
|
88
|
+
audioBufferQueueSourceNode->enqueueBuffer(audioBufferHostObject->audioBuffer_, bufferId, isLastBuffer);
|
|
89
|
+
|
|
90
|
+
return jsi::Value::undefined();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
} // namespace audioapi
|
|
@@ -46,12 +46,12 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
|
|
|
46
46
|
auto result = audioContext->resume();
|
|
47
47
|
|
|
48
48
|
if (!result) {
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
promise->reject("Failed to resume audio context because it is already closed.");
|
|
50
|
+
return;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
promise->resolve([](jsi::Runtime &runtime) {
|
|
54
|
-
return jsi::Value
|
|
53
|
+
promise->resolve([result](jsi::Runtime &runtime) {
|
|
54
|
+
return jsi::Value(result);
|
|
55
55
|
});
|
|
56
56
|
}).detach();
|
|
57
57
|
});
|
|
@@ -66,12 +66,12 @@ class AudioContextHostObject : public BaseAudioContextHostObject {
|
|
|
66
66
|
auto result = audioContext->suspend();
|
|
67
67
|
|
|
68
68
|
if (!result) {
|
|
69
|
-
promise->reject("Failed to
|
|
69
|
+
promise->reject("Failed to suspend audio context because it is already closed.");
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
promise->resolve([](jsi::Runtime &runtime) {
|
|
74
|
-
return jsi::Value
|
|
73
|
+
promise->resolve([result](jsi::Runtime &runtime) {
|
|
74
|
+
return jsi::Value(result);
|
|
75
75
|
});
|
|
76
76
|
}).detach();
|
|
77
77
|
});
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include <audioapi/jsi/JsiPromise.h>
|
|
5
5
|
#include <audioapi/HostObjects/AudioBufferHostObject.h>
|
|
6
6
|
#include <audioapi/HostObjects/AudioBufferSourceNodeHostObject.h>
|
|
7
|
+
#include <audioapi/HostObjects/AudioBufferQueueSourceNodeHostObject.h>
|
|
7
8
|
#include <audioapi/HostObjects/AudioDestinationNodeHostObject.h>
|
|
8
9
|
#include <audioapi/core/BaseAudioContext.h>
|
|
9
10
|
#include <audioapi/HostObjects/BiquadFilterNodeHostObject.h>
|
|
@@ -43,6 +44,7 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
43
44
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createStereoPanner),
|
|
44
45
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBiquadFilter),
|
|
45
46
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBufferSource),
|
|
47
|
+
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBufferQueueSource),
|
|
46
48
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createBuffer),
|
|
47
49
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createPeriodicWave),
|
|
48
50
|
JSI_EXPORT_FUNCTION(BaseAudioContextHostObject, createAnalyser),
|
|
@@ -103,6 +105,13 @@ class BaseAudioContextHostObject : public JsiHostObject {
|
|
|
103
105
|
return jsi::Object::createFromHostObject(runtime, bufferSourceHostObject);
|
|
104
106
|
}
|
|
105
107
|
|
|
108
|
+
JSI_HOST_FUNCTION(createBufferQueueSource) {
|
|
109
|
+
auto bufferSource = context_->createBufferQueueSource();
|
|
110
|
+
auto bufferStreamSourceHostObject =
|
|
111
|
+
std::make_shared<AudioBufferQueueSourceNodeHostObject>(bufferSource);
|
|
112
|
+
return jsi::Object::createFromHostObject(runtime, bufferStreamSourceHostObject);
|
|
113
|
+
}
|
|
114
|
+
|
|
106
115
|
JSI_HOST_FUNCTION(createBuffer) {
|
|
107
116
|
auto numberOfChannels = static_cast<int>(args[0].getNumber());
|
|
108
117
|
auto length = static_cast<size_t>(args[1].getNumber());
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
namespace audioapi {
|
|
13
13
|
AudioContext::AudioContext(
|
|
14
14
|
float sampleRate,
|
|
15
|
+
bool initSuspended,
|
|
15
16
|
const std::shared_ptr<AudioEventHandlerRegistry> &audioEventHandlerRegistry)
|
|
16
17
|
: BaseAudioContext(audioEventHandlerRegistry) {
|
|
17
18
|
#ifdef ANDROID
|
|
@@ -24,8 +25,16 @@ AudioContext::AudioContext(
|
|
|
24
25
|
sampleRate_ = sampleRate;
|
|
25
26
|
audioDecoder_ = std::make_shared<AudioDecoder>(sampleRate);
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
if (initSuspended) {
|
|
29
|
+
playerHasBeenStarted_ = false;
|
|
30
|
+
state_ = ContextState::SUSPENDED;
|
|
31
|
+
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
playerHasBeenStarted_ = true;
|
|
28
36
|
audioPlayer_->start();
|
|
37
|
+
state_ = ContextState::RUNNING;
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
AudioContext::~AudioContext() {
|
|
@@ -36,8 +45,9 @@ AudioContext::~AudioContext() {
|
|
|
36
45
|
|
|
37
46
|
void AudioContext::close() {
|
|
38
47
|
state_ = ContextState::CLOSED;
|
|
39
|
-
audioPlayer_->stop();
|
|
40
48
|
|
|
49
|
+
audioPlayer_->stop();
|
|
50
|
+
audioPlayer_->cleanup();
|
|
41
51
|
nodeManager_->cleanup();
|
|
42
52
|
}
|
|
43
53
|
|
|
@@ -46,8 +56,18 @@ bool AudioContext::resume() {
|
|
|
46
56
|
return false;
|
|
47
57
|
}
|
|
48
58
|
|
|
59
|
+
if (isRunning()) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!playerHasBeenStarted_) {
|
|
64
|
+
playerHasBeenStarted_ = true;
|
|
65
|
+
audioPlayer_->start();
|
|
66
|
+
} else {
|
|
67
|
+
audioPlayer_->resume();
|
|
68
|
+
}
|
|
69
|
+
|
|
49
70
|
state_ = ContextState::RUNNING;
|
|
50
|
-
audioPlayer_->resume();
|
|
51
71
|
return true;
|
|
52
72
|
}
|
|
53
73
|
|
|
@@ -56,8 +76,13 @@ bool AudioContext::suspend() {
|
|
|
56
76
|
return false;
|
|
57
77
|
}
|
|
58
78
|
|
|
79
|
+
if (isSuspended()) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
audioPlayer_->suspend();
|
|
84
|
+
|
|
59
85
|
state_ = ContextState::SUSPENDED;
|
|
60
|
-
audioPlayer_->pause();
|
|
61
86
|
return true;
|
|
62
87
|
}
|
|
63
88
|
|