@capgo/native-audio 7.3.10 → 7.3.12
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 +21 -2
- package/ios/Plugin/Plugin.swift +44 -10
- package/package.json +1 -1
@@ -86,14 +86,19 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
86
86
|
}
|
87
87
|
|
88
88
|
deinit {
|
89
|
-
|
90
|
-
|
89
|
+
currentTimeTimer?.invalidate()
|
90
|
+
currentTimeTimer = nil
|
91
|
+
|
92
|
+
fadeTimer?.invalidate()
|
93
|
+
fadeTimer = nil
|
94
|
+
|
91
95
|
// Clean up any players that might still be playing
|
92
96
|
for player in channels {
|
93
97
|
if player.isPlaying {
|
94
98
|
player.stop()
|
95
99
|
}
|
96
100
|
}
|
101
|
+
channels = []
|
97
102
|
}
|
98
103
|
|
99
104
|
/**
|
@@ -153,6 +158,9 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
153
158
|
* - delay: Delay before playback in seconds
|
154
159
|
*/
|
155
160
|
func play(time: TimeInterval, delay: TimeInterval) {
|
161
|
+
stopCurrentTimeUpdates()
|
162
|
+
stopFadeTimer()
|
163
|
+
|
156
164
|
owner?.executeOnAudioQueue { [self] in
|
157
165
|
guard !channels.isEmpty else { return }
|
158
166
|
|
@@ -161,6 +169,9 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
161
169
|
playIndex = 0
|
162
170
|
}
|
163
171
|
|
172
|
+
// Ensure the audio session is active before playing
|
173
|
+
owner?.activateSession()
|
174
|
+
|
164
175
|
let player = channels[playIndex]
|
165
176
|
// Ensure time is within valid range
|
166
177
|
let validTime = min(max(time, 0), player.duration)
|
@@ -175,6 +186,7 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
175
186
|
} else {
|
176
187
|
player.play()
|
177
188
|
}
|
189
|
+
|
178
190
|
playIndex = (playIndex + 1) % channels.count
|
179
191
|
startCurrentTimeUpdates()
|
180
192
|
}
|
@@ -368,11 +380,18 @@ public class AudioAsset: NSObject, AVAudioPlayerDelegate {
|
|
368
380
|
}
|
369
381
|
}
|
370
382
|
|
383
|
+
/**
|
384
|
+
* AVAudioPlayerDelegate method called when playback finishes
|
385
|
+
*/
|
371
386
|
public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
|
372
387
|
owner?.executeOnAudioQueue { [self] in
|
373
388
|
self.owner?.notifyListeners("complete", data: [
|
374
389
|
"assetId": self.assetId
|
375
390
|
])
|
391
|
+
|
392
|
+
// Notify the owner that this player finished
|
393
|
+
// The owner will check if any other assets are still playing
|
394
|
+
owner?.audioPlayerDidFinishPlaying(player, successfully: flag)
|
376
395
|
}
|
377
396
|
}
|
378
397
|
|
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) {
|