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.
@@ -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;
@@ -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(song, index = 0) {
78
- var _a;
79
- if (!song || !song.downloadUrl)
80
- return;
81
- this.intendedPlaying = true;
82
- this.currentSong = song;
83
- this.currentIndex = index;
84
- let url = ((_a = song.downloadUrl[this.selectedQuality]) === null || _a === void 0 ? void 0 : _a.url) || '';
85
- // 🚀 Auto-convert http → https
86
- if (url.startsWith('http://')) {
87
- url = url.replace('http://', 'https://');
88
- }
89
- this.audio.src = url;
90
- this.audio.load();
91
- this.audio.play().then(() => {
92
- this.isPlaying = true;
93
- this.updateMediaSessionMetadata(song);
94
- keep_awake_1.KeepAwake.keepAwake(); // Keep screen/CPU awake
95
- capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'playing' });
96
- }).catch((err) => {
97
- this.isPlaying = false;
98
- console.warn('Audio play failed:', err);
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.intendedPlaying = false;
103
- this.audio.pause();
104
- this.isPlaying = false;
105
- keep_awake_1.KeepAwake.allowSleep();
106
- capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'paused' });
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.intendedPlaying = true;
110
- this.audio.play();
111
- this.isPlaying = true;
112
- keep_awake_1.KeepAwake.keepAwake();
113
- capacitor_media_session_1.MediaSession.setPlaybackState({ playbackState: 'playing' });
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
- this.intendedPlaying = false;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tunzo-player",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
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,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
- this.audio.src = url;
109
- this.audio.load();
96
+ // Update metadata before playing to ensure UI is ready
97
+ await this.updateMediaSessionMetadata(song);
110
98
 
111
- this.audio.play().then(() => {
99
+ try {
100
+ this.audio.src = url;
101
+ this.audio.load();
102
+ await this.audio.play();
112
103
  this.isPlaying = true;
113
- this.updateMediaSessionMetadata(song);
114
- KeepAwake.keepAwake(); // Keep screen/CPU awake
115
- MediaSession.setPlaybackState({ playbackState: 'playing' });
116
- }).catch((err) => {
117
- this.isPlaying = false;
118
- console.warn('Audio play failed:', err);
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
- KeepAwake.allowSleep();
127
- MediaSession.setPlaybackState({ playbackState: 'paused' });
118
+ await MediaSession.setPlaybackState({ playbackState: 'paused' });
128
119
  }
129
120
 
130
- static resume() {
131
- this.intendedPlaying = true;
132
- this.audio.play();
133
- this.isPlaying = true;
134
- KeepAwake.keepAwake();
135
- MediaSession.setPlaybackState({ playbackState: 'playing' });
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
- this.intendedPlaying = false;
150
+ // End of playlist
151
+ this.isPlaying = false;
152
+ MediaSession.setPlaybackState({ playbackState: 'paused' });
158
153
  }
159
154
  }
160
155