capacitor-plugin-playlist 0.2.1 → 0.2.2
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/android/src/main/java/org/dwbn/plugins/playlist/RmxAudioPlayer.java +4 -10
- package/android/src/main/java/org/dwbn/plugins/playlist/manager/PlaylistManager.kt +2 -0
- package/android/src/main/java/org/dwbn/plugins/playlist/playlist/AudioPlaylistHandler.java +12 -2
- package/dist/docs.json +1 -1
- package/dist/esm/interfaces.d.ts +1 -1
- package/ios/Plugin/AVBidirectionalQueuePlayer.swift +11 -3
- package/ios/Plugin/RmxAudioPlayer.swift +30 -25
- package/package.json +4 -1
- package/android/local.properties +0 -8
|
@@ -107,6 +107,10 @@ public class RmxAudioPlayer implements PlaybackStatusListener<AudioTrack>,
|
|
|
107
107
|
JSONObject trackStatus = getPlayerStatus(item);
|
|
108
108
|
onStatus(RmxAudioStatusMessage.RMXSTATUS_COMPLETED, trackId, trackStatus);
|
|
109
109
|
}
|
|
110
|
+
|
|
111
|
+
if (!playlistManager.isNextAvailable()) {
|
|
112
|
+
onStatus(RmxAudioStatusMessage.RMXSTATUS_PLAYLIST_COMPLETED, "INVALID", null);
|
|
113
|
+
}
|
|
110
114
|
}
|
|
111
115
|
|
|
112
116
|
@Override
|
|
@@ -179,21 +183,11 @@ public class RmxAudioPlayer implements PlaybackStatusListener<AudioTrack>,
|
|
|
179
183
|
|
|
180
184
|
@Override
|
|
181
185
|
public void onItemPlaybackEnded(AudioTrack item) {
|
|
182
|
-
AudioTrack nextItem = playlistManager.getCurrentItem();
|
|
183
|
-
// String title = item != null ? item.getTitle() : "(null)";
|
|
184
|
-
// String currTitle = nextItem != null ? nextItem.getTitle() : "(null)";
|
|
185
|
-
// String currTrackId = nextItem != null ? nextItem.getTrackId() : null;
|
|
186
|
-
// Log.i(TAG, "onItemPlaybackEnded: ==> " + title + "," + trackId + " ==> next item: " + currTitle + "," + currTrackId);
|
|
187
|
-
|
|
188
186
|
if (item != null) {
|
|
189
187
|
String trackId = item.getTrackId();
|
|
190
188
|
JSONObject trackStatus = getPlayerStatus(item);
|
|
191
189
|
onStatus(RmxAudioStatusMessage.RMXSTATUS_STOPPED, trackId, trackStatus);
|
|
192
190
|
}
|
|
193
|
-
|
|
194
|
-
if (nextItem == null) { // if (!playlistManager.isNextAvailable()) {
|
|
195
|
-
onStatus(RmxAudioStatusMessage.RMXSTATUS_PLAYLIST_COMPLETED, "INVALID", null);
|
|
196
|
-
}
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
@Override
|
|
@@ -143,6 +143,7 @@ class PlaylistManager(application: Application) :
|
|
|
143
143
|
currentPosition = 0
|
|
144
144
|
beginPlayback(1, true)
|
|
145
145
|
}
|
|
146
|
+
this.playlistHandler!!.updateMediaControls()
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
fun addAllItems(its: List<AudioTrack>?) {
|
|
@@ -177,6 +178,7 @@ class PlaylistManager(application: Application) :
|
|
|
177
178
|
items = audioTracks
|
|
178
179
|
currentPosition = if (removingCurrent) currentPosition else audioTracks.indexOf(currentItem)
|
|
179
180
|
beginPlayback(currentPosition.toLong(), !wasPlaying)
|
|
181
|
+
this.playlistHandler!!.updateMediaControls()
|
|
180
182
|
return foundItem
|
|
181
183
|
}
|
|
182
184
|
|
|
@@ -49,9 +49,19 @@ public class AudioPlaylistHandler<I extends PlaylistItem, M extends BasePlaylist
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
public void next() {
|
|
52
|
-
if (getPlaylistManager().
|
|
53
|
-
|
|
52
|
+
if (!getPlaylistManager().isNextAvailable()) {
|
|
53
|
+
return;
|
|
54
54
|
}
|
|
55
|
+
getPlaylistManager().next();
|
|
56
|
+
startItemPlayback(0, !this.isPlaying());
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public void previous() {
|
|
60
|
+
if (!getPlaylistManager().isPreviousAvailable()) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
getPlaylistManager().previous();
|
|
64
|
+
startItemPlayback(0, !this.isPlaying());
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
@Override
|
package/dist/docs.json
CHANGED
|
@@ -531,7 +531,7 @@
|
|
|
531
531
|
"tags": [],
|
|
532
532
|
"docs": "If retainPosition is true, this value will tell the plugin the uid of the \"current\" item to start from,\nrather than letting the plugin decide based on current playback.",
|
|
533
533
|
"complexTypes": [],
|
|
534
|
-
"type": "
|
|
534
|
+
"type": "string | undefined"
|
|
535
535
|
},
|
|
536
536
|
{
|
|
537
537
|
"name": "startPaused",
|
package/dist/esm/interfaces.d.ts
CHANGED
|
@@ -66,7 +66,7 @@ export interface PlaylistItemOptions {
|
|
|
66
66
|
* If retainPosition is true, this value will tell the plugin the uid of the "current" item to start from,
|
|
67
67
|
* rather than letting the plugin decide based on current playback.
|
|
68
68
|
*/
|
|
69
|
-
playFromId?:
|
|
69
|
+
playFromId?: string;
|
|
70
70
|
/**
|
|
71
71
|
* If playback should immediately begin when calling setPlaylistItems on the plugin.
|
|
72
72
|
* Default is false;
|
|
@@ -155,7 +155,6 @@ class AVBidirectionalQueuePlayer: AVQueuePlayer {
|
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
func replaceAllItems(with items: [AudioTrack]) {
|
|
158
|
-
print("AVBI, replaceAllItems")
|
|
159
158
|
removeAllItemsSilently()
|
|
160
159
|
appendItems(items)
|
|
161
160
|
}
|
|
@@ -197,15 +196,24 @@ class AVBidirectionalQueuePlayer: AVQueuePlayer {
|
|
|
197
196
|
}*/
|
|
198
197
|
// This does the same thing as the normal AVQueuePlayer removeAllItems, but clears our collection copy
|
|
199
198
|
override func removeAllItems() {
|
|
200
|
-
print("removeAllItems")
|
|
201
199
|
super.removeAllItems()
|
|
202
200
|
queuedAudioTracks.removeAll()
|
|
203
201
|
|
|
204
202
|
NotificationCenter.default.post(name: NSNotification.Name(AVBidirectionalQueueCleared), object: self, userInfo: nil)
|
|
205
203
|
}
|
|
206
204
|
|
|
205
|
+
func removeAllTrackObservers() {
|
|
206
|
+
for item in queuedAudioTracks {
|
|
207
|
+
removeTrackObservers(item)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
func removeTrackObservers(_ playerItem: AudioTrack?) {
|
|
212
|
+
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemDidPlayToEndTime, object: playerItem)
|
|
213
|
+
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemPlaybackStalled, object: playerItem)
|
|
214
|
+
}
|
|
215
|
+
|
|
207
216
|
func removeAllItemsSilently() {
|
|
208
|
-
print("removeAllItemsSilently")
|
|
209
217
|
super.removeAllItems()
|
|
210
218
|
queuedAudioTracks.removeAll()
|
|
211
219
|
}
|
|
@@ -64,7 +64,7 @@ final class RmxAudioPlayer: NSObject {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
func setPlaylistItems(_ items: [AudioTrack], options: [String:Any]) {
|
|
67
|
-
print("RmxAudioPlayer.execute=setPlaylistItems, \(options), \(items)")
|
|
67
|
+
print("RmxAudioPlayer.execute=setPlaylistItems, \(options), \(items.count)")
|
|
68
68
|
|
|
69
69
|
var seekToPosition: Float = 0.0
|
|
70
70
|
let retainPosition = options["retainPosition"] != nil ? (options["retainPosition"] as? Bool) ?? false : false
|
|
@@ -84,19 +84,14 @@ final class RmxAudioPlayer: NSObject {
|
|
|
84
84
|
let result = findTrack(byId: playFromId)
|
|
85
85
|
let idx = (result?["index"] as? NSNumber)?.intValue ?? 0
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
avQueuePlayer.setCurrentIndex(idx)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
87
|
+
setTracks(items, startIndex: idx, startPosition: seekToPosition)
|
|
88
|
+
|
|
93
89
|
// This will wait for the AVPlayerItemStatusReadyToPlay status change, and then trigger playback.
|
|
94
90
|
isWaitingToStartPlayback = !startPaused
|
|
95
91
|
if isWaitingToStartPlayback {
|
|
96
92
|
print("RmxAudioPlayer[setPlaylistItems] will wait for ready event to begin playback")
|
|
97
93
|
}
|
|
98
94
|
|
|
99
|
-
setTracks(items, startPosition: seekToPosition)
|
|
100
95
|
if isWaitingToStartPlayback {
|
|
101
96
|
playCommand(false) // but we will try to preempt it to avoid the button blinking paused.
|
|
102
97
|
}
|
|
@@ -230,6 +225,7 @@ final class RmxAudioPlayer: NSObject {
|
|
|
230
225
|
let item = avQueuePlayer.queuedAudioTracks[index]
|
|
231
226
|
removeTrackObservers(item)
|
|
232
227
|
avQueuePlayer.remove(item)
|
|
228
|
+
onStatus(.rmxstatus_ITEM_REMOVED, trackId: item.trackId, param: item.toDict())
|
|
233
229
|
}
|
|
234
230
|
|
|
235
231
|
func removeItem(_ id: String) throws {
|
|
@@ -246,6 +242,7 @@ final class RmxAudioPlayer: NSObject {
|
|
|
246
242
|
if let track = track {
|
|
247
243
|
avQueuePlayer.remove(track)
|
|
248
244
|
}
|
|
245
|
+
onStatus(.rmxstatus_ITEM_REMOVED, trackId: track?.trackId, param: track?.toDict())
|
|
249
246
|
}
|
|
250
247
|
|
|
251
248
|
// MARK: - player actions
|
|
@@ -373,18 +370,26 @@ final class RmxAudioPlayer: NSObject {
|
|
|
373
370
|
}
|
|
374
371
|
}
|
|
375
372
|
|
|
376
|
-
func setTracks(_ tracks: [AudioTrack], startPosition: Float) {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
373
|
+
func setTracks(_ tracks: [AudioTrack], startIndex: Int, startPosition: Float) {
|
|
374
|
+
avQueuePlayer.removeAllTrackObservers()
|
|
375
|
+
|
|
376
|
+
isReplacingItems = true
|
|
377
|
+
print("RmxAudioPlayer[setTracks] replacing tracks ")
|
|
378
|
+
avQueuePlayer.replaceAllItems(with: tracks)
|
|
379
|
+
|
|
380
|
+
print("RmxAudioPlayer[setTracks] replacing finished ")
|
|
381
381
|
for playerItem in tracks {
|
|
382
382
|
addTrackObservers(playerItem)
|
|
383
383
|
}
|
|
384
|
-
|
|
385
|
-
isReplacingItems =
|
|
386
|
-
|
|
387
|
-
|
|
384
|
+
|
|
385
|
+
isReplacingItems = false
|
|
386
|
+
print("RmxAudioPlayer[setTracks] added track observers ")
|
|
387
|
+
if !avQueuePlayer.queuedAudioTracks.isEmpty {
|
|
388
|
+
if startIndex >= 0 {
|
|
389
|
+
avQueuePlayer.setCurrentIndex(startIndex)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
388
393
|
if startPosition > 0 {
|
|
389
394
|
seek(to: startPosition, isCommand: false)
|
|
390
395
|
}
|
|
@@ -393,6 +398,7 @@ final class RmxAudioPlayer: NSObject {
|
|
|
393
398
|
func removeAllTracks() {
|
|
394
399
|
for item in avQueuePlayer.queuedAudioTracks {
|
|
395
400
|
removeTrackObservers(item)
|
|
401
|
+
onStatus(.rmxstatus_ITEM_REMOVED, trackId: item.trackId, param: item.toDict())
|
|
396
402
|
}
|
|
397
403
|
|
|
398
404
|
avQueuePlayer.removeAllItems()
|
|
@@ -536,8 +542,8 @@ final class RmxAudioPlayer: NSObject {
|
|
|
536
542
|
let player = object as? AVBidirectionalQueuePlayer
|
|
537
543
|
let playerItem = player?.currentAudioTrack
|
|
538
544
|
if playerItem != nil {
|
|
539
|
-
guard self.lastTrackId != playerItem?.trackId else {
|
|
540
|
-
return
|
|
545
|
+
guard !isReplacingItems && self.lastTrackId != playerItem?.trackId else {
|
|
546
|
+
return
|
|
541
547
|
}
|
|
542
548
|
print("observe change currentItem: lastTrackId \(self.lastTrackId) playerItem: \(playerItem?.trackId)")
|
|
543
549
|
self.lastTrackId = playerItem?.trackId
|
|
@@ -689,7 +695,7 @@ final class RmxAudioPlayer: NSObject {
|
|
|
689
695
|
|
|
690
696
|
func handleCurrentItemChanged(_ playerItem: AudioTrack?) {
|
|
691
697
|
if let playerItem = playerItem {
|
|
692
|
-
print("Queue changed current item to: \(playerItem.
|
|
698
|
+
print("Queue changed current item to: \(playerItem.trackId)")
|
|
693
699
|
// NSLog(@"New music name: %@", ((AVURLAsset*)playerItem.asset).URL.pathComponents.lastObject);
|
|
694
700
|
print("New item ID: \(playerItem.trackId ?? "")")
|
|
695
701
|
print("Queue is at end: \(avQueuePlayer.isAtEnd ? "YES" : "NO")")
|
|
@@ -713,6 +719,8 @@ final class RmxAudioPlayer: NSObject {
|
|
|
713
719
|
]
|
|
714
720
|
}
|
|
715
721
|
let trackId = playerItem != nil ? playerItem?.trackId : "NONE"
|
|
722
|
+
|
|
723
|
+
print("Update Track changed: \(info)")
|
|
716
724
|
onStatus(.rmxstatus_TRACK_CHANGED, trackId: trackId, param: info)
|
|
717
725
|
|
|
718
726
|
if avQueuePlayer.isAtEnd && avQueuePlayer.currentItem == nil {
|
|
@@ -988,16 +996,13 @@ final class RmxAudioPlayer: NSObject {
|
|
|
988
996
|
}
|
|
989
997
|
|
|
990
998
|
@objc func queueCleared(_ notification: Notification?) {
|
|
991
|
-
isReplacingItems = false
|
|
999
|
+
isReplacingItems = false // is this necessary ?
|
|
992
1000
|
print("RmxAudioPlayer, queuePlayerCleared")
|
|
993
1001
|
onStatus(.rmxstatus_PLAYLIST_CLEARED, trackId: "INVALID", param: nil)
|
|
994
1002
|
}
|
|
995
1003
|
|
|
996
1004
|
func removeTrackObservers(_ playerItem: AudioTrack?) {
|
|
997
|
-
|
|
998
|
-
NotificationCenter.default.removeObserver(self, name: .AVPlayerItemPlaybackStalled, object: playerItem)
|
|
999
|
-
|
|
1000
|
-
onStatus(.rmxstatus_ITEM_REMOVED, trackId: playerItem?.trackId, param: playerItem?.toDict())
|
|
1005
|
+
avQueuePlayer.removeTrackObservers(playerItem)
|
|
1001
1006
|
}
|
|
1002
1007
|
|
|
1003
1008
|
func activateAudioSession() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capacitor-plugin-playlist",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Playlist ",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -74,5 +74,8 @@
|
|
|
74
74
|
},
|
|
75
75
|
"bugs": {
|
|
76
76
|
"url": "https://github.com/phiamo/capacitor-plugin-playlist/issues"
|
|
77
|
+
},
|
|
78
|
+
"publishConfig": {
|
|
79
|
+
"@phiamo:registry": "https://npm.pkg.github.com"
|
|
77
80
|
}
|
|
78
81
|
}
|
package/android/local.properties
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
-
# as it contains information specific to your local configuration.
|
|
3
|
-
#
|
|
4
|
-
# Location of the SDK. This is only used by Gradle.
|
|
5
|
-
# For customization when using a Version Control System, please read the
|
|
6
|
-
# header note.
|
|
7
|
-
#Sat Jan 15 16:11:50 CET 2022
|
|
8
|
-
sdk.dir=/home/phiamo/Android/Sdk
|