@capgo/native-audio 6.4.20 → 6.4.22
Sign up to get free protection for your applications and to get access to all the features.
- package/android/src/main/java/ee/forgr/audio/AudioAsset.java +11 -0
- package/android/src/main/java/ee/forgr/audio/AudioCompletionListener.java +5 -0
- package/android/src/main/java/ee/forgr/audio/AudioDispatcher.java +1 -1
- package/android/src/main/java/ee/forgr/audio/NativeAudio.java +2 -0
- package/android/src/main/java/ee/forgr/audio/RemoteAudioAsset.java +3 -0
- package/ios/Plugin/RemoteAudioAsset.swift +68 -24
- package/package.json +1 -1
@@ -13,6 +13,7 @@ public class AudioAsset {
|
|
13
13
|
private int playIndex = 0;
|
14
14
|
private final String assetId;
|
15
15
|
protected final NativeAudio owner;
|
16
|
+
protected AudioCompletionListener completionListener;
|
16
17
|
|
17
18
|
AudioAsset(
|
18
19
|
NativeAudio owner,
|
@@ -167,4 +168,14 @@ public class AudioAsset {
|
|
167
168
|
|
168
169
|
return audioList.get(playIndex).isPlaying();
|
169
170
|
}
|
171
|
+
|
172
|
+
public void setCompletionListener(AudioCompletionListener listener) {
|
173
|
+
this.completionListener = listener;
|
174
|
+
}
|
175
|
+
|
176
|
+
protected void notifyCompletion() {
|
177
|
+
if (completionListener != null) {
|
178
|
+
completionListener.onCompletion(this.assetId);
|
179
|
+
}
|
180
|
+
}
|
170
181
|
}
|
@@ -504,6 +504,7 @@ public class NativeAudio
|
|
504
504
|
audioChannelNum,
|
505
505
|
volume
|
506
506
|
);
|
507
|
+
remoteAudioAsset.setCompletionListener(this::dispatchComplete);
|
507
508
|
audioAssetList.put(audioId, remoteAudioAsset);
|
508
509
|
} else if (
|
509
510
|
uri.getScheme() != null && uri.getScheme().equals("file")
|
@@ -535,6 +536,7 @@ public class NativeAudio
|
|
535
536
|
audioChannelNum,
|
536
537
|
volume
|
537
538
|
);
|
539
|
+
asset.setCompletionListener(this::dispatchComplete);
|
538
540
|
audioAssetList.put(audioId, asset);
|
539
541
|
} else {
|
540
542
|
throw new IllegalArgumentException(
|
@@ -45,6 +45,9 @@ public class RemoteAudioAsset extends AudioAsset {
|
|
45
45
|
isPrepared = true;
|
46
46
|
Log.d(TAG, "MediaPlayer prepared for " + uri.toString());
|
47
47
|
});
|
48
|
+
mediaPlayer.setOnCompletionListener(mp -> {
|
49
|
+
notifyCompletion();
|
50
|
+
});
|
48
51
|
mediaPlayer.setOnErrorListener((mp, what, extra) -> {
|
49
52
|
Log.e(TAG, "MediaPlayer error: " + what + ", " + extra);
|
50
53
|
return false;
|
@@ -1,74 +1,118 @@
|
|
1
1
|
import AVFoundation
|
2
2
|
|
3
3
|
public class RemoteAudioAsset: AudioAsset {
|
4
|
-
var
|
5
|
-
var
|
4
|
+
var playerItems: [AVPlayerItem] = []
|
5
|
+
var players: [AVPlayer] = []
|
6
|
+
var playerObservers: [NSKeyValueObservation] = []
|
6
7
|
|
7
8
|
override init(owner: NativeAudio, withAssetId assetId: String, withPath path: String!, withChannels channels: Int!, withVolume volume: Float!, withFadeDelay delay: Float!) {
|
8
9
|
super.init(owner: owner, withAssetId: assetId, withPath: path, withChannels: channels, withVolume: volume, withFadeDelay: delay)
|
9
10
|
|
10
11
|
if let url = URL(string: path) {
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
for _ in 0..<channels {
|
13
|
+
let playerItem = AVPlayerItem(url: url)
|
14
|
+
let player = AVPlayer(playerItem: playerItem)
|
15
|
+
player.volume = volume
|
16
|
+
self.playerItems.append(playerItem)
|
17
|
+
self.players.append(player)
|
18
|
+
|
19
|
+
// Add observer for playback finished
|
20
|
+
let observer = player.observe(\.timeControlStatus) { [weak self] player, _ in
|
21
|
+
if player.timeControlStatus == .paused && player.currentItem?.currentTime() == player.currentItem?.duration {
|
22
|
+
self?.playerDidFinishPlaying(player: player)
|
23
|
+
}
|
24
|
+
}
|
25
|
+
self.playerObservers.append(observer)
|
26
|
+
}
|
14
27
|
}
|
15
28
|
}
|
16
29
|
|
30
|
+
func playerDidFinishPlaying(player: AVPlayer) {
|
31
|
+
self.owner.notifyListeners("complete", data: [
|
32
|
+
"assetId": self.assetId
|
33
|
+
])
|
34
|
+
}
|
35
|
+
|
17
36
|
override func play(time: TimeInterval, delay: TimeInterval) {
|
18
|
-
guard
|
37
|
+
guard !players.isEmpty else { return }
|
38
|
+
let player = players[playIndex]
|
19
39
|
if delay > 0 {
|
20
|
-
// Calculate the future time to play
|
21
40
|
let timeToPlay = CMTimeAdd(CMTimeMakeWithSeconds(player.currentTime().seconds, preferredTimescale: 1), CMTimeMakeWithSeconds(delay, preferredTimescale: 1))
|
22
41
|
player.seek(to: timeToPlay)
|
23
42
|
} else {
|
24
43
|
player.seek(to: CMTimeMakeWithSeconds(time, preferredTimescale: 1))
|
25
44
|
}
|
26
45
|
player.play()
|
46
|
+
playIndex = (playIndex + 1) % players.count
|
27
47
|
}
|
28
48
|
|
29
49
|
override func pause() {
|
30
|
-
|
50
|
+
guard !players.isEmpty else { return }
|
51
|
+
let player = players[playIndex]
|
52
|
+
player.pause()
|
31
53
|
}
|
32
54
|
|
33
55
|
override func resume() {
|
34
|
-
|
56
|
+
guard !players.isEmpty else { return }
|
57
|
+
let player = players[playIndex]
|
58
|
+
player.play()
|
35
59
|
}
|
36
60
|
|
37
61
|
override func stop() {
|
38
|
-
player
|
39
|
-
|
62
|
+
for player in players {
|
63
|
+
player.pause()
|
64
|
+
player.seek(to: CMTime.zero)
|
65
|
+
}
|
40
66
|
}
|
41
67
|
|
42
68
|
override func loop() {
|
43
|
-
player
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
69
|
+
for player in players {
|
70
|
+
player.actionAtItemEnd = .none
|
71
|
+
NotificationCenter.default.addObserver(self,
|
72
|
+
selector: #selector(playerItemDidReachEnd(notification:)),
|
73
|
+
name: .AVPlayerItemDidPlayToEndTime,
|
74
|
+
object: player.currentItem)
|
75
|
+
player.play()
|
76
|
+
}
|
49
77
|
}
|
50
78
|
|
51
79
|
@objc func playerItemDidReachEnd(notification: Notification) {
|
52
|
-
player
|
53
|
-
player
|
80
|
+
guard let player = notification.object as? AVPlayer else { return }
|
81
|
+
player.seek(to: CMTime.zero)
|
82
|
+
player.play()
|
54
83
|
}
|
55
84
|
|
56
85
|
override func unload() {
|
57
86
|
stop()
|
58
87
|
NotificationCenter.default.removeObserver(self)
|
59
|
-
|
60
|
-
|
88
|
+
// Remove KVO observers
|
89
|
+
for observer in playerObservers {
|
90
|
+
observer.invalidate()
|
91
|
+
}
|
92
|
+
playerObservers = []
|
93
|
+
players = []
|
94
|
+
playerItems = []
|
61
95
|
}
|
62
96
|
|
63
97
|
override func setVolume(volume: NSNumber!) {
|
64
|
-
player
|
98
|
+
for player in players {
|
99
|
+
player.volume = volume.floatValue
|
100
|
+
}
|
65
101
|
}
|
66
102
|
|
67
103
|
override func setRate(rate: NSNumber!) {
|
68
|
-
player
|
104
|
+
for player in players {
|
105
|
+
player.rate = rate.floatValue
|
106
|
+
}
|
69
107
|
}
|
70
108
|
|
71
109
|
override func isPlaying() -> Bool {
|
72
|
-
return
|
110
|
+
return players.contains { $0.timeControlStatus == .playing }
|
111
|
+
}
|
112
|
+
|
113
|
+
override func getCurrentTime() -> TimeInterval {
|
114
|
+
guard !players.isEmpty else { return 0 }
|
115
|
+
let player = players[playIndex]
|
116
|
+
return player.currentTime().seconds
|
73
117
|
}
|
74
118
|
}
|