gapless.js 4.0.1 → 4.0.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/package.json +1 -1
- package/src/Track.ts +4 -3
- package/src/machines/track.machine.ts +21 -1
package/package.json
CHANGED
package/src/Track.ts
CHANGED
|
@@ -227,9 +227,10 @@ export class Track {
|
|
|
227
227
|
|
|
228
228
|
activate(): void {
|
|
229
229
|
const state = this._actor.getSnapshot().value;
|
|
230
|
-
// If the track was in webaudio state (e.g. from gapless scheduling
|
|
231
|
-
// preload BUFFER_READY), reset it so play() can start
|
|
232
|
-
|
|
230
|
+
// If the track was in webaudio or loading state (e.g. from gapless scheduling,
|
|
231
|
+
// preload BUFFER_READY, or stuck in loading), reset it so play() can start
|
|
232
|
+
// from a clean state.
|
|
233
|
+
if (state === 'webaudio' || state === 'loading') {
|
|
233
234
|
this._stopSourceNode();
|
|
234
235
|
this._disconnectGain();
|
|
235
236
|
this.scheduledStartContextTime = null;
|
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
// loading Track is preloaded (not yet playing). Decode in progress.
|
|
8
8
|
// webaudio AudioBufferSourceNode is the active output.
|
|
9
9
|
//
|
|
10
|
+
// Design invariant — "Web Audio always wins eventually":
|
|
11
|
+
// When a track's buffer finishes decoding (BUFFER_READY), webAudioLoadingState
|
|
12
|
+
// is set to 'LOADED' regardless of what state the machine is in (html5, loading,
|
|
13
|
+
// or idle). We intentionally do NOT switch mid-stream — the track stays in html5
|
|
14
|
+
// until the next play(). But every state handles BUFFER_READY, so the flag is
|
|
15
|
+
// never lost, and the next play() will see the buffer and use Web Audio.
|
|
16
|
+
//
|
|
17
|
+
// All DEACTIVATE transitions land in idle (not loading), so a deactivated track
|
|
18
|
+
// with a loaded buffer is always in idle+LOADED — ready for Web Audio on re-play.
|
|
19
|
+
//
|
|
10
20
|
// Bug fixes in this rewrite:
|
|
11
21
|
// #2: BUFFER_READY in html5 stays in html5 (no longer auto-transitions to webaudio)
|
|
12
22
|
// #3: DEACTIVATE from webaudio → idle (was staying in webaudio)
|
|
@@ -83,6 +93,12 @@ export function createTrackMachine(initialContext: TrackContext) {
|
|
|
83
93
|
BUFFER_LOADING: {
|
|
84
94
|
actions: assign({ webAudioLoadingState: () => 'LOADING' as WebAudioLoadingState }),
|
|
85
95
|
},
|
|
96
|
+
BUFFER_READY: {
|
|
97
|
+
actions: assign({ webAudioLoadingState: () => 'LOADED' as WebAudioLoadingState }),
|
|
98
|
+
},
|
|
99
|
+
BUFFER_ERROR: {
|
|
100
|
+
actions: assign({ webAudioLoadingState: () => 'ERROR' as WebAudioLoadingState }),
|
|
101
|
+
},
|
|
86
102
|
URL_RESOLVED: {
|
|
87
103
|
actions: assign({
|
|
88
104
|
resolvedUrl: ({ event }) => (event as { type: 'URL_RESOLVED'; url: string }).url,
|
|
@@ -140,7 +156,7 @@ export function createTrackMachine(initialContext: TrackContext) {
|
|
|
140
156
|
}),
|
|
141
157
|
},
|
|
142
158
|
DEACTIVATE: {
|
|
143
|
-
target: '
|
|
159
|
+
target: 'idle',
|
|
144
160
|
actions: assign({ isPlaying: () => false }),
|
|
145
161
|
},
|
|
146
162
|
},
|
|
@@ -178,6 +194,10 @@ export function createTrackMachine(initialContext: TrackContext) {
|
|
|
178
194
|
playbackType: () => 'WEBAUDIO' as PlaybackType,
|
|
179
195
|
}),
|
|
180
196
|
},
|
|
197
|
+
DEACTIVATE: {
|
|
198
|
+
target: 'idle',
|
|
199
|
+
actions: assign({ isPlaying: () => false }),
|
|
200
|
+
},
|
|
181
201
|
URL_RESOLVED: {
|
|
182
202
|
actions: assign({
|
|
183
203
|
resolvedUrl: ({ event }) => (event as { type: 'URL_RESOLVED'; url: string }).url,
|