sezo-audio-engine 0.0.8 → 0.0.9
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 +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/expo/modules/audioengine/ExpoAudioEngineModule.kt +12 -0
- package/ios/AudioEngine/NativeAudioEngine.swift +22 -0
- package/ios/ExpoAudioEngineModule.swift +29 -0
- package/ios/build/generated/ios/FBReactNativeSpec/FBReactNativeSpec-generated.mm +2321 -0
- package/ios/build/generated/ios/FBReactNativeSpec/FBReactNativeSpec.h +2761 -0
- package/ios/build/generated/ios/FBReactNativeSpecJSI-generated.cpp +2929 -0
- package/ios/build/generated/ios/FBReactNativeSpecJSI.h +7727 -0
- package/ios/build/generated/ios/RCTModulesConformingToProtocolsProvider.h +18 -0
- package/ios/build/generated/ios/RCTModulesConformingToProtocolsProvider.mm +33 -0
- package/ios/build/generated/ios/ReactCodegen.podspec.json +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ allprojects {
|
|
|
38
38
|
Optionally pin the engine version in `android/gradle.properties`:
|
|
39
39
|
|
|
40
40
|
```properties
|
|
41
|
-
sezoAudioEngineVersion=android-engine-v0.1.
|
|
41
|
+
sezoAudioEngineVersion=android-engine-v0.1.9
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
If you want to build from source instead, include the local engine module in
|
package/android/build.gradle
CHANGED
|
@@ -44,7 +44,7 @@ dependencies {
|
|
|
44
44
|
if (androidEngineProject != null) {
|
|
45
45
|
implementation androidEngineProject
|
|
46
46
|
} else {
|
|
47
|
-
def sezoAudioEngineVersion = project.findProperty("sezoAudioEngineVersion") ?: "android-engine-v0.1.
|
|
47
|
+
def sezoAudioEngineVersion = project.findProperty("sezoAudioEngineVersion") ?: "android-engine-v0.1.9"
|
|
48
48
|
implementation "com.github.Sepzie:SezoAudioEngine:${sezoAudioEngineVersion}"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -40,6 +40,17 @@ class ExpoAudioEngineModule : Module() {
|
|
|
40
40
|
throw Exception("Failed to initialize audio engine")
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
audioEngine?.setPlaybackStateListener { state, positionMs, durationMs ->
|
|
44
|
+
sendEvent(
|
|
45
|
+
"playbackStateChange",
|
|
46
|
+
mapOf(
|
|
47
|
+
"state" to state,
|
|
48
|
+
"positionMs" to positionMs,
|
|
49
|
+
"durationMs" to durationMs
|
|
50
|
+
)
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
Log.d(TAG, "Audio engine initialized successfully")
|
|
44
55
|
}
|
|
45
56
|
|
|
@@ -53,6 +64,7 @@ class ExpoAudioEngineModule : Module() {
|
|
|
53
64
|
progressLogState.clear()
|
|
54
65
|
engine.setExtractionProgressListener(null)
|
|
55
66
|
engine.setExtractionCompletionListener(null)
|
|
67
|
+
engine.setPlaybackStateListener(null)
|
|
56
68
|
engine.release()
|
|
57
69
|
engine.destroy()
|
|
58
70
|
}
|
|
@@ -5,6 +5,13 @@ import UIKit
|
|
|
5
5
|
/// Swift wrapper around `AVAudioEngine` that backs the Expo module API.
|
|
6
6
|
/// Keeps state on a single serial queue to avoid thread-safety issues.
|
|
7
7
|
final class NativeAudioEngine {
|
|
8
|
+
private enum PlaybackState: String {
|
|
9
|
+
case stopped
|
|
10
|
+
case playing
|
|
11
|
+
case paused
|
|
12
|
+
case recording
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
/// Serial queue to protect engine state and avoid races with audio callbacks.
|
|
9
16
|
private let queue = DispatchQueue(label: "sezo.audioengine.state")
|
|
10
17
|
/// Core iOS audio graph.
|
|
@@ -42,6 +49,8 @@ final class NativeAudioEngine {
|
|
|
42
49
|
private var pauseCommandTarget: Any?
|
|
43
50
|
private var toggleCommandTarget: Any?
|
|
44
51
|
private var lastConfig = AudioEngineConfig(dictionary: [:])
|
|
52
|
+
var onPlaybackStateChange: ((String, Double, Double) -> Void)?
|
|
53
|
+
var onPlaybackComplete: ((Double, Double) -> Void)?
|
|
45
54
|
|
|
46
55
|
/// Bookkeeping for a live recording session.
|
|
47
56
|
private struct RecordingState {
|
|
@@ -720,6 +729,8 @@ final class NativeAudioEngine {
|
|
|
720
729
|
stopAllPlayers()
|
|
721
730
|
stopEngineIfRunning()
|
|
722
731
|
updateNowPlayingInfoInternal()
|
|
732
|
+
emitPlaybackState(.stopped, positionMs: currentPositionMs)
|
|
733
|
+
onPlaybackComplete?(currentPositionMs, durationMs)
|
|
723
734
|
}
|
|
724
735
|
|
|
725
736
|
/// Computes playback position from host time.
|
|
@@ -1191,6 +1202,7 @@ final class NativeAudioEngine {
|
|
|
1191
1202
|
schedulePlayback(at: currentPositionMs)
|
|
1192
1203
|
isPlayingFlag = true
|
|
1193
1204
|
updateNowPlayingInfoInternal()
|
|
1205
|
+
emitPlaybackState(.playing)
|
|
1194
1206
|
}
|
|
1195
1207
|
|
|
1196
1208
|
/// Internal pause logic (expects to run on the queue).
|
|
@@ -1201,10 +1213,12 @@ final class NativeAudioEngine {
|
|
|
1201
1213
|
stopAllPlayers()
|
|
1202
1214
|
stopEngineIfRunning()
|
|
1203
1215
|
updateNowPlayingInfoInternal()
|
|
1216
|
+
emitPlaybackState(.paused, positionMs: currentPositionMs)
|
|
1204
1217
|
}
|
|
1205
1218
|
|
|
1206
1219
|
/// Internal stop logic (expects to run on the queue).
|
|
1207
1220
|
private func stopInternal() {
|
|
1221
|
+
let shouldEmit = isPlayingFlag || currentPositionMs != 0.0
|
|
1208
1222
|
isPlayingFlag = false
|
|
1209
1223
|
currentPositionMs = 0.0
|
|
1210
1224
|
playbackStartHostTime = nil
|
|
@@ -1213,6 +1227,9 @@ final class NativeAudioEngine {
|
|
|
1213
1227
|
stopAllPlayers()
|
|
1214
1228
|
stopEngineIfRunning()
|
|
1215
1229
|
updateNowPlayingInfoInternal()
|
|
1230
|
+
if shouldEmit {
|
|
1231
|
+
emitPlaybackState(.stopped, positionMs: currentPositionMs)
|
|
1232
|
+
}
|
|
1216
1233
|
}
|
|
1217
1234
|
|
|
1218
1235
|
/// Internal seek logic (expects to run on the queue).
|
|
@@ -1251,6 +1268,11 @@ final class NativeAudioEngine {
|
|
|
1251
1268
|
MPNowPlayingInfoCenter.default().nowPlayingInfo = info
|
|
1252
1269
|
}
|
|
1253
1270
|
|
|
1271
|
+
private func emitPlaybackState(_ state: PlaybackState, positionMs: Double? = nil) {
|
|
1272
|
+
let resolvedPosition = positionMs ?? (isPlayingFlag ? currentPlaybackPositionMs() : currentPositionMs)
|
|
1273
|
+
onPlaybackStateChange?(state.rawValue, resolvedPosition, durationMs)
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1254
1276
|
/// Registers basic play/pause remote command handlers.
|
|
1255
1277
|
private func configureRemoteCommandsIfNeeded() {
|
|
1256
1278
|
guard playCommandTarget == nil else { return }
|
|
@@ -5,6 +5,35 @@ public class ExpoAudioEngineModule: Module {
|
|
|
5
5
|
|
|
6
6
|
public func definition() -> ModuleDefinition {
|
|
7
7
|
Name("ExpoAudioEngineModule")
|
|
8
|
+
OnCreate {
|
|
9
|
+
engine.onPlaybackStateChange = { [weak self] state, positionMs, durationMs in
|
|
10
|
+
DispatchQueue.main.async {
|
|
11
|
+
self?.sendEvent(
|
|
12
|
+
"playbackStateChange",
|
|
13
|
+
[
|
|
14
|
+
"state": state,
|
|
15
|
+
"positionMs": positionMs,
|
|
16
|
+
"durationMs": durationMs
|
|
17
|
+
]
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
engine.onPlaybackComplete = { [weak self] positionMs, durationMs in
|
|
22
|
+
DispatchQueue.main.async {
|
|
23
|
+
self?.sendEvent(
|
|
24
|
+
"playbackComplete",
|
|
25
|
+
[
|
|
26
|
+
"positionMs": positionMs,
|
|
27
|
+
"durationMs": durationMs
|
|
28
|
+
]
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
OnDestroy {
|
|
34
|
+
engine.onPlaybackStateChange = nil
|
|
35
|
+
engine.onPlaybackComplete = nil
|
|
36
|
+
}
|
|
8
37
|
|
|
9
38
|
AsyncFunction("initialize") { (config: [String: Any]) in
|
|
10
39
|
engine.initialize(config: config)
|