tunzo-player 1.0.44 → 1.0.45
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/dist/core/player.d.ts +3 -5
- package/dist/core/player.js +49 -44
- package/package.json +1 -1
- package/src/core/player.ts +31 -36
package/dist/core/player.d.ts
CHANGED
|
@@ -12,19 +12,17 @@ export declare class Player {
|
|
|
12
12
|
static queue$: BehaviorSubject<any[]>;
|
|
13
13
|
private static playlist;
|
|
14
14
|
private static selectedQuality;
|
|
15
|
-
private static intendedPlaying;
|
|
16
15
|
private static toastCtrl;
|
|
17
16
|
/** Initialize with playlist and quality */
|
|
18
17
|
static initialize(playlist: any[], quality?: number): void;
|
|
19
18
|
static setToastController(controller: ToastController): void;
|
|
20
19
|
/** Setup audio element for better compatibility */
|
|
21
20
|
private static setupAudioElement;
|
|
22
|
-
private static startWatchdog;
|
|
23
21
|
/** Call this once on user gesture to unlock audio in WebView */
|
|
24
22
|
static unlockAudio(): void;
|
|
25
|
-
static play(song: any, index?: number): void
|
|
26
|
-
static pause(): void
|
|
27
|
-
static resume(): void
|
|
23
|
+
static play(song: any, index?: number): Promise<void>;
|
|
24
|
+
static pause(): Promise<void>;
|
|
25
|
+
static resume(): Promise<void>;
|
|
28
26
|
static togglePlayPause(): void;
|
|
29
27
|
static next(): void;
|
|
30
28
|
static prev(): void;
|
package/dist/core/player.js
CHANGED
|
@@ -11,7 +11,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Player = void 0;
|
|
13
13
|
const rxjs_1 = require("rxjs");
|
|
14
|
-
const keep_awake_1 = require("@capacitor-community/keep-awake");
|
|
15
14
|
const capacitor_media_session_1 = require("@capgo/capacitor-media-session");
|
|
16
15
|
class Player {
|
|
17
16
|
/** Initialize with playlist and quality */
|
|
@@ -20,7 +19,6 @@ class Player {
|
|
|
20
19
|
this.selectedQuality = quality;
|
|
21
20
|
this.setupMediaSession();
|
|
22
21
|
this.setupAudioElement();
|
|
23
|
-
this.startWatchdog();
|
|
24
22
|
}
|
|
25
23
|
static setToastController(controller) {
|
|
26
24
|
this.toastCtrl = controller;
|
|
@@ -58,59 +56,65 @@ class Player {
|
|
|
58
56
|
};
|
|
59
57
|
this.audio.onerror = (e) => {
|
|
60
58
|
console.error('Audio error:', this.audio.error, e);
|
|
59
|
+
this.isPlaying = false;
|
|
60
|
+
capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'none' });
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
static startWatchdog() {
|
|
64
|
-
setInterval(() => {
|
|
65
|
-
if (this.intendedPlaying && this.audio.paused && this.currentSong) {
|
|
66
|
-
console.log('Watchdog: Audio paused unexpectedly. Attempting to resume...');
|
|
67
|
-
this.audio.play().catch(e => console.warn('Watchdog resume failed:', e));
|
|
68
|
-
}
|
|
69
|
-
}, 10000);
|
|
70
|
-
}
|
|
71
63
|
/** Call this once on user gesture to unlock audio in WebView */
|
|
72
64
|
static unlockAudio() {
|
|
73
65
|
this.audio.src = '';
|
|
74
66
|
this.audio.load();
|
|
75
67
|
this.audio.play().catch(() => { });
|
|
76
68
|
}
|
|
77
|
-
static play(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
static play(song_1) {
|
|
70
|
+
return __awaiter(this, arguments, void 0, function* (song, index = 0) {
|
|
71
|
+
var _a;
|
|
72
|
+
if (!song || !song.downloadUrl)
|
|
73
|
+
return;
|
|
74
|
+
this.currentSong = song;
|
|
75
|
+
this.currentIndex = index;
|
|
76
|
+
let url = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || '';
|
|
77
|
+
// 🚀 Auto-convert http → https
|
|
78
|
+
if (url.startsWith('http://')) {
|
|
79
|
+
url = url.replace('http://', 'https://');
|
|
80
|
+
}
|
|
81
|
+
// Update metadata before playing to ensure UI is ready
|
|
82
|
+
yield this.updateMediaSessionMetadata(song);
|
|
83
|
+
try {
|
|
84
|
+
this.audio.src = url;
|
|
85
|
+
this.audio.load();
|
|
86
|
+
yield this.audio.play();
|
|
87
|
+
this.isPlaying = true;
|
|
88
|
+
yield capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'playing' });
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
// Ignore AbortError (happens when play is interrupted by another play call)
|
|
92
|
+
if (err.name !== 'AbortError') {
|
|
93
|
+
console.warn('Audio play failed:', err);
|
|
94
|
+
this.isPlaying = false;
|
|
95
|
+
yield capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
99
98
|
});
|
|
100
99
|
}
|
|
101
100
|
static pause() {
|
|
102
|
-
this
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
this.audio.pause();
|
|
103
|
+
this.isPlaying = false;
|
|
104
|
+
yield capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
105
|
+
});
|
|
107
106
|
}
|
|
108
107
|
static resume() {
|
|
109
|
-
this
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
109
|
+
try {
|
|
110
|
+
yield this.audio.play();
|
|
111
|
+
this.isPlaying = true;
|
|
112
|
+
yield capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'playing' });
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
console.warn('Resume failed:', err);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
114
118
|
}
|
|
115
119
|
static togglePlayPause() {
|
|
116
120
|
if (this.isPlaying) {
|
|
@@ -134,7 +138,9 @@ class Player {
|
|
|
134
138
|
this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
|
|
135
139
|
}
|
|
136
140
|
else {
|
|
137
|
-
|
|
141
|
+
// End of playlist
|
|
142
|
+
this.isPlaying = false;
|
|
143
|
+
capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
138
144
|
}
|
|
139
145
|
}
|
|
140
146
|
static prev() {
|
|
@@ -301,4 +307,3 @@ Player.queue = [];
|
|
|
301
307
|
Player.queue$ = new rxjs_1.BehaviorSubject([]);
|
|
302
308
|
Player.playlist = [];
|
|
303
309
|
Player.selectedQuality = 3;
|
|
304
|
-
Player.intendedPlaying = false;
|
package/package.json
CHANGED
package/src/core/player.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { BehaviorSubject } from 'rxjs';
|
|
2
|
-
import { KeepAwake } from '@capacitor-community/keep-awake';
|
|
3
2
|
import { ToastController } from '@ionic/angular/standalone';
|
|
4
3
|
import { MediaSession } from '@capgo/capacitor-media-session';
|
|
5
4
|
|
|
@@ -15,7 +14,6 @@ export class Player {
|
|
|
15
14
|
static queue$ = new BehaviorSubject<any[]>([]);
|
|
16
15
|
private static playlist: any[] = [];
|
|
17
16
|
private static selectedQuality = 3;
|
|
18
|
-
private static intendedPlaying = false;
|
|
19
17
|
private static toastCtrl: ToastController;
|
|
20
18
|
|
|
21
19
|
/** Initialize with playlist and quality */
|
|
@@ -24,7 +22,6 @@ export class Player {
|
|
|
24
22
|
this.selectedQuality = quality;
|
|
25
23
|
this.setupMediaSession();
|
|
26
24
|
this.setupAudioElement();
|
|
27
|
-
this.startWatchdog();
|
|
28
25
|
}
|
|
29
26
|
|
|
30
27
|
static setToastController(controller: ToastController) {
|
|
@@ -71,18 +68,11 @@ export class Player {
|
|
|
71
68
|
|
|
72
69
|
this.audio.onerror = (e) => {
|
|
73
70
|
console.error('Audio error:', this.audio.error, e);
|
|
71
|
+
this.isPlaying = false;
|
|
72
|
+
MediaSession.setPlaybackState({ playbackState: 'none' });
|
|
74
73
|
};
|
|
75
74
|
}
|
|
76
75
|
|
|
77
|
-
private static startWatchdog() {
|
|
78
|
-
setInterval(() => {
|
|
79
|
-
if (this.intendedPlaying && this.audio.paused && this.currentSong) {
|
|
80
|
-
console.log('Watchdog: Audio paused unexpectedly. Attempting to resume...');
|
|
81
|
-
this.audio.play().catch(e => console.warn('Watchdog resume failed:', e));
|
|
82
|
-
}
|
|
83
|
-
}, 10000);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
76
|
/** Call this once on user gesture to unlock audio in WebView */
|
|
87
77
|
static unlockAudio() {
|
|
88
78
|
this.audio.src = '';
|
|
@@ -90,11 +80,9 @@ export class Player {
|
|
|
90
80
|
this.audio.play().catch(() => { });
|
|
91
81
|
}
|
|
92
82
|
|
|
93
|
-
static play(song: any, index: number = 0) {
|
|
83
|
+
static async play(song: any, index: number = 0) {
|
|
94
84
|
if (!song || !song.downloadUrl) return;
|
|
95
85
|
|
|
96
|
-
this.intendedPlaying = true;
|
|
97
|
-
|
|
98
86
|
this.currentSong = song;
|
|
99
87
|
this.currentIndex = index;
|
|
100
88
|
|
|
@@ -105,34 +93,39 @@ export class Player {
|
|
|
105
93
|
url = url.replace('http://', 'https://');
|
|
106
94
|
}
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
this.
|
|
96
|
+
// Update metadata before playing to ensure UI is ready
|
|
97
|
+
await this.updateMediaSessionMetadata(song);
|
|
110
98
|
|
|
111
|
-
|
|
99
|
+
try {
|
|
100
|
+
this.audio.src = url;
|
|
101
|
+
this.audio.load();
|
|
102
|
+
await this.audio.play();
|
|
112
103
|
this.isPlaying = true;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
104
|
+
await MediaSession.setPlaybackState({ playbackState: 'playing' });
|
|
105
|
+
} catch (err: any) {
|
|
106
|
+
// Ignore AbortError (happens when play is interrupted by another play call)
|
|
107
|
+
if (err.name !== 'AbortError') {
|
|
108
|
+
console.warn('Audio play failed:', err);
|
|
109
|
+
this.isPlaying = false;
|
|
110
|
+
await MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
120
113
|
}
|
|
121
114
|
|
|
122
|
-
static pause() {
|
|
123
|
-
this.intendedPlaying = false;
|
|
115
|
+
static async pause() {
|
|
124
116
|
this.audio.pause();
|
|
125
117
|
this.isPlaying = false;
|
|
126
|
-
|
|
127
|
-
MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
118
|
+
await MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
128
119
|
}
|
|
129
120
|
|
|
130
|
-
static resume() {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
121
|
+
static async resume() {
|
|
122
|
+
try {
|
|
123
|
+
await this.audio.play();
|
|
124
|
+
this.isPlaying = true;
|
|
125
|
+
await MediaSession.setPlaybackState({ playbackState: 'playing' });
|
|
126
|
+
} catch (err) {
|
|
127
|
+
console.warn('Resume failed:', err);
|
|
128
|
+
}
|
|
136
129
|
}
|
|
137
130
|
|
|
138
131
|
static togglePlayPause() {
|
|
@@ -154,7 +147,9 @@ export class Player {
|
|
|
154
147
|
} else if (this.currentIndex < this.playlist.length - 1) {
|
|
155
148
|
this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
|
|
156
149
|
} else {
|
|
157
|
-
|
|
150
|
+
// End of playlist
|
|
151
|
+
this.isPlaying = false;
|
|
152
|
+
MediaSession.setPlaybackState({ playbackState: 'paused' });
|
|
158
153
|
}
|
|
159
154
|
}
|
|
160
155
|
|