@capgo/native-audio 7.3.10 → 7.3.11
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/ios/Plugin/AudioAsset.swift +14 -0
- package/ios/Plugin/Plugin.swift +44 -10
- package/package.json +1 -1
@@ -153,6 +153,9 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
153
153
|
* - delay: Delay before playback in seconds
|
154
154
|
*/
|
155
155
|
func play(time: TimeInterval, delay: TimeInterval) {
|
156
|
+
stopCurrentTimeUpdates()
|
157
|
+
stopFadeTimer()
|
158
|
+
|
156
159
|
owner?.executeOnAudioQueue { [self] in
|
157
160
|
guard !channels.isEmpty else { return }
|
158
161
|
|
@@ -161,6 +164,9 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
161
164
|
playIndex = 0
|
162
165
|
}
|
163
166
|
|
167
|
+
// Ensure the audio session is active before playing
|
168
|
+
owner?.activateSession()
|
169
|
+
|
164
170
|
let player = channels[playIndex]
|
165
171
|
// Ensure time is within valid range
|
166
172
|
let validTime = min(max(time, 0), player.duration)
|
@@ -175,6 +181,7 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
175
181
|
} else {
|
176
182
|
player.play()
|
177
183
|
}
|
184
|
+
|
178
185
|
playIndex = (playIndex + 1) % channels.count
|
179
186
|
startCurrentTimeUpdates()
|
180
187
|
}
|
@@ -368,11 +375,18 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
368
375
|
}
|
369
376
|
}
|
370
377
|
|
378
|
+
/**
|
379
|
+
* AVAudioPlayerDelegate method called when playback finishes
|
380
|
+
*/
|
371
381
|
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
372
382
|
owner?.executeOnAudioQueue { [self] in
|
373
383
|
self.owner?.notifyListeners("complete", data: [
|
374
384
|
"assetId": self.assetId
|
375
385
|
])
|
386
|
+
|
387
|
+
// Notify the owner that this player finished
|
388
|
+
// The owner will check if any other assets are still playing
|
389
|
+
owner?.audioPlayerDidFinishPlaying(player, successfully: flag)
|
376
390
|
}
|
377
391
|
}
|
378
392
|
|
package/ios/Plugin/Plugin.swift
CHANGED
@@ -83,9 +83,9 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
83
83
|
|
84
84
|
private func setupAudioSession() {
|
85
85
|
do {
|
86
|
+
// Only set the category without immediately activating/deactivating
|
86
87
|
try self.session.setCategory(AVAudioSession.Category.playback, options: .mixWithOthers)
|
87
|
-
|
88
|
-
try self.session.setActive(false)
|
88
|
+
// Don't activate/deactivate in setup - we'll do this explicitly when needed
|
89
89
|
} catch {
|
90
90
|
print("Failed to setup audio session: \(error)")
|
91
91
|
}
|
@@ -135,8 +135,7 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
135
135
|
|
136
136
|
// Use a single audio session configuration block for better atomicity
|
137
137
|
do {
|
138
|
-
|
139
|
-
|
138
|
+
// Set category first
|
140
139
|
if focus {
|
141
140
|
try self.session.setCategory(AVAudioSession.Category.playback, options: .duckOthers)
|
142
141
|
} else if !ignoreSilent {
|
@@ -144,9 +143,10 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
144
143
|
} else {
|
145
144
|
try self.session.setCategory(AVAudioSession.Category.playback, options: .mixWithOthers)
|
146
145
|
}
|
147
|
-
|
148
|
-
if
|
149
|
-
|
146
|
+
|
147
|
+
// Only activate if needed (background mode)
|
148
|
+
if background {
|
149
|
+
try self.session.setActive(true)
|
150
150
|
}
|
151
151
|
|
152
152
|
} catch {
|
@@ -175,7 +175,10 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
175
175
|
|
176
176
|
func activateSession() {
|
177
177
|
do {
|
178
|
-
|
178
|
+
// Only activate if not already active
|
179
|
+
if !session.isOtherAudioPlaying {
|
180
|
+
try self.session.setActive(true)
|
181
|
+
}
|
179
182
|
} catch {
|
180
183
|
print("Failed to set session active: \(error)")
|
181
184
|
}
|
@@ -183,14 +186,45 @@ public class NativeAudio: CAPPlugin, AVAudioPlayerDelegate, CAPBridgedPlugin {
|
|
183
186
|
|
184
187
|
func endSession() {
|
185
188
|
do {
|
186
|
-
|
189
|
+
// Check if any audio assets are still playing before deactivating
|
190
|
+
let hasPlayingAssets = audioQueue.sync {
|
191
|
+
return self.audioList.values.contains { asset in
|
192
|
+
if let audioAsset = asset as? AudioAsset {
|
193
|
+
return audioAsset.isPlaying()
|
194
|
+
}
|
195
|
+
return false
|
196
|
+
}
|
197
|
+
}
|
198
|
+
|
199
|
+
// Only deactivate if no assets are playing
|
200
|
+
if !hasPlayingAssets {
|
201
|
+
try self.session.setActive(false, options: .notifyOthersOnDeactivation)
|
202
|
+
}
|
187
203
|
} catch {
|
188
204
|
print("Failed to deactivate audio session: \(error)")
|
189
205
|
}
|
190
206
|
}
|
191
207
|
|
192
208
|
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
193
|
-
|
209
|
+
// Don't immediately end the session here, as other players might still be active
|
210
|
+
// Instead, check if all players are done
|
211
|
+
audioQueue.async { [weak self] in
|
212
|
+
guard let self = self else { return }
|
213
|
+
|
214
|
+
// Avoid recursive calls by checking if the asset is still in the list
|
215
|
+
let hasPlayingAssets = self.audioList.values.contains { asset in
|
216
|
+
if let audioAsset = asset as? AudioAsset {
|
217
|
+
// Check if the asset has any playing channels other than the one that just finished
|
218
|
+
return audioAsset.channels.contains { $0 != player && $0.isPlaying }
|
219
|
+
}
|
220
|
+
return false
|
221
|
+
}
|
222
|
+
|
223
|
+
// Only end the session if no more assets are playing
|
224
|
+
if !hasPlayingAssets {
|
225
|
+
self.endSession()
|
226
|
+
}
|
227
|
+
}
|
194
228
|
}
|
195
229
|
|
196
230
|
@objc func play(_ call: CAPPluginCall) {
|