@capgo/native-audio 7.1.7 → 7.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/README.md +56 -8
- package/android/build.gradle +14 -5
- package/android/src/main/java/ee/forgr/audio/AudioAsset.java +276 -133
- package/android/src/main/java/ee/forgr/audio/AudioCompletionListener.java +1 -1
- package/android/src/main/java/ee/forgr/audio/AudioDispatcher.java +168 -182
- package/android/src/main/java/ee/forgr/audio/Constant.java +20 -21
- package/android/src/main/java/ee/forgr/audio/NativeAudio.java +596 -506
- package/android/src/main/java/ee/forgr/audio/RemoteAudioAsset.java +599 -166
- package/android/src/main/java/ee/forgr/audio/StreamAudioAsset.java +499 -0
- package/dist/docs.json +96 -3
- package/dist/esm/definitions.d.ts +33 -2
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +4 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +4 -3
- package/dist/esm/web.js +23 -20
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +22 -19
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +22 -19
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/AudioAsset.swift +200 -94
- package/ios/Plugin/Plugin.swift +56 -50
- package/ios/Plugin/RemoteAudioAsset.swift +217 -62
- package/package.json +18 -20
@@ -20,70 +20,88 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
20
20
|
let FADESTEP: Float = 0.05
|
21
21
|
let FADEDELAY: Float = 0.08
|
22
22
|
|
23
|
+
private var currentTimeTimer: Timer?
|
24
|
+
|
23
25
|
init(owner: NativeAudio, withAssetId assetId: String, withPath path: String!, withChannels channels: Int!, withVolume volume: Float!, withFadeDelay delay: Float!) {
|
24
26
|
|
25
27
|
self.owner = owner
|
26
28
|
self.assetId = assetId
|
27
29
|
self.channels = []
|
30
|
+
self.initialVolume = volume ?? 1.0
|
28
31
|
|
29
32
|
super.init()
|
30
33
|
|
31
34
|
let pathUrl: URL = URL(string: path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)!
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
player
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
player
|
35
|
+
|
36
|
+
owner.executeOnAudioQueue { [self] in
|
37
|
+
for _ in 0..<channels {
|
38
|
+
do {
|
39
|
+
let player: AVAudioPlayer! = try AVAudioPlayer(contentsOf: pathUrl)
|
40
|
+
player.delegate = self
|
41
|
+
if player != nil {
|
42
|
+
player.enableRate = true
|
43
|
+
player.volume = volume
|
44
|
+
player.rate = 1.0
|
45
|
+
player.prepareToPlay()
|
46
|
+
self.channels.append(player)
|
44
47
|
}
|
48
|
+
} catch let error as NSError {
|
49
|
+
print(error.debugDescription)
|
50
|
+
print("Error loading \(String(describing: path))")
|
45
51
|
}
|
46
|
-
} catch let error as NSError {
|
47
|
-
print(error.debugDescription)
|
48
|
-
print("Error loading \(String(describing: path))")
|
49
52
|
}
|
50
53
|
}
|
51
54
|
}
|
52
55
|
|
53
56
|
func getCurrentTime() -> TimeInterval {
|
54
|
-
|
55
|
-
|
57
|
+
var result: TimeInterval = 0
|
58
|
+
owner.executeOnAudioQueue { [self] in
|
59
|
+
if channels.count != 1 {
|
60
|
+
result = 0
|
61
|
+
return
|
62
|
+
}
|
63
|
+
let player: AVAudioPlayer = channels[playIndex]
|
64
|
+
result = player.currentTime
|
56
65
|
}
|
57
|
-
|
58
|
-
|
59
|
-
return player.currentTime
|
66
|
+
return result
|
60
67
|
}
|
61
68
|
|
62
69
|
func setCurrentTime(time: TimeInterval) {
|
63
|
-
|
64
|
-
|
70
|
+
owner.executeOnAudioQueue { [self] in
|
71
|
+
if channels.count != 1 {
|
72
|
+
return
|
73
|
+
}
|
74
|
+
let player: AVAudioPlayer = channels[playIndex]
|
75
|
+
player.currentTime = time
|
65
76
|
}
|
66
|
-
|
67
|
-
let player: AVAudioPlayer = channels[playIndex]
|
68
|
-
|
69
|
-
player.currentTime = time
|
70
77
|
}
|
71
78
|
|
72
79
|
func getDuration() -> TimeInterval {
|
73
|
-
|
74
|
-
|
80
|
+
var result: TimeInterval = 0
|
81
|
+
owner.executeOnAudioQueue { [self] in
|
82
|
+
if channels.count != 1 {
|
83
|
+
result = 0
|
84
|
+
return
|
85
|
+
}
|
86
|
+
let player: AVAudioPlayer = channels[playIndex]
|
87
|
+
result = player.duration
|
75
88
|
}
|
76
|
-
|
77
|
-
let player: AVAudioPlayer = channels[playIndex]
|
78
|
-
|
79
|
-
return player.duration
|
89
|
+
return result
|
80
90
|
}
|
81
91
|
|
82
92
|
func play(time: TimeInterval, delay: TimeInterval) {
|
83
|
-
|
93
|
+
owner.executeOnAudioQueue { [self] in
|
94
|
+
guard !channels.isEmpty else {
|
95
|
+
NSLog("No channels available")
|
96
|
+
return
|
97
|
+
}
|
98
|
+
guard playIndex < channels.count else {
|
99
|
+
NSLog("PlayIndex out of bounds")
|
100
|
+
playIndex = 0
|
101
|
+
return
|
102
|
+
}
|
84
103
|
|
85
|
-
|
86
|
-
player = channels[playIndex]
|
104
|
+
let player = channels[playIndex]
|
87
105
|
player.currentTime = time
|
88
106
|
player.numberOfLoops = 0
|
89
107
|
if delay > 0 {
|
@@ -93,100 +111,137 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
93
111
|
}
|
94
112
|
playIndex += 1
|
95
113
|
playIndex = playIndex % channels.count
|
114
|
+
NSLog("About to start timer updates")
|
115
|
+
startCurrentTimeUpdates()
|
96
116
|
}
|
97
117
|
}
|
98
118
|
|
99
119
|
func playWithFade(time: TimeInterval) {
|
100
|
-
|
101
|
-
|
120
|
+
owner.executeOnAudioQueue { [self] in
|
121
|
+
guard !channels.isEmpty else {
|
122
|
+
NSLog("No channels available")
|
123
|
+
return
|
124
|
+
}
|
125
|
+
guard playIndex < channels.count else {
|
126
|
+
NSLog("PlayIndex out of bounds")
|
127
|
+
playIndex = 0
|
128
|
+
return
|
129
|
+
}
|
102
130
|
|
103
|
-
|
104
|
-
player.
|
105
|
-
|
106
|
-
player.
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
131
|
+
let player: AVAudioPlayer = channels[playIndex]
|
132
|
+
player.currentTime = time
|
133
|
+
|
134
|
+
if !player.isPlaying {
|
135
|
+
player.numberOfLoops = 0
|
136
|
+
player.volume = initialVolume
|
137
|
+
player.play()
|
138
|
+
playIndex += 1
|
139
|
+
playIndex = playIndex % channels.count
|
140
|
+
NSLog("PlayWithFade: About to start timer updates")
|
141
|
+
startCurrentTimeUpdates()
|
142
|
+
} else {
|
143
|
+
if player.volume < initialVolume {
|
144
|
+
player.volume += self.FADESTEP
|
145
|
+
}
|
112
146
|
}
|
113
147
|
}
|
114
|
-
|
115
148
|
}
|
116
149
|
|
117
150
|
func pause() {
|
118
|
-
|
119
|
-
|
151
|
+
owner.executeOnAudioQueue { [self] in
|
152
|
+
stopCurrentTimeUpdates()
|
153
|
+
let player: AVAudioPlayer = channels[playIndex]
|
154
|
+
player.pause()
|
155
|
+
}
|
120
156
|
}
|
121
157
|
|
122
158
|
func resume() {
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
159
|
+
owner.executeOnAudioQueue { [self] in
|
160
|
+
let player: AVAudioPlayer = channels[playIndex]
|
161
|
+
let timeOffset = player.deviceCurrentTime + 0.01
|
162
|
+
player.play(atTime: timeOffset)
|
163
|
+
NSLog("Resume: About to start timer updates")
|
164
|
+
startCurrentTimeUpdates()
|
165
|
+
}
|
127
166
|
}
|
128
167
|
|
129
168
|
func stop() {
|
130
|
-
|
131
|
-
|
169
|
+
owner.executeOnAudioQueue { [self] in
|
170
|
+
stopCurrentTimeUpdates()
|
171
|
+
for player in channels {
|
172
|
+
if player.isPlaying {
|
173
|
+
player.stop()
|
174
|
+
}
|
175
|
+
player.currentTime = 0
|
176
|
+
player.numberOfLoops = 0
|
177
|
+
}
|
178
|
+
playIndex = 0
|
132
179
|
}
|
133
180
|
}
|
134
181
|
|
135
182
|
func stopWithFade() {
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
183
|
+
owner.executeOnAudioQueue { [self] in
|
184
|
+
let player: AVAudioPlayer = channels[playIndex]
|
185
|
+
if player.isPlaying {
|
186
|
+
if player.volume > self.FADESTEP {
|
187
|
+
player.volume -= self.FADESTEP
|
188
|
+
// Schedule next fade step
|
189
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(Int(self.FADEDELAY * 1000))) { [weak self] in
|
190
|
+
self?.stopWithFade()
|
191
|
+
}
|
192
|
+
} else {
|
193
|
+
// Volume is near 0, actually stop
|
194
|
+
player.volume = 0
|
195
|
+
self.stop()
|
196
|
+
}
|
148
197
|
}
|
149
198
|
}
|
150
199
|
}
|
151
200
|
|
152
201
|
func loop() {
|
153
|
-
self
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
202
|
+
owner.executeOnAudioQueue { [self] in
|
203
|
+
self.stop()
|
204
|
+
let player: AVAudioPlayer = channels[playIndex]
|
205
|
+
player.delegate = self
|
206
|
+
player.numberOfLoops = -1
|
207
|
+
player.play()
|
208
|
+
playIndex += 1
|
209
|
+
playIndex = playIndex % channels.count
|
210
|
+
NSLog("Loop: About to start timer updates")
|
211
|
+
startCurrentTimeUpdates()
|
212
|
+
}
|
160
213
|
}
|
161
214
|
|
162
215
|
func unload() {
|
163
|
-
self
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
//
|
168
|
-
// player = nil
|
169
|
-
// }
|
170
|
-
channels = []
|
216
|
+
owner.executeOnAudioQueue { [self] in
|
217
|
+
self.stop()
|
218
|
+
channels = []
|
219
|
+
}
|
171
220
|
}
|
172
221
|
|
173
222
|
func setVolume(volume: NSNumber!) {
|
174
|
-
|
175
|
-
player
|
223
|
+
owner.executeOnAudioQueue { [self] in
|
224
|
+
for player in channels {
|
225
|
+
player.volume = volume.floatValue
|
226
|
+
}
|
176
227
|
}
|
177
228
|
}
|
178
229
|
|
179
230
|
func setRate(rate: NSNumber!) {
|
180
|
-
|
181
|
-
player
|
231
|
+
owner.executeOnAudioQueue { [self] in
|
232
|
+
for player in channels {
|
233
|
+
player.rate = rate.floatValue
|
234
|
+
}
|
182
235
|
}
|
183
236
|
}
|
184
237
|
|
185
238
|
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
186
|
-
|
187
|
-
|
188
|
-
"
|
189
|
-
|
239
|
+
owner.executeOnAudioQueue { [self] in
|
240
|
+
NSLog("playerDidFinish")
|
241
|
+
self.owner.notifyListeners("complete", data: [
|
242
|
+
"assetId": self.assetId
|
243
|
+
])
|
244
|
+
}
|
190
245
|
}
|
191
246
|
|
192
247
|
func playerDecodeError(player: AVAudioPlayer!, error: NSError!) {
|
@@ -194,11 +249,62 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
194
249
|
}
|
195
250
|
|
196
251
|
func isPlaying() -> Bool {
|
197
|
-
|
198
|
-
|
252
|
+
var result: Bool = false
|
253
|
+
owner.executeOnAudioQueue { [self] in
|
254
|
+
if channels.count != 1 {
|
255
|
+
result = false
|
256
|
+
return
|
257
|
+
}
|
258
|
+
let player: AVAudioPlayer = channels[playIndex]
|
259
|
+
result = player.isPlaying
|
199
260
|
}
|
261
|
+
return result
|
262
|
+
}
|
263
|
+
|
264
|
+
internal func startCurrentTimeUpdates() {
|
265
|
+
NSLog("Starting timer updates")
|
266
|
+
DispatchQueue.main.async { [weak self] in
|
267
|
+
guard let self = self else {
|
268
|
+
NSLog("Self is nil in timer start")
|
269
|
+
return
|
270
|
+
}
|
271
|
+
|
272
|
+
self.currentTimeTimer?.invalidate()
|
273
|
+
self.currentTimeTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in
|
274
|
+
guard let self = self else {
|
275
|
+
NSLog("Self is nil in timer callback")
|
276
|
+
return
|
277
|
+
}
|
278
|
+
|
279
|
+
var shouldNotify = false
|
280
|
+
var currentTime: TimeInterval = 0
|
200
281
|
|
201
|
-
|
202
|
-
|
282
|
+
self.owner.executeOnAudioQueue {
|
283
|
+
shouldNotify = self.isPlaying()
|
284
|
+
NSLog("isPlaying returned: \(shouldNotify)")
|
285
|
+
if shouldNotify {
|
286
|
+
currentTime = self.getCurrentTime()
|
287
|
+
NSLog("getCurrentTime returned: \(currentTime)")
|
288
|
+
}
|
289
|
+
}
|
290
|
+
|
291
|
+
if shouldNotify {
|
292
|
+
NSLog("Calling notifyCurrentTime")
|
293
|
+
self.owner.notifyCurrentTime(self)
|
294
|
+
} else {
|
295
|
+
NSLog("Stopping timer - not playing")
|
296
|
+
self.stopCurrentTimeUpdates()
|
297
|
+
}
|
298
|
+
}
|
299
|
+
RunLoop.current.add(self.currentTimeTimer!, forMode: .common)
|
300
|
+
NSLog("Timer added to RunLoop")
|
301
|
+
}
|
302
|
+
}
|
303
|
+
|
304
|
+
internal func stopCurrentTimeUpdates() {
|
305
|
+
DispatchQueue.main.async { [weak self] in
|
306
|
+
self?.currentTimeTimer?.invalidate()
|
307
|
+
self?.currentTimeTimer = nil
|
308
|
+
}
|
203
309
|
}
|
204
310
|
}
|
package/ios/Plugin/Plugin.swift
CHANGED
@@ -10,7 +10,7 @@ enum MyError: Error {
|
|
10
10
|
/// Please read the Capacitor iOS Plugin Development Guide
|
11
11
|
/// here: https://capacitor.ionicframework.com/docs/plugins/ios
|
12
12
|
@objc(NativeAudio)
|
13
|
-
public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
13
|
+
public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
14
14
|
public let identifier = "NativeAudio"
|
15
15
|
public let jsName = "NativeAudio"
|
16
16
|
public let pluginMethods: [CAPPluginMethod] = [
|
@@ -28,9 +28,10 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
28
28
|
CAPPluginMethod(name: "getCurrentTime", returnType: CAPPluginReturnPromise),
|
29
29
|
CAPPluginMethod(name: "getDuration", returnType: CAPPluginReturnPromise),
|
30
30
|
CAPPluginMethod(name: "resume", returnType: CAPPluginReturnPromise),
|
31
|
-
CAPPluginMethod(name: "setCurrentTime", returnType: CAPPluginReturnPromise)
|
31
|
+
CAPPluginMethod(name: "setCurrentTime", returnType: CAPPluginReturnPromise),
|
32
|
+
CAPPluginMethod(name: "clearCache", returnType: CAPPluginReturnPromise)
|
32
33
|
]
|
33
|
-
|
34
|
+
internal let audioQueue = DispatchQueue(label: "ee.forgr.audio.queue", qos: .userInitiated, attributes: .concurrent)
|
34
35
|
private var audioList: [String: Any] = [:] {
|
35
36
|
didSet {
|
36
37
|
// Ensure audioList modifications happen on audioQueue
|
@@ -165,18 +166,13 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
165
166
|
let time = call.getDouble("time") ?? 0
|
166
167
|
let delay = call.getDouble("delay") ?? 0
|
167
168
|
|
168
|
-
|
169
|
-
|
170
|
-
return
|
171
|
-
}
|
172
|
-
|
173
|
-
audioQueue.async {
|
174
|
-
guard !self.audioList.isEmpty else {
|
169
|
+
audioQueue.sync { [self] in // Changed from async to sync for consistency
|
170
|
+
guard !audioList.isEmpty else {
|
175
171
|
call.reject("Audio list is empty")
|
176
172
|
return
|
177
173
|
}
|
178
174
|
|
179
|
-
guard let asset =
|
175
|
+
guard let asset = audioList[audioId] else {
|
180
176
|
call.reject(Constant.ErrorAssetNotFound)
|
181
177
|
return
|
182
178
|
}
|
@@ -200,29 +196,9 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
200
196
|
}
|
201
197
|
|
202
198
|
@objc private func getAudioAsset(_ call: CAPPluginCall) -> AudioAsset? {
|
203
|
-
let audioId = call.getString(Constant.AssetIdKey) ?? ""
|
204
|
-
if audioId.isEmpty {
|
205
|
-
call.reject(Constant.ErrorAssetId)
|
206
|
-
return nil
|
207
|
-
}
|
208
|
-
|
209
199
|
var asset: AudioAsset?
|
210
|
-
audioQueue.sync {
|
211
|
-
|
212
|
-
call.reject("Audio list is empty")
|
213
|
-
return
|
214
|
-
}
|
215
|
-
|
216
|
-
guard let foundAsset = self.audioList[audioId] as? AudioAsset else {
|
217
|
-
call.reject(Constant.ErrorAssetNotFound + " - " + audioId)
|
218
|
-
return
|
219
|
-
}
|
220
|
-
asset = foundAsset
|
221
|
-
}
|
222
|
-
|
223
|
-
if asset == nil {
|
224
|
-
call.reject("Failed to get audio asset")
|
225
|
-
return nil
|
200
|
+
audioQueue.sync { [self] in // Read operation
|
201
|
+
asset = self.audioList[call.getString(Constant.AssetIdKey) ?? ""] as? AudioAsset
|
226
202
|
}
|
227
203
|
return asset
|
228
204
|
}
|
@@ -380,12 +356,20 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
380
356
|
}
|
381
357
|
}
|
382
358
|
|
383
|
-
|
359
|
+
@objc func clearCache(_ call: CAPPluginCall) {
|
360
|
+
audioQueue.async {
|
361
|
+
RemoteAudioAsset.clearCache()
|
362
|
+
call.resolve()
|
363
|
+
}
|
364
|
+
}
|
365
|
+
|
366
|
+
@objc private func preloadAsset(_ call: CAPPluginCall, isComplex complex: Bool) {
|
384
367
|
let audioId = call.getString(Constant.AssetIdKey) ?? ""
|
385
368
|
let channels: Int?
|
386
369
|
let volume: Float?
|
387
370
|
let delay: Float?
|
388
371
|
var isLocalUrl: Bool = call.getBool("isUrl") ?? false
|
372
|
+
|
389
373
|
if audioId == "" {
|
390
374
|
call.reject(Constant.ErrorAssetId)
|
391
375
|
return
|
@@ -397,23 +381,22 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
397
381
|
channels = call.getInt("channels") ?? 1
|
398
382
|
delay = call.getFloat("delay") ?? 1.0
|
399
383
|
} else {
|
400
|
-
channels =
|
401
|
-
volume = 0
|
402
|
-
delay = 0
|
384
|
+
channels = 1
|
385
|
+
volume = 1.0
|
386
|
+
delay = 0.0
|
403
387
|
isLocalUrl = false
|
404
388
|
}
|
405
389
|
|
406
|
-
|
407
|
-
audioList
|
408
|
-
|
390
|
+
audioQueue.sync(flags: .barrier) { [self] in
|
391
|
+
if audioList.isEmpty {
|
392
|
+
audioList = [:]
|
393
|
+
}
|
394
|
+
|
395
|
+
if audioList[audioId] != nil {
|
396
|
+
call.reject(Constant.ErrorAssetAlreadyLoaded + " - " + audioId)
|
397
|
+
return
|
398
|
+
}
|
409
399
|
|
410
|
-
let asset = audioList[audioId]
|
411
|
-
let queue = DispatchQueue(label: "ee.forgr.audio.simple.queue", qos: .userInitiated)
|
412
|
-
if asset != nil {
|
413
|
-
call.reject(Constant.ErrorAssetAlreadyLoaded + " - " + audioId)
|
414
|
-
return
|
415
|
-
}
|
416
|
-
queue.async {
|
417
400
|
var basePath: String?
|
418
401
|
if let url = URL(string: assetPath), url.scheme != nil {
|
419
402
|
// Handle remote URL
|
@@ -423,9 +406,7 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
423
406
|
return
|
424
407
|
} else if isLocalUrl == false {
|
425
408
|
// Handle public folder
|
426
|
-
// if assetPath doesnt start with public/ add it
|
427
409
|
assetPath = assetPath.starts(with: "public/") ? assetPath : "public/" + assetPath
|
428
|
-
|
429
410
|
let assetPathSplit = assetPath.components(separatedBy: ".")
|
430
411
|
basePath = Bundle.main.path(forResource: assetPathSplit[0], ofType: assetPathSplit[1])
|
431
412
|
} else {
|
@@ -482,9 +463,34 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate {
|
|
482
463
|
}
|
483
464
|
|
484
465
|
if self.fadeMusic {
|
485
|
-
audioAsset.
|
466
|
+
audioAsset.stopWithFade()
|
486
467
|
} else {
|
487
468
|
audioAsset.stop()
|
488
469
|
}
|
489
470
|
}
|
471
|
+
|
472
|
+
internal func executeOnAudioQueue(_ block: @escaping () -> Void) {
|
473
|
+
if DispatchQueue.getSpecific(key: queueKey) != nil {
|
474
|
+
block() // Already on queue
|
475
|
+
} else {
|
476
|
+
audioQueue.sync(flags: .barrier) {
|
477
|
+
block()
|
478
|
+
}
|
479
|
+
}
|
480
|
+
}
|
481
|
+
|
482
|
+
@objc func notifyCurrentTime(_ asset: AudioAsset) {
|
483
|
+
NSLog("notifyCurrentTime called in Plugin")
|
484
|
+
audioQueue.sync {
|
485
|
+
let rawTime = asset.getCurrentTime()
|
486
|
+
// Round to nearest 100ms (0.1 seconds)
|
487
|
+
let currentTime = round(rawTime * 10) / 10
|
488
|
+
NSLog("About to notify listeners with time: \(currentTime)")
|
489
|
+
notifyListeners("currentTime", data: [
|
490
|
+
"currentTime": currentTime,
|
491
|
+
"assetId": asset.assetId
|
492
|
+
])
|
493
|
+
NSLog("Listeners notified")
|
494
|
+
}
|
495
|
+
}
|
490
496
|
}
|