tunzo-player 1.0.11 → 1.0.13

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.
@@ -20,12 +20,16 @@ class Player {
20
20
  return;
21
21
  this.currentSong = song;
22
22
  this.currentIndex = index;
23
- this.audio.src = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || '';
23
+ let url = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || '';
24
+ // 🚀 Auto-convert http → https
25
+ if (url.startsWith('http://')) {
26
+ url = url.replace('http://', 'https://');
27
+ }
28
+ this.audio.src = url;
24
29
  this.audio.load(); // Ensure audio is loaded before play
25
30
  this.audio.play().then(() => {
26
31
  this.isPlaying = true;
27
32
  }).catch((err) => {
28
- // Handle play errors (autoplay, WebView restrictions)
29
33
  this.isPlaying = false;
30
34
  console.warn('Audio play failed:', err);
31
35
  });
@@ -41,6 +45,10 @@ class Player {
41
45
  this.audio.onended = () => {
42
46
  this.autoNext();
43
47
  };
48
+ // Catch errors
49
+ this.audio.onerror = (e) => {
50
+ console.error('Audio error:', this.audio.error, e);
51
+ };
44
52
  }
45
53
  static pause() {
46
54
  this.audio.pause();
@@ -61,6 +69,7 @@ class Player {
61
69
  static next() {
62
70
  if (this.queue.length > 0) {
63
71
  const nextQueued = this.queue.shift();
72
+ this.queue$.next([...this.queue]);
64
73
  const index = this.playlist.findIndex(s => s.id === nextQueued.id);
65
74
  this.play(nextQueued, index);
66
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tunzo-player",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "A music playback service for Angular and Ionic apps with native audio control support.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,174 +1,188 @@
1
1
  import { BehaviorSubject } from 'rxjs';
2
2
 
3
3
  export class Player {
4
- private static audio = new Audio();
5
- private static currentSong: any = null;
6
- private static currentIndex = 0;
7
- private static isPlaying = false;
8
- private static currentTime = 0;
9
- private static duration = 0;
10
- private static isShuffle = true;
11
- private static queue: any[] = [];
12
- static queue$ = new BehaviorSubject<any[]>([]);
13
- private static playlist: any[] = [];
14
- private static selectedQuality = 3;
15
-
16
- /** Initialize with playlist and quality */
17
- static initialize(playlist: any[], quality = 3) {
18
- this.playlist = playlist;
19
- this.selectedQuality = quality;
20
- }
21
-
22
- /** Call this once on user gesture to unlock audio in WebView */
23
- static unlockAudio() {
24
- this.audio.src = '';
25
- this.audio.load();
26
- this.audio.play().catch(() => {});
27
- }
28
-
29
- static play(song: any, index: number = 0) {
30
- if (!song || !song.downloadUrl) return;
31
-
32
- this.currentSong = song;
33
- this.currentIndex = index;
34
- this.audio.src = song.downloadUrl[this.selectedQuality]?.url || '';
35
- this.audio.load(); // Ensure audio is loaded before play
36
- this.audio.play().then(() => {
37
- this.isPlaying = true;
38
- }).catch((err) => {
39
- // Handle play errors (autoplay, WebView restrictions)
40
- this.isPlaying = false;
41
- console.warn('Audio play failed:', err);
42
- });
43
-
44
- // Set duration
45
- this.audio.onloadedmetadata = () => {
46
- this.duration = this.audio.duration;
47
- };
48
-
49
- // Set current time
50
- this.audio.ontimeupdate = () => {
51
- this.currentTime = this.audio.currentTime;
52
- };
53
-
54
- // Auto-play next song
55
- this.audio.onended = () => {
56
- this.autoNext();
57
- };
58
- }
59
-
60
- static pause() {
61
- this.audio.pause();
62
- this.isPlaying = false;
4
+ private static audio = new Audio();
5
+ private static currentSong: any = null;
6
+ private static currentIndex = 0;
7
+ private static isPlaying = false;
8
+ private static currentTime = 0;
9
+ private static duration = 0;
10
+ private static isShuffle = true;
11
+ private static queue: any[] = [];
12
+ static queue$ = new BehaviorSubject<any[]>([]);
13
+ private static playlist: any[] = [];
14
+ private static selectedQuality = 3;
15
+
16
+ /** Initialize with playlist and quality */
17
+ static initialize(playlist: any[], quality = 3) {
18
+ this.playlist = playlist;
19
+ this.selectedQuality = quality;
20
+ }
21
+
22
+ /** Call this once on user gesture to unlock audio in WebView */
23
+ static unlockAudio() {
24
+ this.audio.src = '';
25
+ this.audio.load();
26
+ this.audio.play().catch(() => { });
27
+ }
28
+
29
+ static play(song: any, index: number = 0) {
30
+ if (!song || !song.downloadUrl) return;
31
+
32
+ this.currentSong = song;
33
+ this.currentIndex = index;
34
+
35
+ let url = song.downloadUrl[this.selectedQuality]?.url || '';
36
+
37
+ // 🚀 Auto-convert http → https
38
+ if (url.startsWith('http://')) {
39
+ url = url.replace('http://', 'https://');
63
40
  }
64
-
65
- static resume() {
66
- this.audio.play();
41
+
42
+ this.audio.src = url;
43
+ this.audio.load(); // Ensure audio is loaded before play
44
+ this.audio.play().then(() => {
67
45
  this.isPlaying = true;
68
- }
69
-
70
- static togglePlayPause() {
71
- if (this.isPlaying) {
72
- this.pause();
73
- } else {
74
- this.resume();
75
- }
76
- }
77
-
78
- static next() {
79
- if (this.queue.length > 0) {
80
- const nextQueued = this.queue.shift();
81
- const index = this.playlist.findIndex(s => s.id === nextQueued.id);
82
- this.play(nextQueued, index);
83
- } else if (this.isShuffle) {
84
- this.playRandom();
85
- } else if (this.currentIndex < this.playlist.length - 1) {
86
- this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
87
- }
88
- }
89
-
90
- static prev() {
91
- if (this.currentIndex > 0) {
92
- this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
93
- }
94
- }
95
-
96
- static seek(seconds: number) {
97
- this.audio.currentTime = seconds;
98
- }
99
-
100
- static autoNext() {
101
- this.next();
102
- }
103
-
104
- static playRandom() {
105
- if (this.playlist.length <= 1) return;
106
-
107
- let randomIndex;
108
- do {
109
- randomIndex = Math.floor(Math.random() * this.playlist.length);
110
- } while (randomIndex === this.currentIndex);
111
-
112
- this.play(this.playlist[randomIndex], randomIndex);
113
- }
114
-
115
- static toggleShuffle() {
116
- this.isShuffle = !this.isShuffle;
117
- }
46
+ }).catch((err) => {
47
+ this.isPlaying = false;
48
+ console.warn('Audio play failed:', err);
49
+ });
118
50
 
119
- static getShuffleStatus(): boolean {
120
- return this.isShuffle;
121
- }
122
-
123
- static addToQueue(song: any) {
124
- if (!this.queue.some(q => q.id === song.id)) {
125
- this.queue.push(song);
126
- this.queue$.next([...this.queue]);
127
- }
128
- }
129
-
130
- static removeFromQueue(index: number) {
131
- this.queue.splice(index, 1);
132
- this.queue$.next([...this.queue]);
133
- }
134
-
135
- static reorderQueue(from: number, to: number) {
136
- const item = this.queue.splice(from, 1)[0];
137
- this.queue.splice(to, 0, item);
138
- this.queue$.next([...this.queue]);
139
- }
140
-
141
- static getCurrentTime(): number {
142
- return this.currentTime;
143
- }
144
-
145
- static getDuration(): number {
146
- return this.duration;
147
- }
148
-
149
- static formatTime(time: number): string {
150
- const minutes = Math.floor(time / 60);
151
- const seconds = Math.floor(time % 60);
152
- return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
153
- }
154
-
155
- static isPlayingSong(): boolean {
156
- return this.isPlaying;
157
- }
158
-
159
- static getCurrentSong(): any {
160
- return this.currentSong;
51
+ // Set duration
52
+ this.audio.onloadedmetadata = () => {
53
+ this.duration = this.audio.duration;
54
+ };
55
+
56
+ // Set current time
57
+ this.audio.ontimeupdate = () => {
58
+ this.currentTime = this.audio.currentTime;
59
+ };
60
+
61
+ // Auto-play next song
62
+ this.audio.onended = () => {
63
+ this.autoNext();
64
+ };
65
+
66
+ // Catch errors
67
+ this.audio.onerror = (e) => {
68
+ console.error('Audio error:', this.audio.error, e);
69
+ };
70
+ }
71
+
72
+
73
+ static pause() {
74
+ this.audio.pause();
75
+ this.isPlaying = false;
76
+ }
77
+
78
+ static resume() {
79
+ this.audio.play();
80
+ this.isPlaying = true;
81
+ }
82
+
83
+ static togglePlayPause() {
84
+ if (this.isPlaying) {
85
+ this.pause();
86
+ } else {
87
+ this.resume();
161
88
  }
162
-
163
- static setQuality(index: number) {
164
- this.selectedQuality = index;
89
+ }
90
+
91
+ static next() {
92
+ if (this.queue.length > 0) {
93
+ const nextQueued = this.queue.shift();
94
+ this.queue$.next([...this.queue]);
95
+ const index = this.playlist.findIndex(s => s.id === nextQueued.id);
96
+ this.play(nextQueued, index);
97
+ } else if (this.isShuffle) {
98
+ this.playRandom();
99
+ } else if (this.currentIndex < this.playlist.length - 1) {
100
+ this.play(this.playlist[this.currentIndex + 1], this.currentIndex + 1);
165
101
  }
166
-
167
- static getQueue(): any[] {
168
- return this.queue;
102
+ }
103
+
104
+ static prev() {
105
+ if (this.currentIndex > 0) {
106
+ this.play(this.playlist[this.currentIndex - 1], this.currentIndex - 1);
169
107
  }
170
-
171
- static getPlaylist(): any[] {
172
- return this.playlist;
108
+ }
109
+
110
+ static seek(seconds: number) {
111
+ this.audio.currentTime = seconds;
112
+ }
113
+
114
+ static autoNext() {
115
+ this.next();
116
+ }
117
+
118
+ static playRandom() {
119
+ if (this.playlist.length <= 1) return;
120
+
121
+ let randomIndex;
122
+ do {
123
+ randomIndex = Math.floor(Math.random() * this.playlist.length);
124
+ } while (randomIndex === this.currentIndex);
125
+
126
+ this.play(this.playlist[randomIndex], randomIndex);
127
+ }
128
+
129
+ static toggleShuffle() {
130
+ this.isShuffle = !this.isShuffle;
131
+ }
132
+
133
+ static getShuffleStatus(): boolean {
134
+ return this.isShuffle;
135
+ }
136
+
137
+ static addToQueue(song: any) {
138
+ if (!this.queue.some(q => q.id === song.id)) {
139
+ this.queue.push(song);
140
+ this.queue$.next([...this.queue]);
173
141
  }
174
142
  }
143
+
144
+ static removeFromQueue(index: number) {
145
+ this.queue.splice(index, 1);
146
+ this.queue$.next([...this.queue]);
147
+ }
148
+
149
+ static reorderQueue(from: number, to: number) {
150
+ const item = this.queue.splice(from, 1)[0];
151
+ this.queue.splice(to, 0, item);
152
+ this.queue$.next([...this.queue]);
153
+ }
154
+
155
+ static getCurrentTime(): number {
156
+ return this.currentTime;
157
+ }
158
+
159
+ static getDuration(): number {
160
+ return this.duration;
161
+ }
162
+
163
+ static formatTime(time: number): string {
164
+ const minutes = Math.floor(time / 60);
165
+ const seconds = Math.floor(time % 60);
166
+ return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
167
+ }
168
+
169
+ static isPlayingSong(): boolean {
170
+ return this.isPlaying;
171
+ }
172
+
173
+ static getCurrentSong(): any {
174
+ return this.currentSong;
175
+ }
176
+
177
+ static setQuality(index: number) {
178
+ this.selectedQuality = index;
179
+ }
180
+
181
+ static getQueue(): any[] {
182
+ return this.queue;
183
+ }
184
+
185
+ static getPlaylist(): any[] {
186
+ return this.playlist;
187
+ }
188
+ }