gapless.js 3.0.1 → 4.0.1

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/README.md CHANGED
@@ -1,60 +1,159 @@
1
1
  # gapless.js
2
2
 
3
- gapless.js is a library for gapless audio playback. It is not intended to be a flawless solution for every use-case, but rather a balance between the needs of my use-case over at <Relisten.net>.
3
+ Gapless audio playback for the web. Takes an array of audio tracks and uses HTML5 audio with the Web Audio API to enable seamless, gapless transitions between tracks.
4
4
 
5
- In short, it takes an array of audio tracks and utilizes HTML5 audio and the web audio API to enable gapless playback of individual tracks.
5
+ Built for [Relisten.net](https://relisten.net).
6
6
 
7
- I will expand this README with more details in time. If you're interested in this library, don't hesitate to leave me a note with any questions.
7
+ **[Live Demo](https://gapless.saewitz.com)**
8
8
 
9
- You can see a sample of the library in use currently at <Relisten.live> which is the not-yet-released beta of the next version of <Relisten.net>
9
+ ## Install
10
10
 
11
- ## Sample usage
11
+ ```bash
12
+ pnpm install gapless.js
13
+ ```
14
+
15
+ ## Quick Start
12
16
 
13
17
  ```javascript
14
- import GaplessQueue from 'gapless.js';
15
-
16
- const player = new GaplessQueue({
17
- tracks: [
18
- "http://phish.in/audio/000/012/321/12321.mp3",
19
- "http://phish.in/audio/000/012/322/12322.mp3",
20
- "http://phish.in/audio/000/012/323/12323.mp3",
21
- "http://phish.in/audio/000/012/324/12324.mp3"
22
- ],
23
- onProgress: function(track) {
24
- track && console.log(track.completeState);
25
- }
26
- });
27
-
28
- player.play();
18
+ import Queue from 'gapless.js';
19
+
20
+ const player = new Queue({
21
+ tracks: [
22
+ 'https://example.com/track1.mp3',
23
+ 'https://example.com/track2.mp3',
24
+ 'https://example.com/track3.mp3',
25
+ ],
26
+ onProgress: (track) => {
27
+ console.log(`${track.currentTime} / ${track.duration}`);
28
+ },
29
+ onEnded: () => {
30
+ console.log('Queue finished');
31
+ },
32
+ });
33
+
34
+ player.play();
29
35
  ```
30
36
 
31
- ## Gapless.Queue Options
32
- ```javascript
33
- tracks = [],
34
- onProgress,
35
- onEnded,
36
- onPlayNextTrack,
37
- onPlayPreviousTrack,
38
- onStartNewTrack,
39
- webAudioIsDisabled = false
37
+ ## API
38
+
39
+ ### Constructor Options (`GaplessOptions`)
40
+
41
+ ```typescript
42
+ const player = new Queue({
43
+ tracks: [], // Initial list of track URLs
44
+ onProgress: (info) => {}, // Called at ~60fps while playing
45
+ onEnded: () => {}, // Called when the last track ends
46
+ onPlayNextTrack: (info) => {}, // Called when advancing to next track
47
+ onPlayPreviousTrack: (info) => {},// Called when going to previous track
48
+ onStartNewTrack: (info) => {}, // Called whenever a new track becomes current
49
+ onError: (error) => {}, // Called on audio errors
50
+ onPlayBlocked: () => {}, // Called when autoplay is blocked by the browser
51
+ onDebug: (msg) => {}, // Internal debug messages (development only)
52
+ webAudioIsDisabled: false, // Disable Web Audio API (disables gapless playback)
53
+ trackMetadata: [], // Per-track metadata (aligned by index)
54
+ volume: 1, // Initial volume, 0.0–1.0
55
+ });
40
56
  ```
41
57
 
42
- ## API (subject to change)
58
+ ### Methods
43
59
 
44
- ```javascript
45
- // functions
46
- player.togglePlayPause(); // toggle play/pause
47
- player.playNext(); // play next track
48
- player.playPrevious(); // play previous track
49
- player.resetCurrentTrack(); // reset current track to 0
50
- player.gotoTrack(idx, playImmediately); // jump to track by index and pass true to play immediately
51
- player.disableWebAudio(); // disable gapless playback/web audio
52
-
53
- // getters
54
- player.currentTrack; // returns current active track
55
- player.nextTrack; // returns next track
60
+ | Method | Description |
61
+ |--------|-------------|
62
+ | `play()` | Start or resume playback |
63
+ | `pause()` | Pause playback |
64
+ | `togglePlayPause()` | Toggle between play and pause |
65
+ | `next()` | Advance to the next track |
66
+ | `previous()` | Go to previous track (restarts current track if > 8s in) |
67
+ | `gotoTrack(index, playImmediately?)` | Jump to a track by index |
68
+ | `seek(time)` | Seek to a position in seconds |
69
+ | `setVolume(volume)` | Set volume (0.0–1.0) |
70
+ | `addTrack(url, options?)` | Add a track to the end of the queue |
71
+ | `removeTrack(index)` | Remove a track by index |
72
+ | `resumeAudioContext()` | Resume the AudioContext (for browsers that require user gesture) |
73
+ | `destroy()` | Clean up all resources |
74
+
75
+ ### Getters
76
+
77
+ | Getter | Type | Description |
78
+ |--------|------|-------------|
79
+ | `currentTrack` | `TrackInfo \| undefined` | Snapshot of the current track |
80
+ | `currentTrackIndex` | `number` | Index of the current track |
81
+ | `tracks` | `readonly TrackInfo[]` | Snapshot of all tracks |
82
+ | `isPlaying` | `boolean` | Whether the queue is playing |
83
+ | `isPaused` | `boolean` | Whether the queue is paused |
84
+ | `volume` | `number` | Current volume |
85
+
86
+ ### `TrackInfo`
87
+
88
+ All callbacks and getters return `TrackInfo` objects — plain data snapshots with no methods:
89
+
90
+ ```typescript
91
+ interface TrackInfo {
92
+ index: number; // Position in the queue
93
+ currentTime: number; // Playback position in seconds
94
+ duration: number; // Total duration (NaN until loaded)
95
+ isPlaying: boolean;
96
+ isPaused: boolean;
97
+ volume: number;
98
+ trackUrl: string; // Resolved audio URL
99
+ playbackType: 'HTML5' | 'WEBAUDIO';
100
+ webAudioLoadingState: 'NONE' | 'LOADING' | 'LOADED' | 'ERROR';
101
+ metadata?: TrackMetadata;
102
+ machineState: string; // Internal state machine state
103
+ }
56
104
  ```
57
105
 
106
+ ### `AddTrackOptions`
107
+
108
+ ```typescript
109
+ player.addTrack('https://example.com/track.mp3', {
110
+ skipHEAD: true, // Skip HEAD request for URL resolution
111
+ metadata: {
112
+ title: 'Track Title',
113
+ artist: 'Artist',
114
+ album: 'Album',
115
+ artwork: [{ src: 'https://example.com/art.jpg', sizes: '512x512', type: 'image/jpeg' }],
116
+ },
117
+ });
118
+ ```
119
+
120
+ ### `TrackMetadata`
121
+
122
+ Metadata is used for the [Media Session API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API) (lock screen controls, browser media UI) and can contain arbitrary additional fields:
123
+
124
+ ```typescript
125
+ interface TrackMetadata {
126
+ title?: string;
127
+ artist?: string;
128
+ album?: string;
129
+ artwork?: MediaImage[];
130
+ [key: string]: unknown;
131
+ }
132
+ ```
133
+
134
+ ## Migration from v3
135
+
136
+ v4 is a complete rewrite. The public API has changed:
137
+
138
+ | v3 | v4 |
139
+ |----|-----|
140
+ | `import GaplessQueue from 'gapless.js'` | `import Queue from 'gapless.js'` (or `import { Queue }`) |
141
+ | `player.playNext()` | `player.next()` |
142
+ | `player.playPrevious()` | `player.previous()` |
143
+ | `player.resetCurrentTrack()` | `player.seek(0)` |
144
+ | `player.disableWebAudio()` | Pass `webAudioIsDisabled: true` in constructor |
145
+ | `player.nextTrack` | `player.tracks[player.currentTrackIndex + 1]` |
146
+ | `track.completeState` | Callbacks now receive `TrackInfo` objects |
147
+ | Callbacks receive Track instances | Callbacks receive plain `TrackInfo` data snapshots |
148
+
149
+ ### Key differences
150
+
151
+ - **State machines**: Internally uses [XState](https://xstate.js.org/) for queue and track state management. XState is bundled — no extra dependency needed.
152
+ - **ESM only**: Published as ES module only. No CommonJS build.
153
+ - **TrackInfo**: All callbacks and getters return plain data objects (`TrackInfo`) instead of Track class instances.
154
+ - **Media Session**: Built-in support for the Media Session API via `trackMetadata`.
155
+ - **Volume**: Volume is now set via `setVolume(n)` and readable via the `volume` getter.
156
+
58
157
  ## License
59
158
 
60
- MIT - do as you please
159
+ MIT
@@ -0,0 +1,215 @@
1
+ type PlaybackType = 'HTML5' | 'WEBAUDIO';
2
+ type WebAudioLoadingState = 'NONE' | 'LOADING' | 'LOADED' | 'ERROR';
3
+ /** Metadata attached to a track (arbitrary user data). */
4
+ interface TrackMetadata {
5
+ title?: string;
6
+ artist?: string;
7
+ album?: string;
8
+ artwork?: MediaImage[];
9
+ [key: string]: unknown;
10
+ }
11
+ /** Options accepted by the Queue constructor. */
12
+ interface GaplessOptions {
13
+ /** Initial list of track URLs. */
14
+ tracks?: string[];
15
+ /** Called at ~60fps while playing. */
16
+ onProgress?: (info: TrackInfo) => void;
17
+ /** Called when the last track in the queue ends. */
18
+ onEnded?: () => void;
19
+ /** Called when the queue advances to the next track. */
20
+ onPlayNextTrack?: (info: TrackInfo) => void;
21
+ /** Called when the queue goes back to the previous track. */
22
+ onPlayPreviousTrack?: (info: TrackInfo) => void;
23
+ /** Called whenever a new track becomes the current track. */
24
+ onStartNewTrack?: (info: TrackInfo) => void;
25
+ /** Called on HTML5 audio errors. */
26
+ onError?: (error: Error) => void;
27
+ /** Called with internal debug messages. Only use for development. */
28
+ onDebug?: (msg: string) => void;
29
+ /** Called when autoplay is blocked by the browser. */
30
+ onPlayBlocked?: () => void;
31
+ /**
32
+ * Set true to disable Web Audio API entirely and use HTML5 audio only.
33
+ * Gapless playback will not be available in this mode.
34
+ */
35
+ webAudioIsDisabled?: boolean;
36
+ /** Per-track metadata (aligned to the tracks array by index). */
37
+ trackMetadata?: TrackMetadata[];
38
+ /** Initial volume, 0.0–1.0. Defaults to 1. */
39
+ volume?: number;
40
+ }
41
+ /** Options for dynamically adding a track. */
42
+ interface AddTrackOptions {
43
+ /**
44
+ * Skip the HEAD request used to resolve redirects.
45
+ * Set true when the URL is already a direct, final URL.
46
+ */
47
+ skipHEAD?: boolean;
48
+ metadata?: TrackMetadata;
49
+ }
50
+ /**
51
+ * A plain-data snapshot of a track's current state.
52
+ * Returned by Queue getters and passed to callbacks.
53
+ * No methods — pure data.
54
+ */
55
+ interface TrackInfo {
56
+ /** Zero-based position of this track in the queue. */
57
+ index: number;
58
+ /** Current playback position in seconds. */
59
+ currentTime: number;
60
+ /** Total duration in seconds (NaN until loaded). */
61
+ duration: number;
62
+ /** True if currently playing. */
63
+ isPlaying: boolean;
64
+ /** True if explicitly paused. */
65
+ isPaused: boolean;
66
+ /** Current volume, 0.0–1.0. */
67
+ volume: number;
68
+ /** The resolved URL of the audio file. */
69
+ trackUrl: string;
70
+ /** Which backend is currently producing sound. */
71
+ playbackType: PlaybackType;
72
+ /** Whether the Web Audio buffer has been decoded. */
73
+ webAudioLoadingState: WebAudioLoadingState;
74
+ /** Arbitrary metadata supplied when the track was added. */
75
+ metadata?: TrackMetadata;
76
+ /** Current xstate machine state for this track (e.g. 'idle', 'html5', 'webaudio'). */
77
+ machineState: string;
78
+ }
79
+
80
+ interface TrackQueueRef {
81
+ onTrackEnded(track: Track): void;
82
+ onTrackBufferReady(track: Track): void;
83
+ onProgress(info: TrackInfo): void;
84
+ onError(error: Error): void;
85
+ onPlayBlocked(): void;
86
+ onDebug(msg: string): void;
87
+ readonly volume: number;
88
+ readonly webAudioIsDisabled: boolean;
89
+ readonly currentTrackIndex: number;
90
+ }
91
+ declare class Track {
92
+ readonly index: number;
93
+ readonly metadata: TrackMetadata;
94
+ private _trackUrl;
95
+ private _resolvedUrl;
96
+ private readonly skipHEAD;
97
+ private loadedHEAD;
98
+ private abortController;
99
+ readonly audio: HTMLAudioElement;
100
+ private readonly _webAudioDisabled;
101
+ private get ctx();
102
+ private gainNode;
103
+ private sourceNode;
104
+ audioBuffer: AudioBuffer | null;
105
+ /** AudioContext.currentTime when the current source node was started. */
106
+ private webAudioStartedAt;
107
+ /** Track-time (seconds) frozen at the moment of the most recent pause. */
108
+ private pausedAtTrackTime;
109
+ scheduledStartContextTime: number | null;
110
+ private readonly _actor;
111
+ private readonly queueRef;
112
+ private rafId;
113
+ private _notifiedLookahead;
114
+ constructor(opts: {
115
+ trackUrl: string;
116
+ index: number;
117
+ queue: TrackQueueRef;
118
+ skipHEAD?: boolean;
119
+ metadata?: TrackMetadata;
120
+ });
121
+ play(): void;
122
+ pause(): void;
123
+ seek(time: number): void;
124
+ setVolume(v: number): void;
125
+ preload(): void;
126
+ seekToEnd(secondsFromEnd?: number): void;
127
+ activate(): void;
128
+ deactivate(): void;
129
+ destroy(): void;
130
+ cancelGaplessStart(): void;
131
+ scheduleGaplessStart(when: number): void;
132
+ get currentTime(): number;
133
+ get duration(): number;
134
+ get isPaused(): boolean;
135
+ get isPlaying(): boolean;
136
+ get trackUrl(): string;
137
+ get playbackType(): PlaybackType;
138
+ get webAudioLoadingState(): WebAudioLoadingState;
139
+ get hasSourceNode(): boolean;
140
+ get machineState(): string;
141
+ get isBufferLoaded(): boolean;
142
+ toInfo(): TrackInfo;
143
+ private _playHtml5;
144
+ private get _isUsingWebAudio();
145
+ private _playWebAudio;
146
+ private _startSourceNode;
147
+ private _stopSourceNode;
148
+ private _disconnectGain;
149
+ private _handleWebAudioEnded;
150
+ private _startLoad;
151
+ startProgressLoop(): void;
152
+ private _stopProgressLoop;
153
+ }
154
+
155
+ declare class Queue implements TrackQueueRef {
156
+ private _tracks;
157
+ private readonly _actor;
158
+ private readonly _onProgress?;
159
+ private readonly _onEnded?;
160
+ private readonly _onPlayNextTrack?;
161
+ private readonly _onPlayPreviousTrack?;
162
+ private readonly _onStartNewTrack?;
163
+ private readonly _onError?;
164
+ private readonly _onPlayBlocked?;
165
+ private readonly _onDebug?;
166
+ readonly webAudioIsDisabled: boolean;
167
+ private _volume;
168
+ /** Track indices for which a gapless start has been pre-scheduled. */
169
+ private _scheduledIndices;
170
+ private _throttledUpdatePositionState;
171
+ constructor(options?: GaplessOptions);
172
+ play(): void;
173
+ pause(): void;
174
+ togglePlayPause(): void;
175
+ next(): void;
176
+ previous(): void;
177
+ gotoTrack(index: number, playImmediately?: boolean): void;
178
+ seek(time: number): void;
179
+ setVolume(volume: number): void;
180
+ addTrack(url: string, options?: AddTrackOptions): void;
181
+ removeTrack(index: number): void;
182
+ resumeAudioContext(): Promise<void>;
183
+ destroy(): void;
184
+ get currentTrack(): TrackInfo | undefined;
185
+ get currentTrackIndex(): number;
186
+ get tracks(): readonly TrackInfo[];
187
+ get isPlaying(): boolean;
188
+ get isPaused(): boolean;
189
+ get volume(): number;
190
+ /** Snapshot of the queue state machine (state name + context). For debugging. */
191
+ get queueSnapshot(): {
192
+ state: string;
193
+ context: {
194
+ currentTrackIndex: number;
195
+ trackCount: number;
196
+ };
197
+ };
198
+ onTrackEnded(track: Track): void;
199
+ onTrackBufferReady(track: Track): void;
200
+ onProgress(info: TrackInfo): void;
201
+ onError(error: Error): void;
202
+ onPlayBlocked(): void;
203
+ onDebug(msg: string): void;
204
+ private get _currentTrack();
205
+ private _deactivateCurrent;
206
+ private _activateCurrent;
207
+ private _preloadAhead;
208
+ private _cancelScheduledGapless;
209
+ private _cancelAllScheduledGapless;
210
+ private _cancelAndRescheduleGapless;
211
+ private _tryScheduleGapless;
212
+ private _computeTrackEndTime;
213
+ }
214
+
215
+ export { type AddTrackOptions, type GaplessOptions, type PlaybackType, Queue, type TrackInfo, type TrackMetadata, type WebAudioLoadingState, Queue as default };
package/dist/index.mjs CHANGED
@@ -1,2 +1,4 @@
1
- var f=typeof window<"u",p=f&&(window.AudioContext||window.webkitAudioContext)?new(window.AudioContext||window.webkitAudioContext):null;var o=class{playbackType;webAudioLoadingState;loadedHEAD;idx;queue;trackUrl;skipHEAD;metadata;audio;audioContext;gainNode;bufferSourceNode;audioBuffer;webAudioStartedPlayingAt;webAudioPausedDuration;webAudioPausedAt;boundOnEnded;boundOnProgress;boundAudioOnError;progressFrameId=null;constructor({trackUrl:e,skipHEAD:t,queue:i,idx:s,metadata:d={}}){this.playbackType="HTML5",this.webAudioLoadingState="NONE",this.loadedHEAD=!1,this.idx=s,this.queue=i,this.trackUrl=e,this.skipHEAD=t,this.metadata=d,this.boundOnEnded=a=>this.onEnded(a),this.boundOnProgress=()=>this.onProgress(),this.boundAudioOnError=a=>this.audioOnError(a),this.audio=new Audio,this.audio.onerror=this.boundAudioOnError,this.audio.onended=()=>this.boundOnEnded("HTML5"),this.audio.controls=!1,this.audio.volume=i.state.volume,this.audio.preload="none",this.audio.src=e,this.audioContext=i.state.webAudioIsDisabled?null:p,this.gainNode=null,this.bufferSourceNode=null,this.audioBuffer=null,this.webAudioStartedPlayingAt=0,this.webAudioPausedDuration=0,this.webAudioPausedAt=0,this.audioContext&&(this.gainNode=this.audioContext.createGain(),this.gainNode.gain.value=i.state.volume)}loadHEAD(e){if(this.loadedHEAD||this.skipHEAD){e();return}let t={method:"HEAD"};fetch(this.trackUrl,t).then(i=>{i.redirected&&i.url&&(this.trackUrl=i.url,this.audio.src!==this.trackUrl&&this.audio.readyState===0&&(this.audio.src=this.trackUrl)),this.loadedHEAD=!0,e()}).catch(i=>{console.error(`HEAD request failed for track ${this.idx}:`,i),e()})}loadBuffer(e){!this.audioContext||this.webAudioLoadingState!=="NONE"||this.queue.state.webAudioIsDisabled||(this.webAudioLoadingState="LOADING",this.debug("starting download"),fetch(this.trackUrl).then(t=>{if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.arrayBuffer()}).then(t=>this.audioContext.decodeAudioData(t,i=>{this.debug("finished decoding track"),this.webAudioLoadingState="LOADED",this.audioBuffer=i,this.queue.loadTrack(this.idx+1),this.isActiveTrack&&this.playbackType==="HTML5"&&!this.isPaused?this.switchToWebAudio():this.isActiveTrack&&this.playbackType==="HTML5"&&this.isPaused?(this.playbackType="WEBAUDIO",this.debug("WebAudio ready for paused track")):this.isActiveTrack||(this.playbackType="WEBAUDIO",this.debug("WebAudio ready for inactive track")),e==null||e(i)},i=>{console.error(`Error decoding audio data for track ${this.idx}:`,i),this.webAudioLoadingState="NONE"})).catch(t=>{this.debug("caught fetch/decode error",t),this.webAudioLoadingState="NONE"}))}createBufferSourceNode(){if(!this.audioContext||!this.audioBuffer||!this.gainNode)return null;let e=this.audioContext.createBufferSource();return e.buffer=this.audioBuffer,e.connect(this.gainNode),e.onended=()=>this.boundOnEnded("webaudio_auto"),e}switchToWebAudio(e=!1){if(!this.audioContext||!this.audioBuffer||!this.gainNode||this.webAudioLoadingState!=="LOADED"){this.debug("Cannot switch to WebAudio: not ready.");return}if(!this.isActiveTrack&&!e){this.debug("Cannot switch to WebAudio: not active track.");return}let t=this.audio.paused,i=this.audio.currentTime;if(this.debug("Attempting switch to web audio",`currentTime: ${i}`,`wasPaused: ${t}`,`HTML5 duration: ${this.audio.duration}`,`WebAudio duration: ${this.audioBuffer.duration}`),this.audio.pause(),this.stopAndDisconnectSourceNode(),this.bufferSourceNode=this.createBufferSourceNode(),!this.bufferSourceNode){this.debug("Failed to create buffer source node for switch"),this.playbackType="HTML5";return}this.connectGainNode(),this.webAudioStartedPlayingAt=this.audioContext.currentTime-i,this.webAudioPausedDuration=0,this.webAudioPausedAt=0;try{this.bufferSourceNode.start(0,i),this.debug(`WebAudio started at context time ${this.audioContext.currentTime}, track time ${i}`)}catch(s){console.error("Error starting buffer source node:",s),this.playbackType="HTML5",this.disconnectGainNode();return}t||e?(this.pauseWebAudio(),this.debug("Switched to WebAudio (Paused)")):(this.bufferSourceNode.playbackRate.value=1,this.debug("Switched to WebAudio (Playing)")),this.playbackType="WEBAUDIO"}pause(){this.debug("pause command received"),this.isUsingWebAudio?this.pauseWebAudio():(this.audio.pause(),this.cancelProgressFrame())}pauseWebAudio(){!this.audioContext||!this.bufferSourceNode||this.isPaused||(this.webAudioPausedAt=this.audioContext.currentTime,this.disconnectGainNode(),this.debug(`WebAudio paused at ${this.webAudioPausedAt}`),this.cancelProgressFrame())}play(){this.debug("play command received"),this.audioBuffer&&this.audioContext&&!this.queue.state.webAudioIsDisabled?this.isUsingWebAudio?this.playWebAudio():this.webAudioLoadingState==="LOADED"?(this.debug("WebAudio buffer ready, switching from HTML5..."),this.switchToWebAudio(),this.requestProgressFrame()):this.webAudioLoadingState==="LOADING"?(this.debug("WebAudio loading, playing HTML5 temporarily..."),this.playHtml5Audio()):(this.debug("WebAudio not loaded, starting load and playing HTML5..."),this.preload(),this.playHtml5Audio()):this.playHtml5Audio(),this.queue.loadTrack(this.idx+1)}playWebAudio(){if(!(!this.audioContext||!this.bufferSourceNode||!this.isPaused)){if(this.webAudioPausedAt>0){let e=this.audioContext.currentTime-this.webAudioPausedAt;this.webAudioPausedDuration+=e,this.debug(`Resuming WebAudio after ${e.toFixed(2)}s pause. Total paused: ${this.webAudioPausedDuration.toFixed(2)}s`)}this.connectGainNode(),this.webAudioPausedAt=0,this.debug("WebAudio playing"),this.requestProgressFrame()}}playHtml5Audio(){if(!this.audio.paused)return;this.audio.preload!=="auto"&&(this.audio.preload="auto");let e=this.audio.play();e!==void 0?e.then(t=>{this.debug("HTML5 playing"),this.requestProgressFrame(),!this.queue.state.webAudioIsDisabled&&this.webAudioLoadingState==="NONE"&&this.preload()}).catch(t=>{console.error(`Error playing HTML5 audio for track ${this.idx}:`,t),this.boundAudioOnError(`Playback error: ${t.message}`)}):(this.debug("HTML5 playing (no promise)"),this.requestProgressFrame(),!this.queue.state.webAudioIsDisabled&&this.webAudioLoadingState==="NONE"&&this.preload())}togglePlayPause(){this.isPaused?this.play():this.pause()}preload(e=!1){this.debug(`preload called, loadHTML5: ${e}`),e&&this.audio.preload!=="auto"&&this.audio.readyState<2&&(this.debug("preloading HTML5"),this.audio.preload="auto"),!this.queue.state.webAudioIsDisabled&&this.webAudioLoadingState==="NONE"&&(this.debug("preloading WebAudio buffer"),this.skipHEAD?this.loadBuffer():this.loadHEAD(()=>this.loadBuffer()))}seek(e=0){let t=this.duration;if(isNaN(t)||t<=0){this.debug("Cannot seek: duration unknown or invalid.");return}let i=Math.max(0,Math.min(e,t));this.debug(`seek command to: ${i} (original: ${e})`),this.isUsingWebAudio&&this.audioContext?this.seekBufferSourceNode(i):this.audio.readyState>=this.audio.HAVE_METADATA?this.audio.currentTime=i:this.debug("Cannot seek HTML5: not ready."),this.onProgress()}seekBufferSourceNode(e){if(!this.audioContext||!this.audioBuffer||!this.gainNode){this.debug("Cannot seek WebAudio: context, buffer, or gain node missing.");return}let t=this.isPaused;if(this.debug(`Seeking WebAudio to ${e}. Was paused: ${t}`),this.stopAndDisconnectSourceNode(),this.bufferSourceNode=this.createBufferSourceNode(),!this.bufferSourceNode){this.debug("Failed to create buffer source node for seek");return}this.webAudioStartedPlayingAt=this.audioContext.currentTime-e,this.webAudioPausedDuration=0,this.webAudioPausedAt=0;try{this.bufferSourceNode.start(0,e),this.debug(`WebAudio started after seek at context time ${this.audioContext.currentTime}, track time ${e}`)}catch(i){console.error("Error starting buffer source node after seek:",i),this.disconnectGainNode();return}t?(this.pauseWebAudio(),this.debug("Re-applied paused state after seek.")):(this.connectGainNode(),this.debug("Resumed playing state after seek."),this.requestProgressFrame())}stopAndDisconnectSourceNode(){if(this.bufferSourceNode){try{this.bufferSourceNode.onended=null,this.bufferSourceNode.stop(),this.bufferSourceNode.disconnect(),this.debug("Stopped and disconnected previous source node.")}catch(e){e.name!=="InvalidStateError"&&console.error("Error stopping buffer source node:",e)}this.bufferSourceNode=null}}connectGainNode(){if(this.gainNode&&this.audioContext)try{this.gainNode.connect(this.audioContext.destination)}catch(e){console.error("Error connecting gain node:",e)}}disconnectGainNode(){if(this.gainNode&&this.audioContext)try{this.gainNode.disconnect(this.audioContext.destination)}catch{}}audioOnError=e=>{let t=e;if(typeof e!="string"&&e.target){let i=e.target.error;t=`HTML5 Audio Error: code=${i==null?void 0:i.code}, message=${i==null?void 0:i.message}`}this.debug("audioOnError",t)};onEnded(e){this.debug("onEnded triggered",`from: ${typeof e=="string"?e:"event"}`,`isActive: ${this.isActiveTrack}`),this.bufferSourceNode&&(this.bufferSourceNode.onended=null),this.audio.onended=null,this.cancelProgressFrame(),this.isActiveTrack?this.queue.playNext():(this.debug("onEnded ignored for inactive track"),this.resetStateAfterEnded())}resetStateAfterEnded(){this.webAudioStartedPlayingAt=0,this.webAudioPausedDuration=0,this.webAudioPausedAt=0,this.stopAndDisconnectSourceNode(),this.audio.readyState>0&&(this.audio.currentTime=0),this.audio.onended=()=>this.boundOnEnded("HTML5"),this.bufferSourceNode&&this.audioContext}onProgress(){if(!this.isActiveTrack||this.isPaused){this.cancelProgressFrame();return}let e=this.currentTime,t=this.duration;if(isNaN(e)||isNaN(t)||t<=0){this.requestProgressFrame();return}let i=t-e<=25,s=this.queue.nextTrack;i&&s&&!s.isLoaded&&this.queue.loadTrack(this.idx+1,!0),this.queue.onProgress(this),this.requestProgressFrame()}requestProgressFrame(){this.cancelProgressFrame(),this.progressFrameId=window.requestAnimationFrame(this.boundOnProgress)}cancelProgressFrame(){this.progressFrameId!==null&&(window.cancelAnimationFrame(this.progressFrameId),this.progressFrameId=null)}setVolume(e){let t=Math.max(0,Math.min(1,e));this.audio.volume=t,this.gainNode&&(this.gainNode.gain.value=t)}get isUsingWebAudio(){return this.playbackType==="WEBAUDIO"&&!this.queue.state.webAudioIsDisabled}get isPaused(){return this.isUsingWebAudio&&this.audioContext?this.webAudioPausedAt>0:this.audio.paused}get currentTime(){return this.isUsingWebAudio&&this.audioContext?this.webAudioPausedAt>0?this.webAudioStartedPlayingAt>0?this.webAudioPausedAt-this.webAudioStartedPlayingAt-this.webAudioPausedDuration:0:this.webAudioStartedPlayingAt>0?this.audioContext.currentTime-this.webAudioStartedPlayingAt-this.webAudioPausedDuration:0:this.audio.currentTime}get duration(){return this.isUsingWebAudio&&this.audioBuffer?this.audioBuffer.duration:this.audio.duration}get isActiveTrack(){return this.queue.currentTrack===this}get isLoaded(){return this.webAudioLoadingState==="LOADED"||this.audio.readyState>=this.audio.HAVE_FUTURE_DATA}get state(){return{playbackType:this.playbackType,webAudioLoadingState:this.webAudioLoadingState}}get completeState(){var e;return{playbackType:this.playbackType,webAudioLoadingState:this.webAudioLoadingState,isPaused:this.isPaused,currentTime:this.currentTime,duration:this.duration,idx:this.idx,id:(e=this.metadata)==null?void 0:e.trackId}}debug(e,...t){console.debug(`[Track ${this.idx} | ${this.playbackType} | ${this.webAudioLoadingState}] ${e}`,...t,this.completeState)}seekToEnd(e=6){let t=this.duration;!isNaN(t)&&t>e?this.seek(t-e):this.debug(`Cannot seekToEnd: duration invalid or too short (${t})`)}};var g=2,A=typeof window<"u",u=A&&typeof window.AudioContext<"u"?new window.AudioContext:null,r=class{props;state;tracks;Track;constructor(e={}){let{tracks:t=[],onProgress:i=()=>{},onEnded:s=()=>{},onPlayNextTrack:d=()=>{},onPlayPreviousTrack:a=()=>{},onStartNewTrack:h=()=>{},webAudioIsDisabled:c=!1}=e;this.props={onProgress:i,onEnded:s,onPlayNextTrack:d,onPlayPreviousTrack:a,onStartNewTrack:h},this.state={volume:1,currentTrackIdx:0,webAudioIsDisabled:c},this.Track=o,this.tracks=t.map((l,b)=>new o({trackUrl:l,idx:b,queue:this,metadata:{}})),u||this.disableWebAudio()}addTrack({trackUrl:e,skipHEAD:t,metadata:i={}}){this.tracks.push(new o({trackUrl:e,skipHEAD:t,metadata:i,idx:this.tracks.length,queue:this}))}removeTrack(e){let t=this.tracks.indexOf(e);return t>-1?this.tracks.splice(t,1):[]}togglePlayPause(){this.currentTrack&&this.currentTrack.togglePlayPause()}play(){this.currentTrack&&this.currentTrack.play()}pause(){this.currentTrack&&this.currentTrack.pause()}playPrevious(){if(this.currentTrack&&this.currentTrack.currentTime>8){this.currentTrack.seek(0);return}this.resetCurrentTrack(),--this.state.currentTrackIdx<0&&(this.state.currentTrackIdx=0),this.play(),this.props.onStartNewTrack&&this.props.onStartNewTrack(this.currentTrack),this.props.onPlayPreviousTrack&&this.props.onPlayPreviousTrack(this.currentTrack)}playNext(){if(this.resetCurrentTrack(),this.state.currentTrackIdx<this.tracks.length-1)this.state.currentTrackIdx++;else{this.props.onEnded();return}this.play(),this.props.onStartNewTrack&&this.props.onStartNewTrack(this.currentTrack),this.props.onPlayNextTrack&&this.props.onPlayNextTrack(this.currentTrack)}resetCurrentTrack(){if(this.currentTrack)try{this.currentTrack.isPaused||this.currentTrack.pause(),this.currentTrack.duration>0&&!isNaN(this.currentTrack.duration)&&this.currentTrack.seek(0)}catch(e){console.error("Error resetting track:",e,this.currentTrack)}}pauseAll(){this.tracks.forEach(e=>{e.pause()})}cleanUp(){this.tracks.forEach(e=>{e.bufferSourceNode&&e.bufferSourceNode.buffer&&(e.bufferSourceNode.buffer=null),e.audioBuffer&&(e.audioBuffer=null);try{e.bufferSourceNode&&(e.bufferSourceNode.onended=null,e.bufferSourceNode.stop(),e.bufferSourceNode.disconnect()),e.gainNode&&u&&e.gainNode.disconnect(),e.audio&&(e.audio.pause(),e.audio.src="",e.audio.load(),e.audio.onended=null,e.audio.onerror=null)}catch(t){console.error("Error during track cleanup:",t,e)}})}gotoTrack(e,t=!1){if(e<0||e>=this.tracks.length){console.warn(`gotoTrack: Index ${e} out of bounds.`);return}this.pauseAll(),this.resetCurrentTrack(),this.state.currentTrackIdx=e,t&&(this.play(),this.props.onStartNewTrack&&this.props.onStartNewTrack(this.currentTrack))}loadTrack(e,t){if(e<0||e>=this.tracks.length||this.state.currentTrackIdx+g<e)return;let i=this.tracks[e];i&&i.preload(t)}setProps(e={}){this.props={...this.props,...e}}onEnded(){this.props.onEnded&&this.props.onEnded()}onProgress(e){this.props.onProgress&&this.props.onProgress(e)}get currentTrack(){return this.tracks[this.state.currentTrackIdx]}get nextTrack(){return this.tracks[this.state.currentTrackIdx+1]}disableWebAudio(){this.state.webAudioIsDisabled=!0,this.tracks.forEach(e=>{e.isUsingWebAudio&&console.warn("Web Audio disabled while track was using it. State might be inconsistent.")})}setVolume(e){let t=Math.max(0,Math.min(1,e));this.state.volume=t,this.tracks.forEach(i=>i.setVolume(t))}};export{r as default};
1
+ function Te(){if(typeof globalThis<"u")return globalThis;if(typeof self<"u")return self;if(typeof window<"u")return window;if(typeof global<"u")return global}function Se(){let n=Te();if(n.__xstate__)return n.__xstate__}var Pt=n=>{if(typeof window>"u")return;let t=Se();t&&t.register(n)};var Z=class{constructor(t){this._process=t,this._active=!1,this._current=null,this._last=null}start(){this._active=!0,this.flush()}clear(){this._current&&(this._current.next=null,this._last=this._current)}enqueue(t){let e={value:t,next:null};if(this._current){this._last.next=e,this._last=e;return}this._current=e,this._last=e,this._active&&this.flush()}flush(){for(;this._current;){let t=this._current;this._process(t.value),this._current=t.next}this._last=null}},Tt=".",xe="",St="",ke="#",be="*",Mt="xstate.init",Nt="xstate.error",gt="xstate.stop";function Ae(n,t){return{type:`xstate.after.${n}.${t}`}}function yt(n,t){return{type:`xstate.done.state.${n}`,output:t}}function Ee(n,t){return{type:`xstate.done.actor.${n}`,output:t,actorId:n}}function xt(n,t){return{type:`xstate.error.actor.${n}`,error:t,actorId:n}}function nt(n){return{type:Mt,input:n}}function T(n){setTimeout(()=>{throw n})}var Ie=typeof Symbol=="function"&&Symbol.observable||"@@observable";function kt(n,t){let e=Ot(n),s=Ot(t);return typeof s=="string"?typeof e=="string"?s===e:!1:typeof e=="string"?e in s:Object.keys(e).every(i=>i in s?kt(e[i],s[i]):!1)}function st(n){if(Gt(n))return n;let t=[],e="";for(let s=0;s<n.length;s++){switch(n.charCodeAt(s)){case 92:e+=n[s+1],s++;continue;case 46:t.push(e),e="";continue}e+=n[s]}return t.push(e),t}function Ot(n){if(re(n))return n.value;if(typeof n!="string")return n;let t=st(n);return Ut(t)}function Ut(n){if(n.length===1)return n[0];let t={},e=t;for(let s=0;s<n.length-1;s++)if(s===n.length-2)e[n[s]]=n[s+1];else{let i=e;e={},i[n[s]]=e}return t}function bt(n,t){let e={},s=Object.keys(n);for(let i=0;i<s.length;i++){let r=s[i];e[r]=t(n[r],r,n,i)}return e}function Bt(n){return Gt(n)?n:[n]}function S(n){return n===void 0?[]:Bt(n)}function _t(n,t,e,s){return typeof n=="function"?n({context:t,event:e,self:s}):n}function Gt(n){return Array.isArray(n)}function we(n){return n.type.startsWith("xstate.error.actor")}function A(n){return Bt(n).map(t=>typeof t>"u"||typeof t=="string"?{target:t}:t)}function qt(n){if(!(n===void 0||n===xe))return S(n)}function tt(n,t,e){var r,o,a;let s=typeof n=="object",i=s?n:void 0;return{next:(r=s?n.next:n)==null?void 0:r.bind(i),error:(o=s?n.error:t)==null?void 0:o.bind(i),complete:(a=s?n.complete:e)==null?void 0:a.bind(i)}}function At(n,t){return`${t}.${n}`}function H(n,t){let e=t.match(/^xstate\.invoke\.(\d+)\.(.*)/);if(!e)return n.implementations.actors[t];let[,s,i]=e,o=n.getStateNodeById(i).config.invoke;return(Array.isArray(o)?o[s]:o).src}function Wt(n,t){if(t===n||t===be)return!0;if(!t.endsWith(".*"))return!1;let e=t.split("."),s=n.split(".");for(let i=0;i<e.length;i++){let r=e[i],o=s[i];if(r==="*")return i===e.length-1;if(r!==o)return!1}return!0}function Rt(n,t){return`${n.sessionId}.${t}`}var De=0;function Pe(n,t){let e=new Map,s=new Map,i=new WeakMap,r=new Set,o={},{clock:a,logger:c}=t,f={schedule:(u,l,h,y,_=Math.random().toString(36).slice(2))=>{let P={source:u,target:l,event:h,delay:y,id:_,startedAt:Date.now()},O=Rt(u,_);d._snapshot._scheduledEvents[O]=P;let ve=a.setTimeout(()=>{delete o[O],delete d._snapshot._scheduledEvents[O],d._relay(u,l,h)},y);o[O]=ve},cancel:(u,l)=>{let h=Rt(u,l),y=o[h];delete o[h],delete d._snapshot._scheduledEvents[h],y!==void 0&&a.clearTimeout(y)},cancelAll:u=>{for(let l in d._snapshot._scheduledEvents){let h=d._snapshot._scheduledEvents[l];h.source===u&&f.cancel(u,h.id)}}},p=u=>{if(!r.size)return;let l={...u,rootId:n.sessionId};r.forEach(h=>{var y;return(y=h.next)==null?void 0:y.call(h,l)})},d={_snapshot:{_scheduledEvents:((t==null?void 0:t.snapshot)&&t.snapshot.scheduler)??{}},_bookId:()=>`x:${De++}`,_register:(u,l)=>(e.set(u,l),u),_unregister:u=>{e.delete(u.sessionId);let l=i.get(u);l!==void 0&&(s.delete(l),i.delete(u))},get:u=>s.get(u),getAll:()=>Object.fromEntries(s.entries()),_set:(u,l)=>{let h=s.get(u);if(h&&h!==l)throw new Error(`Actor with system ID '${u}' already exists.`);s.set(u,l),i.set(l,u)},inspect:u=>{let l=tt(u);return r.add(l),{unsubscribe(){r.delete(l)}}},_sendInspectionEvent:p,_relay:(u,l,h)=>{d._sendInspectionEvent({type:"@xstate.event",sourceRef:u,actorRef:l,event:h}),l._send(h)},scheduler:f,getSnapshot:()=>({_scheduledEvents:{...d._snapshot._scheduledEvents}}),start:()=>{let u=d._snapshot._scheduledEvents;d._snapshot._scheduledEvents={};for(let l in u){let{source:h,target:y,event:_,delay:P,id:O}=u[l];f.schedule(h,y,_,P,O)}},_clock:a,_logger:c};return d}var ft=!1,it=1,m=(function(n){return n[n.NotStarted=0]="NotStarted",n[n.Running=1]="Running",n[n.Stopped=2]="Stopped",n})({}),Oe={clock:{setTimeout:(n,t)=>setTimeout(n,t),clearTimeout:n=>clearTimeout(n)},logger:console.log.bind(console),devTools:!1},et=class{constructor(t,e){this.logic=t,this._snapshot=void 0,this.clock=void 0,this.options=void 0,this.id=void 0,this.mailbox=new Z(this._process.bind(this)),this.observers=new Set,this.eventListeners=new Map,this.logger=void 0,this._processingStatus=m.NotStarted,this._parent=void 0,this._syncSnapshot=void 0,this.ref=void 0,this._actorScope=void 0,this.systemId=void 0,this.sessionId=void 0,this.system=void 0,this._doneEvent=void 0,this.src=void 0,this._deferred=[];let s={...Oe,...e},{clock:i,logger:r,parent:o,syncSnapshot:a,id:c,systemId:f,inspect:p}=s;this.system=o?o.system:Pe(this,{clock:i,logger:r}),p&&!o&&this.system.inspect(tt(p)),this.sessionId=this.system._bookId(),this.id=c??this.sessionId,this.logger=(e==null?void 0:e.logger)??this.system._logger,this.clock=(e==null?void 0:e.clock)??this.system._clock,this._parent=o,this._syncSnapshot=a,this.options=s,this.src=s.src??t,this.ref=this,this._actorScope={self:this,id:this.id,sessionId:this.sessionId,logger:this.logger,defer:d=>{this._deferred.push(d)},system:this.system,stopChild:d=>{if(d._parent!==this)throw new Error(`Cannot stop child actor ${d.id} of ${this.id} because it is not a child`);d._stop()},emit:d=>{let u=this.eventListeners.get(d.type),l=this.eventListeners.get("*");if(!u&&!l)return;let h=[...u?u.values():[],...l?l.values():[]];for(let y of h)try{y(d)}catch(_){T(_)}},actionExecutor:d=>{let u=()=>{if(this._actorScope.system._sendInspectionEvent({type:"@xstate.action",actorRef:this,action:{type:d.type,params:d.params}}),!d.exec)return;let l=ft;try{ft=!0,d.exec(d.info,d.params)}finally{ft=l}};this._processingStatus===m.Running?u():this._deferred.push(u)}},this.send=this.send.bind(this),this.system._sendInspectionEvent({type:"@xstate.actor",actorRef:this}),f&&(this.systemId=f,this.system._set(f,this)),this._initState((e==null?void 0:e.snapshot)??(e==null?void 0:e.state)),f&&this._snapshot.status!=="active"&&this.system._unregister(this)}_initState(t){var e;try{this._snapshot=t?this.logic.restoreSnapshot?this.logic.restoreSnapshot(t,this._actorScope):t:this.logic.getInitialSnapshot(this._actorScope,(e=this.options)==null?void 0:e.input)}catch(s){this._snapshot={status:"error",output:void 0,error:s}}}update(t,e){var i,r;this._snapshot=t;let s;for(;s=this._deferred.shift();)try{s()}catch(o){this._deferred.length=0,this._snapshot={...t,status:"error",error:o}}switch(this._snapshot.status){case"active":for(let o of this.observers)try{(i=o.next)==null||i.call(o,t)}catch(a){T(a)}break;case"done":for(let o of this.observers)try{(r=o.next)==null||r.call(o,t)}catch(a){T(a)}this._stopProcedure(),this._complete(),this._doneEvent=Ee(this.id,this._snapshot.output),this._parent&&this.system._relay(this,this._parent,this._doneEvent);break;case"error":this._error(this._snapshot.error);break}this.system._sendInspectionEvent({type:"@xstate.snapshot",actorRef:this,event:e,snapshot:t})}subscribe(t,e,s){var r;let i=tt(t,e,s);if(this._processingStatus!==m.Stopped)this.observers.add(i);else switch(this._snapshot.status){case"done":try{(r=i.complete)==null||r.call(i)}catch(o){T(o)}break;case"error":{let o=this._snapshot.error;if(!i.error)T(o);else try{i.error(o)}catch(a){T(a)}break}}return{unsubscribe:()=>{this.observers.delete(i)}}}on(t,e){let s=this.eventListeners.get(t);s||(s=new Set,this.eventListeners.set(t,s));let i=e.bind(void 0);return s.add(i),{unsubscribe:()=>{s.delete(i)}}}start(){if(this._processingStatus===m.Running)return this;this._syncSnapshot&&this.subscribe({next:s=>{s.status==="active"&&this.system._relay(this,this._parent,{type:`xstate.snapshot.${this.id}`,snapshot:s})},error:()=>{}}),this.system._register(this.sessionId,this),this.systemId&&this.system._set(this.systemId,this),this._processingStatus=m.Running;let t=nt(this.options.input);switch(this.system._sendInspectionEvent({type:"@xstate.event",sourceRef:this._parent,actorRef:this,event:t}),this._snapshot.status){case"done":return this.update(this._snapshot,t),this;case"error":return this._error(this._snapshot.error),this}if(this._parent||this.system.start(),this.logic.start)try{this.logic.start(this._snapshot,this._actorScope)}catch(s){return this._snapshot={...this._snapshot,status:"error",error:s},this._error(s),this}return this.update(this._snapshot,t),this.options.devTools&&this.attachDevTools(),this.mailbox.start(),this}_process(t){let e,s;try{e=this.logic.transition(this._snapshot,t,this._actorScope)}catch(i){s={err:i}}if(s){let{err:i}=s;this._snapshot={...this._snapshot,status:"error",error:i},this._error(i);return}this.update(e,t),t.type===gt&&(this._stopProcedure(),this._complete())}_stop(){return this._processingStatus===m.Stopped?this:(this.mailbox.clear(),this._processingStatus===m.NotStarted?(this._processingStatus=m.Stopped,this):(this.mailbox.enqueue({type:gt}),this))}stop(){if(this._parent)throw new Error("A non-root actor cannot be stopped directly.");return this._stop()}_complete(){var t;for(let e of this.observers)try{(t=e.complete)==null||t.call(e)}catch(s){T(s)}this.observers.clear(),this.eventListeners.clear()}_reportError(t){if(!this.observers.size){this._parent||T(t),this.eventListeners.clear();return}let e=!1;for(let s of this.observers){let i=s.error;e||=!i;try{i==null||i(t)}catch(r){T(r)}}this.observers.clear(),this.eventListeners.clear(),e&&T(t)}_error(t){this._stopProcedure(),this._reportError(t),this._parent&&this.system._relay(this,this._parent,xt(this.id,t))}_stopProcedure(){return this._processingStatus!==m.Running?this:(this.system.scheduler.cancelAll(this),this.mailbox.clear(),this.mailbox=new Z(this._process.bind(this)),this._processingStatus=m.Stopped,this.system._unregister(this),this)}_send(t){this._processingStatus!==m.Stopped&&this.mailbox.enqueue(t)}send(t){this.system._relay(void 0,this,t)}attachDevTools(){let{devTools:t}=this.options;t&&(typeof t=="function"?t:Pt)(this)}toJSON(){return{xstate$$type:it,id:this.id}}getPersistedSnapshot(t){return this.logic.getPersistedSnapshot(this._snapshot,t)}[Ie](){return this}getSnapshot(){return this._snapshot}};function v(n,...[t]){return new et(n,t)}function Re(n,t,e,s,{sendId:i}){let r=typeof i=="function"?i(e,s):i;return[t,{sendId:r},void 0]}function Le(n,t){n.defer(()=>{n.system.scheduler.cancel(n.self,t.sendId)})}function $(n){function t(e,s){}return t.type="xstate.cancel",t.sendId=n,t.resolve=Re,t.execute=Le,t}function Ce(n,t,e,s,{id:i,systemId:r,src:o,input:a,syncSnapshot:c}){let f=typeof o=="string"?H(t.machine,o):o,p=typeof i=="function"?i(e):i,d,u;return f&&(u=typeof a=="function"?a({context:t.context,event:e.event,self:n.self}):a,d=v(f,{id:p,src:o,parent:n.self,syncSnapshot:c,systemId:r,input:u})),[b(t,{children:{...t.children,[p]:d}}),{id:i,systemId:r,actorRef:d,src:o,input:u},void 0]}function $e(n,{actorRef:t}){t&&n.defer(()=>{t._processingStatus!==m.Stopped&&t.start()})}function M(...[n,{id:t,systemId:e,input:s,syncSnapshot:i=!1}={}]){function r(o,a){}return r.type="xstate.spawnChild",r.id=t,r.systemId=e,r.src=n,r.input=s,r.syncSnapshot=i,r.resolve=Ce,r.execute=$e,r}function Me(n,t,e,s,{actorRef:i}){let r=typeof i=="function"?i(e,s):i,o=typeof r=="string"?t.children[r]:r,a=t.children;return o&&(a={...a},delete a[o.id]),[b(t,{children:a}),o,void 0]}function Ht(n,t){let e=t.getSnapshot();if(e&&"children"in e)for(let s of Object.values(e.children))Ht(n,s);n.system._unregister(t)}function Ne(n,t){if(t){if(Ht(n,t),t._processingStatus!==m.Running){n.stopChild(t);return}n.defer(()=>{n.stopChild(t)})}}function w(n){function t(e,s){}return t.type="xstate.stopChild",t.actorRef=n,t.resolve=Me,t.execute=Ne,t}function N(n,t,e,s){let{machine:i}=s,r=typeof n=="function",o=r?n:i.implementations.guards[typeof n=="string"?n:n.type];if(!r&&!o)throw new Error(`Guard '${typeof n=="string"?n:n.type}' is not implemented.'.`);if(typeof o!="function")return N(o,t,e,s);let a={context:t,event:e},c=r||typeof n=="string"?void 0:"params"in n?typeof n.params=="function"?n.params({context:t,event:e}):n.params:void 0;return"check"in o?o.check(s,a,o):o(a,c)}function rt(n){return n.type==="atomic"||n.type==="final"}function L(n){return Object.values(n.states).filter(t=>t.type!=="history")}function U(n,t){let e=[];if(t===n)return e;let s=n.parent;for(;s&&s!==t;)e.push(s),s=s.parent;return e}function j(n){let t=new Set(n),e=Vt(t);for(let s of t)if(s.type==="compound"&&(!e.get(s)||!e.get(s).length))Lt(s).forEach(i=>t.add(i));else if(s.type==="parallel"){for(let i of L(s))if(i.type!=="history"&&!t.has(i)){let r=Lt(i);for(let o of r)t.add(o)}}for(let s of t){let i=s.parent;for(;i;)t.add(i),i=i.parent}return t}function jt(n,t){let e=t.get(n);if(!e)return{};if(n.type==="compound"){let i=e[0];if(i){if(rt(i))return i.key}else return{}}let s={};for(let i of e)s[i.key]=jt(i,t);return s}function Vt(n){let t=new Map;for(let e of n)t.has(e)||t.set(e,[]),e.parent&&(t.has(e.parent)||t.set(e.parent,[]),t.get(e.parent).push(e));return t}function Ft(n,t){let e=j(t);return jt(n,Vt(e))}function ot(n,t){return t.type==="compound"?L(t).some(e=>e.type==="final"&&n.has(e)):t.type==="parallel"?L(t).every(e=>ot(n,e)):t.type==="final"}var V=n=>n[0]===ke;function Kt(n,t){return n.transitions.get(t)||[...n.transitions.keys()].filter(s=>Wt(t,s)).sort((s,i)=>i.length-s.length).flatMap(s=>n.transitions.get(s))}function Yt(n){let t=n.config.after;if(!t)return[];let e=i=>{let r=Ae(i,n.id),o=r.type;return n.entry.push(G(r,{id:o,delay:i})),n.exit.push($(o)),o};return Object.keys(t).flatMap(i=>{let r=t[i],o=typeof r=="string"?{target:r}:r,a=Number.isNaN(+i)?i:+i,c=e(a);return S(o).map(f=>({...f,event:c,delay:a}))}).map(i=>{let{delay:r}=i;return{...x(n,i.event,i),delay:r}})}function x(n,t,e){let s=qt(e.target),i=e.reenter??!1,r=Ue(n,s),o={...e,actions:S(e.actions),guard:e.guard,target:r,source:n,reenter:i,eventType:t,toJSON:()=>({...o,source:`#${n.id}`,target:r?r.map(a=>`#${a.id}`):void 0})};return o}function Jt(n){let t=new Map;if(n.config.on)for(let e of Object.keys(n.config.on)){if(e===St)throw new Error('Null events ("") cannot be specified as a transition key. Use `always: { ... }` instead.');let s=n.config.on[e];t.set(e,A(s).map(i=>x(n,e,i)))}if(n.config.onDone){let e=`xstate.done.state.${n.id}`;t.set(e,A(n.config.onDone).map(s=>x(n,e,s)))}for(let e of n.invoke){if(e.onDone){let s=`xstate.done.actor.${e.id}`;t.set(s,A(e.onDone).map(i=>x(n,s,i)))}if(e.onError){let s=`xstate.error.actor.${e.id}`;t.set(s,A(e.onError).map(i=>x(n,s,i)))}if(e.onSnapshot){let s=`xstate.snapshot.${e.id}`;t.set(s,A(e.onSnapshot).map(i=>x(n,s,i)))}}for(let e of n.after){let s=t.get(e.eventType);s||(s=[],t.set(e.eventType,s)),s.push(e)}return t}function Xt(n){let t=[],e=s=>{Object.values(s).forEach(i=>{if(i.config.route&&i.config.id){let r=i.config.id,o=i.config.route.guard,a=(f,p)=>f.event.to!==`#${r}`?!1:o&&typeof o=="function"?o(f,p):!0,c={...i.config.route,guard:a,target:`#${r}`};t.push(x(n,"xstate.route",c))}i.states&&e(i.states)})};e(n.states),t.length>0&&n.transitions.set("xstate.route",t)}function zt(n,t){let e=typeof t=="string"?n.states[t]:t?n.states[t.target]:void 0;if(!e&&t)throw new Error(`Initial state node "${t}" not found on parent state node #${n.id}`);let s={source:n,actions:!t||typeof t=="string"?[]:S(t.actions),eventType:null,reenter:!1,target:e?[e]:[],toJSON:()=>({...s,source:`#${n.id}`,target:e?[`#${e.id}`]:[]})};return s}function Ue(n,t){if(t!==void 0)return t.map(e=>{if(typeof e!="string")return e;if(V(e))return n.machine.getStateNodeById(e);let s=e[0]===Tt;if(s&&!n.parent)return W(n,e.slice(1));let i=s?n.key+e:e;if(n.parent)try{return W(n.parent,i)}catch(r){throw new Error(`Invalid transition definition for state node '${n.id}':
2
+ ${r.message}`)}else throw new Error(`Invalid target: "${e}" is not a valid target from the root node. Did you mean ".${e}"?`)})}function Qt(n){let t=qt(n.config.target);return t?{target:t.map(e=>typeof e=="string"?W(n.parent,e):e)}:n.parent.initial}function E(n){return n.type==="history"}function Lt(n){let t=Zt(n);for(let e of t)for(let s of U(e,n))t.add(s);return t}function Zt(n){let t=new Set;function e(s){if(!t.has(s)){if(t.add(s),s.type==="compound")e(s.initial.target[0]);else if(s.type==="parallel")for(let i of L(s))e(i)}}return e(n),t}function C(n,t){if(V(t))return n.machine.getStateNodeById(t);if(!n.states)throw new Error(`Unable to retrieve child state '${t}' from '${n.id}'; no child states exist.`);let e=n.states[t];if(!e)throw new Error(`Child state '${t}' does not exist on '${n.id}'`);return e}function W(n,t){if(typeof t=="string"&&V(t))try{return n.machine.getStateNodeById(t)}catch{}let e=st(t).slice(),s=n;for(;e.length;){let i=e.shift();if(!i.length)break;s=C(s,i)}return s}function B(n,t){if(typeof t=="string"){let i=n.states[t];if(!i)throw new Error(`State '${t}' does not exist on '${n.id}'`);return[n,i]}let e=Object.keys(t),s=e.map(i=>C(n,i)).filter(Boolean);return[n.machine.root,n].concat(s,e.reduce((i,r)=>{let o=C(n,r);if(!o)return i;let a=B(o,t[r]);return i.concat(a)},[]))}function Be(n,t,e,s){let r=C(n,t).next(e,s);return!r||!r.length?n.next(e,s):r}function Ge(n,t,e,s){let i=Object.keys(t),r=C(n,i[0]),o=at(r,t[i[0]],e,s);return!o||!o.length?n.next(e,s):o}function qe(n,t,e,s){let i=[];for(let r of Object.keys(t)){let o=t[r];if(!o)continue;let a=C(n,r),c=at(a,o,e,s);c&&i.push(...c)}return i.length?i:n.next(e,s)}function at(n,t,e,s){return typeof t=="string"?Be(n,t,e,s):Object.keys(t).length===1?Ge(n,t,e,s):qe(n,t,e,s)}function We(n){return Object.keys(n.states).map(t=>n.states[t]).filter(t=>t.type==="history")}function k(n,t){let e=n;for(;e.parent&&e.parent!==t;)e=e.parent;return e.parent===t}function He(n,t){let e=new Set(n),s=new Set(t);for(let i of e)if(s.has(i))return!0;for(let i of s)if(e.has(i))return!0;return!1}function te(n,t,e){let s=new Set;for(let i of n){let r=!1,o=new Set;for(let a of s)if(He(mt([i],t,e),mt([a],t,e)))if(k(i.source,a.source))o.add(a);else{r=!0;break}if(!r){for(let a of o)s.delete(a);s.add(i)}}return Array.from(s)}function je(n){let[t,...e]=n;for(let s of U(t,void 0))if(e.every(i=>k(i,s)))return s}function Et(n,t){if(!n.target)return[];let e=new Set;for(let s of n.target)if(E(s))if(t[s.id])for(let i of t[s.id])e.add(i);else for(let i of Et(Qt(s),t))e.add(i);else e.add(s);return[...e]}function ee(n,t){let e=Et(n,t);if(!e)return;if(!n.reenter&&e.every(i=>i===n.source||k(i,n.source)))return n.source;let s=je(e.concat(n.source));if(s)return s;if(!n.reenter)return n.source.machine.root}function mt(n,t,e){var i;let s=new Set;for(let r of n)if((i=r.target)!=null&&i.length){let o=ee(r,e);r.reenter&&r.source===o&&s.add(o);for(let a of t)k(a,o)&&s.add(a)}return[...s]}function Ve(n,t){if(n.length!==t.size)return!1;for(let e of n)if(!t.has(e))return!1;return!0}function It(n,t,e,s,i){return vt([{target:[...Zt(n)],source:n,reenter:!0,actions:[],eventType:null,toJSON:null}],t,e,s,!0,i)}function vt(n,t,e,s,i,r){let o=[];if(!n.length)return[t,o];let a=e.actionExecutor;e.actionExecutor=c=>{o.push(c),a(c)};try{let c=new Set(t._nodes),f=t.historyValue,p=te(n,c,f),d=t;i||([d,f]=Je(d,s,e,p,c,f,r,e.actionExecutor)),d=I(d,s,e,p.flatMap(l=>l.actions),r,void 0),d=Ke(d,s,e,p,c,r,f,i);let u=[...c];d.status==="done"&&(d=I(d,s,e,u.sort((l,h)=>h.order-l.order).flatMap(l=>l.exit),r,void 0));try{return f===t.historyValue&&Ve(t._nodes,c)?[d,o]:[b(d,{_nodes:u,historyValue:f}),o]}catch(l){throw l}}finally{e.actionExecutor=a}}function Fe(n,t,e,s,i){if(s.output===void 0)return;let r=yt(i.id,i.output!==void 0&&i.parent?_t(i.output,n.context,t,e.self):void 0);return _t(s.output,n.context,r,e.self)}function Ke(n,t,e,s,i,r,o,a){let c=n,f=new Set,p=new Set;Ye(s,o,p,f),a&&p.add(n.machine.root);let d=new Set;for(let u of[...f].sort((l,h)=>l.order-h.order)){i.add(u);let l=[];l.push(...u.entry);for(let h of u.invoke)l.push(M(h.src,{...h,syncSnapshot:!!h.onSnapshot}));if(p.has(u)){let h=u.initial.actions;l.push(...h)}if(c=I(c,t,e,l,r,u.invoke.map(h=>h.id)),u.type==="final"){let h=u.parent,y=(h==null?void 0:h.type)==="parallel"?h:h==null?void 0:h.parent,_=y||u;for((h==null?void 0:h.type)==="compound"&&r.push(yt(h.id,u.output!==void 0?_t(u.output,c.context,t,e.self):void 0));(y==null?void 0:y.type)==="parallel"&&!d.has(y)&&ot(i,y);)d.add(y),r.push(yt(y.id)),_=y,y=y.parent;if(y)continue;c=b(c,{status:"done",output:Fe(c,t,e,c.machine.root,_)})}}return c}function Ye(n,t,e,s){for(let i of n){let r=ee(i,t);for(let a of i.target||[])!E(a)&&(i.source!==a||i.source!==r||i.reenter)&&(s.add(a),e.add(a)),R(a,t,e,s);let o=Et(i,t);for(let a of o){let c=U(a,r);(r==null?void 0:r.type)==="parallel"&&c.push(r),ne(s,t,e,c,!i.source.parent&&i.reenter?void 0:r)}}}function R(n,t,e,s){var i;if(E(n))if(t[n.id]){let r=t[n.id];for(let o of r)s.add(o),R(o,t,e,s);for(let o of r)pt(o,n.parent,s,t,e)}else{let r=Qt(n);for(let o of r.target)s.add(o),r===((i=n.parent)==null?void 0:i.initial)&&e.add(n.parent),R(o,t,e,s);for(let o of r.target)pt(o,n.parent,s,t,e)}else if(n.type==="compound"){let[r]=n.initial.target;E(r)||(s.add(r),e.add(r)),R(r,t,e,s),pt(r,n,s,t,e)}else if(n.type==="parallel")for(let r of L(n).filter(o=>!E(o)))[...s].some(o=>k(o,r))||(E(r)||(s.add(r),e.add(r)),R(r,t,e,s))}function ne(n,t,e,s,i){for(let r of s)if((!i||k(r,i))&&n.add(r),r.type==="parallel")for(let o of L(r).filter(a=>!E(a)))[...n].some(a=>k(a,o))||(n.add(o),R(o,t,e,n))}function pt(n,t,e,s,i){ne(e,s,i,U(n,t))}function Je(n,t,e,s,i,r,o,a){let c=n,f=mt(s,i,r);f.sort((d,u)=>u.order-d.order);let p;for(let d of f)for(let u of We(d)){let l;u.history==="deep"?l=h=>rt(h)&&k(h,d):l=h=>h.parent===d,p??={...r},p[u.id]=Array.from(i).filter(l)}for(let d of f)c=I(c,t,e,[...d.exit,...d.invoke.map(u=>w(u.id))],o,void 0),i.delete(d);return[c,p||r]}function Xe(n,t){return n.implementations.actions[t]}function se(n,t,e,s,i,r){let{machine:o}=n,a=n;for(let c of s){let f=typeof c=="function",p=f?c:Xe(o,typeof c=="string"?c:c.type),d={context:a.context,event:t,self:e.self,system:e.system},u=f||typeof c=="string"?void 0:"params"in c?typeof c.params=="function"?c.params({context:a.context,event:t}):c.params:void 0;if(!p||!("resolve"in p)){e.actionExecutor({type:typeof c=="string"?c:typeof c=="object"?c.type:c.name||"(anonymous)",info:d,params:u,exec:p});continue}let l=p,[h,y,_]=l.resolve(e,a,d,u,p,i);a=h,"retryResolve"in l&&(r==null||r.push([l,y])),"execute"in l&&e.actionExecutor({type:l.type,info:d,params:y,exec:l.execute.bind(null,e,y)}),_&&(a=se(a,t,e,_,i,r))}return a}function I(n,t,e,s,i,r){let o=r?[]:void 0,a=se(n,t,e,s,{internalQueue:i,deferredActorIds:r},o);return o==null||o.forEach(([c,f])=>{c.retryResolve(e,a,f)}),a}function F(n,t,e,s){let i=n,r=[];function o(f,p,d){e.system._sendInspectionEvent({type:"@xstate.microstep",actorRef:e.self,event:p,snapshot:f[0],_transitions:d}),r.push(f)}if(t.type===gt)return i=b(Ct(i,t,e),{status:"stopped"}),o([i,[]],t,[]),{snapshot:i,microsteps:r};let a=t;if(a.type!==Mt){let f=a,p=we(f),d=$t(f,i);if(p&&!d.length)return i=b(n,{status:"error",error:f.error}),o([i,[]],f,[]),{snapshot:i,microsteps:r};let u=vt(d,n,e,a,!1,s);i=u[0],o(u,f,d)}let c=!0;for(;i.status==="active";){let f=c?ze(i,a):[],p=f.length?i:void 0;if(!f.length){if(!s.length)break;a=s.shift(),f=$t(a,i)}let d=vt(f,i,e,a,!1,s);i=d[0],c=i!==p,o(d,a,f)}return i.status!=="active"&&Ct(i,a,e),{snapshot:i,microsteps:r}}function Ct(n,t,e){return I(n,t,e,Object.values(n.children).map(s=>w(s)),[],void 0)}function $t(n,t){return t.machine.getTransitionData(t,n)}function ze(n,t){let e=new Set,s=n._nodes.filter(rt);for(let i of s)t:for(let r of[i].concat(U(i,void 0)))if(r.always){for(let o of r.always)if(o.guard===void 0||N(o.guard,n.context,t,n)){e.add(o);break t}}return te(Array.from(e),new Set(n._nodes),n.historyValue)}function ie(n,t){let e=j(B(n,t));return Ft(n,[...e])}function re(n){return!!n&&typeof n=="object"&&"machine"in n&&"value"in n}var Qe=function(t){return kt(t,this.value)},Ze=function(t){return this.tags.has(t)},tn=function(t){let e=this.machine.getTransitionData(this,t);return!!(e!=null&&e.length)&&e.some(s=>s.target!==void 0||s.actions.length)},en=function(){let{_nodes:t,tags:e,machine:s,getMeta:i,toJSON:r,can:o,hasTag:a,matches:c,...f}=this;return{...f,tags:Array.from(e)}},nn=function(){return this._nodes.reduce((t,e)=>(e.meta!==void 0&&(t[e.id]=e.meta),t),{})};function K(n,t){return{status:n.status,output:n.output,error:n.error,machine:t,context:n.context,_nodes:n._nodes,value:Ft(t.root,n._nodes),tags:new Set(n._nodes.flatMap(e=>e.tags)),children:n.children,historyValue:n.historyValue||{},matches:Qe,hasTag:Ze,can:tn,getMeta:nn,toJSON:en}}function b(n,t={}){return K({...n,...t},n.machine)}function sn(n){if(typeof n!="object"||n===null)return{};let t={};for(let e in n){let s=n[e];Array.isArray(s)&&(t[e]=s.map(i=>({id:i.id})))}return t}function oe(n,t){let{_nodes:e,tags:s,machine:i,children:r,context:o,can:a,hasTag:c,matches:f,getMeta:p,toJSON:d,...u}=n,l={};for(let y in r){let _=r[y];l[y]={snapshot:_.getPersistedSnapshot(t),src:_.src,systemId:_.systemId,syncSnapshot:_._syncSnapshot}}return{...u,context:ae(o),children:l,historyValue:sn(u.historyValue)}}function ae(n){let t;for(let e in n){let s=n[e];if(s&&typeof s=="object")if("sessionId"in s&&"send"in s&&"ref"in s)t??=Array.isArray(n)?n.slice():{...n},t[e]={xstate$$type:it,id:s.id};else{let i=ae(s);i!==s&&(t??=Array.isArray(n)?n.slice():{...n},t[e]=i)}}return t??n}function rn(n,t,e,s,{event:i,id:r,delay:o},{internalQueue:a}){let c=t.machine.implementations.delays;if(typeof i=="string")throw new Error(`Only event objects may be used with raise; use raise({ type: "${i}" }) instead`);let f=typeof i=="function"?i(e,s):i,p;if(typeof o=="string"){let d=c&&c[o];p=typeof d=="function"?d(e,s):d}else p=typeof o=="function"?o(e,s):o;return typeof p!="number"&&a.push(f),[t,{event:f,id:r,delay:p},void 0]}function on(n,t){let{event:e,delay:s,id:i}=t;if(typeof s=="number"){n.defer(()=>{let r=n.self;n.system.scheduler.schedule(r,r,e,s,i)});return}}function G(n,t){function e(s,i){}return e.type="xstate.raise",e.event=n,e.id=t==null?void 0:t.id,e.delay=t==null?void 0:t.delay,e.resolve=rn,e.execute=on,e}function ce(n,t){return{config:n,transition:(e,s,i)=>({...e,context:n(e.context,s,i)}),getInitialSnapshot:(e,s)=>({status:"active",output:void 0,error:void 0,context:typeof t=="function"?t({input:s}):t}),getPersistedSnapshot:e=>e,restoreSnapshot:e=>e}}var Dn=ce(n=>{},void 0);function an(n,{machine:t,context:e},s,i){let r=(o,a)=>{if(typeof o=="string"){let c=H(t,o);if(!c)throw new Error(`Actor logic '${o}' not implemented in machine '${t.id}'`);let f=v(c,{id:a==null?void 0:a.id,parent:n.self,syncSnapshot:a==null?void 0:a.syncSnapshot,input:typeof(a==null?void 0:a.input)=="function"?a.input({context:e,event:s,self:n.self}):a==null?void 0:a.input,src:o,systemId:a==null?void 0:a.systemId});return i[f.id]=f,f}else return v(o,{id:a==null?void 0:a.id,parent:n.self,syncSnapshot:a==null?void 0:a.syncSnapshot,input:a==null?void 0:a.input,src:o,systemId:a==null?void 0:a.systemId})};return(o,a)=>{let c=r(o,a);return i[c.id]=c,n.defer(()=>{c._processingStatus!==m.Stopped&&c.start()}),c}}function cn(n,t,e,s,{assignment:i}){if(!t.context)throw new Error("Cannot assign to undefined `context`. Ensure that `context` is defined in the machine config.");let r={},o={context:t.context,event:e.event,spawn:an(n,t,e.event,r),self:n.self,system:n.system},a={};if(typeof i=="function")a=i(o,s);else for(let f of Object.keys(i)){let p=i[f];a[f]=typeof p=="function"?p(o,s):p}let c=Object.assign({},t.context,a);return[b(t,{context:c,children:Object.keys(r).length?{...t.children,...r}:t.children}),void 0,void 0]}function g(n){function t(e,s){}return t.type="xstate.assign",t.assignment=n,t.resolve=cn,t}var ue=new WeakMap;function q(n,t,e){let s=ue.get(n);return s?t in s||(s[t]=e()):(s={[t]:e()},ue.set(n,s)),s[t]}var un={},Y=n=>typeof n=="string"?{type:n}:typeof n=="function"?"resolve"in n?{type:n.type}:{type:n.name}:n,ct=class n{constructor(t,e){if(this.config=t,this.key=void 0,this.id=void 0,this.type=void 0,this.path=void 0,this.states=void 0,this.history=void 0,this.entry=void 0,this.exit=void 0,this.parent=void 0,this.machine=void 0,this.meta=void 0,this.output=void 0,this.order=-1,this.description=void 0,this.tags=[],this.transitions=void 0,this.always=void 0,this.parent=e._parent,this.key=e._key,this.machine=e._machine,this.path=this.parent?this.parent.path.concat(this.key):[],this.id=this.config.id||[this.machine.id,...this.path].join(Tt),this.type=this.config.type||(this.config.states&&Object.keys(this.config.states).length?"compound":this.config.history?"history":"atomic"),this.description=this.config.description,this.order=this.machine.idMap.size,this.machine.idMap.set(this.id,this),this.states=this.config.states?bt(this.config.states,(s,i)=>new n(s,{_parent:this,_key:i,_machine:this.machine})):un,this.type==="compound"&&!this.config.initial)throw new Error(`No initial state specified for compound state node "#${this.id}". Try adding { initial: "${Object.keys(this.states)[0]}" } to the state config.`);this.history=this.config.history===!0?"shallow":this.config.history||!1,this.entry=S(this.config.entry).slice(),this.exit=S(this.config.exit).slice(),this.meta=this.config.meta,this.output=this.type==="final"||!this.parent?this.config.output:void 0,this.tags=S(t.tags).slice()}_initialize(){this.transitions=Jt(this),this.config.always&&(this.always=A(this.config.always).map(t=>x(this,St,t))),Object.keys(this.states).forEach(t=>{this.states[t]._initialize()})}get definition(){return{id:this.id,key:this.key,version:this.machine.version,type:this.type,initial:this.initial?{target:this.initial.target,source:this,actions:this.initial.actions.map(Y),eventType:null,reenter:!1,toJSON:()=>({target:this.initial.target.map(t=>`#${t.id}`),source:`#${this.id}`,actions:this.initial.actions.map(Y),eventType:null})}:void 0,history:this.history,states:bt(this.states,t=>t.definition),on:this.on,transitions:[...this.transitions.values()].flat().map(t=>({...t,actions:t.actions.map(Y)})),entry:this.entry.map(Y),exit:this.exit.map(Y),meta:this.meta,order:this.order||-1,output:this.output,invoke:this.invoke,description:this.description,tags:this.tags}}toJSON(){return this.definition}get invoke(){return q(this,"invoke",()=>S(this.config.invoke).map((t,e)=>{let{src:s,systemId:i}=t,r=t.id??At(this.id,e),o=typeof s=="string"?s:`xstate.invoke.${At(this.id,e)}`;return{...t,src:o,id:r,systemId:i,toJSON(){let{onDone:a,onError:c,...f}=t;return{...f,type:"xstate.invoke",src:o,id:r}}}}))}get on(){return q(this,"on",()=>[...this.transitions].flatMap(([e,s])=>s.map(i=>[e,i])).reduce((e,[s,i])=>(e[s]=e[s]||[],e[s].push(i),e),{}))}get after(){return q(this,"delayedTransitions",()=>Yt(this))}get initial(){return q(this,"initial",()=>zt(this,this.config.initial))}next(t,e){let s=e.type,i=[],r,o=q(this,`candidates-${s}`,()=>Kt(this,s));for(let a of o){let{guard:c}=a,f=t.context,p=!1;try{p=!c||N(c,f,e,t)}catch(d){let u=typeof c=="string"?c:typeof c=="object"?c.type:void 0;throw new Error(`Unable to evaluate guard ${u?`'${u}' `:""}in transition for event '${s}' in state node '${this.id}':
3
+ ${d.message}`)}if(p){i.push(...a.actions),r=a;break}}return r?[r]:void 0}get events(){return q(this,"events",()=>{let{states:t}=this,e=new Set(this.ownEvents);if(t)for(let s of Object.keys(t)){let i=t[s];if(i.states)for(let r of i.events)e.add(`${r}`)}return Array.from(e)})}get ownEvents(){let t=Object.keys(Object.fromEntries(this.transitions)),e=new Set(t.filter(s=>this.transitions.get(s).some(i=>!(!i.target&&!i.actions.length&&!i.reenter))));return Array.from(e)}},dn="#",ut=class n{constructor(t,e){this.config=t,this.version=void 0,this.schemas=void 0,this.implementations=void 0,this.__xstatenode=!0,this.idMap=new Map,this.root=void 0,this.id=void 0,this.states=void 0,this.events=void 0,this.id=t.id||"(machine)",this.implementations={actors:(e==null?void 0:e.actors)??{},actions:(e==null?void 0:e.actions)??{},delays:(e==null?void 0:e.delays)??{},guards:(e==null?void 0:e.guards)??{}},this.version=this.config.version,this.schemas=this.config.schemas,this.transition=this.transition.bind(this),this.getInitialSnapshot=this.getInitialSnapshot.bind(this),this.getPersistedSnapshot=this.getPersistedSnapshot.bind(this),this.restoreSnapshot=this.restoreSnapshot.bind(this),this.start=this.start.bind(this),this.root=new ct(t,{_key:this.id,_machine:this}),this.root._initialize(),Xt(this.root),this.states=this.root.states,this.events=this.root.events}provide(t){let{actions:e,guards:s,actors:i,delays:r}=this.implementations;return new n(this.config,{actions:{...e,...t.actions},guards:{...s,...t.guards},actors:{...i,...t.actors},delays:{...r,...t.delays}})}resolveState(t){let e=ie(this.root,t.value),s=j(B(this.root,e));return K({_nodes:[...s],context:t.context||{},children:{},status:ot(s,this.root)?"done":t.status||"active",output:t.output,error:t.error,historyValue:t.historyValue},this)}transition(t,e,s){return F(t,e,s,[]).snapshot}microstep(t,e,s){return F(t,e,s,[]).microsteps.map(([i])=>i)}getTransitionData(t,e){return at(this.root,t.value,t,e)||[]}_getPreInitialState(t,e,s){let{context:i}=this.config,r=K({context:typeof i!="function"&&i?i:{},_nodes:[this.root],children:{},status:"active"},this);return typeof i=="function"?I(r,e,t,[g(({spawn:a,event:c,self:f})=>i({spawn:a,input:c.input,self:f}))],s,void 0):r}getInitialSnapshot(t,e){let s=nt(e),i=[],r=this._getPreInitialState(t,s,i),[o]=It(this.root,r,t,s,i),{snapshot:a}=F(o,s,t,i);return a}start(t){Object.values(t.children).forEach(e=>{e.getSnapshot().status==="active"&&e.start()})}getStateNodeById(t){let e=st(t),s=e.slice(1),i=V(e[0])?e[0].slice(dn.length):e[0],r=this.idMap.get(i);if(!r)throw new Error(`Child state node '#${i}' does not exist on machine '${this.id}'`);return W(r,s)}get definition(){return this.root.definition}toJSON(){return this.definition}getPersistedSnapshot(t,e){return oe(t,e)}restoreSnapshot(t,e){let s={},i=t.children;Object.keys(i).forEach(d=>{let u=i[d],l=u.snapshot,h=u.src,y=typeof h=="string"?H(this,h):h;if(!y)return;let _=v(y,{id:d,parent:e.self,syncSnapshot:u.syncSnapshot,snapshot:l,src:h,systemId:u.systemId});s[d]=_});function r(d,u){if(u instanceof ct)return u;try{return d.machine.getStateNodeById(u.id)}catch{}}function o(d,u){if(!u||typeof u!="object")return{};let l={};for(let h in u){let y=u[h];for(let _ of y){let P=r(d,_);P&&(l[h]??=[],l[h].push(P))}}return l}let a=o(this.root,t.historyValue),c=K({...t,children:s,_nodes:Array.from(j(B(this.root,t.value))),historyValue:a},this),f=new Set;function p(d,u){if(!f.has(d)){f.add(d);for(let l in d){let h=d[l];if(h&&typeof h=="object"){if("xstate$$type"in h&&h.xstate$$type===it){d[l]=u[h.id];continue}p(h,u)}}}}return p(c.context,s),c}};function hn(n,t,e,s,{event:i}){let r=typeof i=="function"?i(e,s):i;return[t,{event:r},void 0]}function ln(n,{event:t}){n.defer(()=>n.emit(t))}function Dt(n){function t(e,s){}return t.type="xstate.emit",t.event=n,t.resolve=hn,t.execute=ln,t}var wt=(function(n){return n.Parent="#_parent",n.Internal="#_internal",n})({});function fn(n,t,e,s,{to:i,event:r,id:o,delay:a},c){var h;let f=t.machine.implementations.delays;if(typeof r=="string")throw new Error(`Only event objects may be used with sendTo; use sendTo({ type: "${r}" }) instead`);let p=typeof r=="function"?r(e,s):r,d;if(typeof a=="string"){let y=f&&f[a];d=typeof y=="function"?y(e,s):y}else d=typeof a=="function"?a(e,s):a;let u=typeof i=="function"?i(e,s):i,l;if(typeof u=="string"){if(u===wt.Parent?l=n.self._parent:u===wt.Internal?l=n.self:u.startsWith("#_")?l=t.children[u.slice(2)]:l=(h=c.deferredActorIds)!=null&&h.includes(u)?u:t.children[u],!l)throw new Error(`Unable to send event to actor '${u}' from machine '${t.machine.id}'.`)}else l=u||n.self;return[t,{to:l,targetId:typeof u=="string"?u:void 0,event:p,id:o,delay:d},void 0]}function pn(n,t,e){typeof e.to=="string"&&(e.to=t.children[e.to])}function gn(n,t){n.defer(()=>{let{to:e,event:s,delay:i,id:r}=t;if(typeof i=="number"){n.system.scheduler.schedule(n.self,e,s,i,r);return}n.system._relay(n.self,e,s.type===Nt?xt(n.self.id,s.data):s)})}function dt(n,t,e){function s(i,r){}return s.type="xstate.sendTo",s.to=n,s.event=t,s.id=e==null?void 0:e.id,s.delay=e==null?void 0:e.delay,s.resolve=fn,s.retryResolve=pn,s.execute=gn,s}function yn(n,t){return dt(wt.Parent,n,t)}function _n(n,t,e,s,{collect:i}){let r=[],o=function(c){r.push(c)};return o.assign=(...a)=>{r.push(g(...a))},o.cancel=(...a)=>{r.push($(...a))},o.raise=(...a)=>{r.push(G(...a))},o.sendTo=(...a)=>{r.push(dt(...a))},o.sendParent=(...a)=>{r.push(yn(...a))},o.spawnChild=(...a)=>{r.push(M(...a))},o.stopChild=(...a)=>{r.push(w(...a))},o.emit=(...a)=>{r.push(Dt(...a))},i({context:e.context,event:e.event,enqueue:o,check:a=>N(a,t.context,e.event,t),self:n.self,system:n.system},s),[t,void 0,r]}function de(n){function t(e,s){}return t.type="xstate.enqueueActions",t.collect=n,t.resolve=_n,t}function mn(n,t,e,s,{value:i,label:r}){return[t,{value:typeof i=="function"?i(e,s):i,label:r},void 0]}function vn({logger:n},{value:t,label:e}){e?n(e,t):n(t)}function he(n=({context:e,event:s})=>({context:e,event:s}),t){function e(s,i){}return e.type="xstate.log",e.value=n,e.label=t,e.resolve=mn,e.execute=vn,e}function Tn(n,t){return new ut(n,t)}function J({schemas:n,actors:t,actions:e,guards:s,delays:i}){return{assign:g,sendTo:dt,raise:G,log:he,cancel:$,stopChild:w,enqueueActions:de,emit:Dt,spawnChild:M,createStateConfig:r=>r,createAction:r=>r,createMachine:r=>Tn({...r,schemas:n},{actors:t,actions:e,guards:s,delays:i}),extend:r=>J({schemas:n,actors:t,actions:{...e,...r.actions},guards:{...s,...r.guards},delays:{...i,...r.delays}})}}var Sn=typeof window<"u",X;function xn(){if(!Sn)return null;let n=window.AudioContext??window.webkitAudioContext;return n?new n:null}function z(){return X===void 0?null:X}function le(){X===void 0&&(X=xn());let n=X;return n&&n.state==="suspended"?n.resume():Promise.resolve()}var ht=typeof navigator<"u"&&"mediaSession"in navigator;function fe(n){if(!ht)return;let{mediaSession:t}=navigator;t.setActionHandler("play",n.onPlay),t.setActionHandler("pause",n.onPause),t.setActionHandler("nexttrack",n.onNext),t.setActionHandler("previoustrack",n.onPrevious),t.setActionHandler("seekto",e=>{e.seekTime!=null&&n.onSeek(e.seekTime)})}function D(n){if(ht){if(!n){navigator.mediaSession.metadata=null;return}navigator.mediaSession.metadata=new MediaMetadata({title:n.title??"",artist:n.artist??"",album:n.album??"",artwork:n.artwork??[]})}}function pe(n){ht&&(navigator.mediaSession.playbackState=n?"playing":"paused")}function ge(n,t,e=1){if(ht)try{navigator.mediaSession.setPositionState({duration:n,position:t,playbackRate:e})}catch{}}function ye(n){return J({types:{context:{},events:{}},guards:{hasNextTrack:({context:t})=>t.currentTrackIndex+1<t.trackCount,playImmediately:({event:t})=>!!t.playImmediately}}).createMachine({id:"queue",initial:"idle",context:n,on:{ADD_TRACK:{actions:g({trackCount:({context:t})=>t.trackCount+1})},REMOVE_TRACK:{actions:g({trackCount:({context:t})=>Math.max(0,t.trackCount-1),currentTrackIndex:({context:t,event:e})=>e.index<t.currentTrackIndex?Math.max(0,t.currentTrackIndex-1):t.currentTrackIndex})}},states:{idle:{on:{PLAY:{target:"playing"},GOTO:[{guard:"playImmediately",target:"playing",actions:g({currentTrackIndex:({event:t})=>t.index})},{target:"paused",actions:g({currentTrackIndex:({event:t})=>t.index})}]}},playing:{on:{PAUSE:{target:"paused"},TOGGLE:{target:"paused"},NEXT:{actions:g({currentTrackIndex:({context:t})=>{let e=t.currentTrackIndex+1;return e<t.trackCount?e:t.currentTrackIndex}})},PREVIOUS:{actions:g({currentTrackIndex:({context:t})=>Math.max(0,t.currentTrackIndex-1)})},GOTO:{actions:g({currentTrackIndex:({event:t})=>t.index})},SEEK:{},TRACK_ENDED:[{guard:"hasNextTrack",target:"playing",actions:g({currentTrackIndex:({context:t})=>t.currentTrackIndex+1})},{target:"ended"}],TRACK_LOADED:{}}},paused:{on:{PLAY:{target:"playing"},TOGGLE:{target:"playing"},NEXT:{actions:g({currentTrackIndex:({context:t})=>{let e=t.currentTrackIndex+1;return e<t.trackCount?e:t.currentTrackIndex}})},PREVIOUS:{actions:g({currentTrackIndex:({context:t})=>Math.max(0,t.currentTrackIndex-1)})},GOTO:[{guard:"playImmediately",target:"playing",actions:g({currentTrackIndex:({event:t})=>t.index})},{actions:g({currentTrackIndex:({event:t})=>t.index})}],SEEK:{},TRACK_ENDED:[{guard:"hasNextTrack",target:"paused",actions:g({currentTrackIndex:({context:t})=>t.currentTrackIndex+1})},{target:"ended"}]}},ended:{on:{PLAY:{target:"playing",actions:g({currentTrackIndex:()=>0})},GOTO:[{guard:"playImmediately",target:"playing",actions:g({currentTrackIndex:({event:t})=>t.index})},{target:"paused",actions:g({currentTrackIndex:({event:t})=>t.index})}]}}}})}function _e(n){return J({types:{context:{},events:{}}}).createMachine({id:"track",initial:"idle",context:n,states:{idle:{on:{HTML5_ENDED:{},PLAY:{target:"html5",actions:g({isPlaying:()=>!0})},PLAY_WEBAUDIO:{target:"webaudio",actions:g({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO"})},PRELOAD:{target:"loading"},BUFFER_LOADING:{actions:g({webAudioLoadingState:()=>"LOADING"})},URL_RESOLVED:{actions:g({resolvedUrl:({event:t})=>t.url})}}},html5:{on:{PAUSE:{actions:g({isPlaying:()=>!1})},PLAY:{actions:g({isPlaying:()=>!0})},BUFFER_LOADING:{actions:g({webAudioLoadingState:()=>"LOADING"})},PLAY_WEBAUDIO:{target:"webaudio",actions:g({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO"})},BUFFER_READY:{actions:g({webAudioLoadingState:()=>"LOADED"})},BUFFER_ERROR:{actions:g({webAudioLoadingState:()=>"ERROR"})},SEEK:{actions:g({pausedAtTrackTime:({event:t})=>t.time})},HTML5_ENDED:{target:"idle",actions:g({isPlaying:()=>!1})},URL_RESOLVED:{actions:g({resolvedUrl:({event:t})=>t.url})},DEACTIVATE:{target:"loading",actions:g({isPlaying:()=>!1})}}},loading:{on:{BUFFER_LOADING:{actions:g({webAudioLoadingState:()=>"LOADING"})},BUFFER_READY:{target:"idle",actions:g({webAudioLoadingState:()=>"LOADED"})},BUFFER_ERROR:{target:"idle",actions:g({webAudioLoadingState:()=>"ERROR"})},PLAY:{target:"html5",actions:g({isPlaying:()=>!0})},PLAY_WEBAUDIO:{target:"webaudio",actions:g({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO"})},URL_RESOLVED:{actions:g({resolvedUrl:({event:t})=>t.url})}}},webaudio:{on:{PAUSE:{actions:g({isPlaying:()=>!1})},PLAY:{actions:g({isPlaying:()=>!0})},PLAY_WEBAUDIO:{actions:g({isPlaying:()=>!0,playbackType:()=>"WEBAUDIO"})},SEEK:{actions:g({pausedAtTrackTime:({event:t})=>t.time})},SET_VOLUME:{},WEBAUDIO_ENDED:{target:"idle",actions:g({isPlaying:()=>!1})},DEACTIVATE:{target:"idle",actions:g({isPlaying:()=>!1})}}}}})}var kn=5,Q=class{index;metadata;_trackUrl;_resolvedUrl;skipHEAD;loadedHEAD=!1;abortController=null;audio;_webAudioDisabled;get ctx(){if(this._webAudioDisabled)return null;let t=z();return t&&!this.gainNode&&(this.gainNode=t.createGain(),this.gainNode.gain.value=this.audio.volume),t}gainNode=null;sourceNode=null;audioBuffer=null;webAudioStartedAt=0;pausedAtTrackTime=0;scheduledStartContextTime=null;_actor;queueRef;rafId=null;_notifiedLookahead=!1;constructor(t){this.index=t.index,this._trackUrl=t.trackUrl,this._resolvedUrl=t.trackUrl,this.skipHEAD=t.skipHEAD??!1,this.metadata=t.metadata??{},this.queueRef=t.queue,this.audio=new Audio,this.audio.preload="none",this.audio.src=this._trackUrl,this.audio.volume=t.queue.volume,this.audio.controls=!1,this.audio.onerror=()=>{var r,o;let s=(r=this.audio.error)==null?void 0:r.code;if(s===1)return;let i=((o=this.audio.error)==null?void 0:o.message)??"unknown";this.queueRef.onError(new Error(`HTML5 audio error on track ${this.index} (code ${s}): ${i}`))},this.audio.onended=()=>{let s=this._actor.getSnapshot().value;this.queueRef.onDebug(`audio.onended track=${this.index} machineState=${s} queueIdx=${this.queueRef.currentTrackIndex}`),(s==="html5"||s==="idle")&&(this._actor.send({type:"HTML5_ENDED"}),this.queueRef.onTrackEnded(this))},this._webAudioDisabled=t.queue.webAudioIsDisabled;let e={trackUrl:this._trackUrl,resolvedUrl:this._trackUrl,skipHEAD:this.skipHEAD,playbackType:"HTML5",webAudioLoadingState:"NONE",webAudioStartedAt:0,pausedAtTrackTime:0,isPlaying:!1};this._actor=v(_e(e)),this._actor.start()}play(){let t=this._actor.getSnapshot().value,e=!1;this.queueRef.onDebug(`Track.play() track=${this.index} machineState=${t} hasBuffer=${!!this.audioBuffer} hasCtx=${!!this.ctx} audioPaused=${this.audio.paused}`),t==="webaudio"?e=this._playWebAudio():this.audioBuffer&&this.ctx&&(t==="loading"||t==="idle")&&(e=this._playWebAudio()),e||t==="html5"&&!this.audio.paused||this._playHtml5(),this._actor.send({type:e?"PLAY_WEBAUDIO":"PLAY"}),this.startProgressLoop()}pause(){this._actor.getSnapshot().value==="webaudio"?(this.pausedAtTrackTime=this.currentTime,this._stopSourceNode(),this._disconnectGain()):this.audio.pause(),this._actor.send({type:"PAUSE"}),this._stopProgressLoop(),this.queueRef.onProgress(this.toInfo())}seek(t){let e=Math.max(0,isNaN(this.duration)?t:Math.min(t,this.duration));if(this.pausedAtTrackTime=e,this._actor.getSnapshot().value==="webaudio"){let i=this._actor.getSnapshot().context.isPlaying;this._stopSourceNode(),this.scheduledStartContextTime=null,i&&this._startSourceNode(e)}else this.audio.preload!=="auto"&&(this.audio.preload="auto"),this.audio.readyState>=HTMLMediaElement.HAVE_METADATA?this.audio.currentTime=e:(this.audio.addEventListener("loadedmetadata",()=>{this.audio.currentTime=e},{once:!0}),this.audio.load());this._actor.send({type:"SEEK",time:e}),this.queueRef.onProgress(this.toInfo())}setVolume(t){let e=Math.min(1,Math.max(0,t));this.audio.volume=e,this.gainNode&&(this.gainNode.gain.value=e),this._actor.send({type:"SET_VOLUME",volume:e})}preload(){this.queueRef.onDebug(`preload() track=${this.index} state=${this._actor.getSnapshot().value} hasBuffer=${!!this.audioBuffer} hasCtx=${!!this.ctx}`),this._actor.getSnapshot().value==="idle"&&this._actor.send({type:"PRELOAD"}),!(this.audioBuffer||!this.ctx)&&this._startLoad()}seekToEnd(t=6){let e=this.duration;!isNaN(e)&&e>t&&this.seek(e-t)}activate(){this._actor.getSnapshot().value==="webaudio"&&(this._stopSourceNode(),this._disconnectGain(),this.scheduledStartContextTime=null,this._stopProgressLoop(),this._actor.send({type:"DEACTIVATE"})),this.webAudioStartedAt=0,this.pausedAtTrackTime=0,this._notifiedLookahead=!1,(this.audio.ended||this.audio.currentTime>0)&&(this.audio.currentTime=0)}deactivate(){this.queueRef.onDebug(`Track.deactivate() track=${this.index} machineState=${this._actor.getSnapshot().value} isPlaying=${this.isPlaying}`),this._stopSourceNode(),this._disconnectGain(),this.webAudioStartedAt=0,this.pausedAtTrackTime=0,this.scheduledStartContextTime=null,this.audio.pause(),this.audio.currentTime=0,this._stopProgressLoop(),this._actor.send({type:"DEACTIVATE"}),this.queueRef.onDebug(`Track.deactivate() done track=${this.index} machineState=${this._actor.getSnapshot().value}`)}destroy(){var t,e;this.deactivate(),(t=this.abortController)==null||t.abort(),this.audioBuffer=null,(e=this.gainNode)==null||e.disconnect(),this.gainNode=null,this._actor.stop()}cancelGaplessStart(){this.scheduledStartContextTime!==null&&(this._stopSourceNode(),this._disconnectGain(),this.scheduledStartContextTime=null,this.webAudioStartedAt=0,this.pausedAtTrackTime=0,this._stopProgressLoop(),this._actor.send({type:"DEACTIVATE"}))}scheduleGaplessStart(t){!this.ctx||!this.audioBuffer||!this.gainNode||(this.scheduledStartContextTime=t,this._stopSourceNode(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.connect(this.gainNode),this.gainNode.connect(this.ctx.destination),this.sourceNode.onended=this._handleWebAudioEnded,this.sourceNode.start(t,0),this.webAudioStartedAt=t,this._actor.send({type:"PLAY_WEBAUDIO"}),this.queueRef.onDebug(`scheduleGaplessStart track=${this.index} when=${t.toFixed(3)} ctxNow=${this.ctx.currentTime.toFixed(3)} delta=${(t-this.ctx.currentTime).toFixed(3)}s ctxState=${this.ctx.state}`))}get currentTime(){return this._isUsingWebAudio?this._actor.getSnapshot().context.isPlaying?this.ctx?Math.max(0,this.ctx.currentTime-this.webAudioStartedAt):0:this.pausedAtTrackTime:this.audio.currentTime}get duration(){return this.audioBuffer?this.audioBuffer.duration:this.audio.duration}get isPaused(){return this._isUsingWebAudio?!this._actor.getSnapshot().context.isPlaying:this.audio.paused}get isPlaying(){return this._actor.getSnapshot().context.isPlaying}get trackUrl(){return this._resolvedUrl}get playbackType(){return this._actor.getSnapshot().context.playbackType}get webAudioLoadingState(){return this._actor.getSnapshot().context.webAudioLoadingState}get hasSourceNode(){return this.sourceNode!==null}get machineState(){return this._actor.getSnapshot().value}get isBufferLoaded(){return this.audioBuffer!==null}toInfo(){var t;return{index:this.index,currentTime:this.currentTime,duration:this.duration,isPlaying:this.isPlaying,isPaused:this.isPaused,volume:((t=this.gainNode)==null?void 0:t.gain.value)??this.audio.volume,trackUrl:this.trackUrl,playbackType:this.playbackType,webAudioLoadingState:this.webAudioLoadingState,metadata:this.metadata,machineState:this.machineState}}_playHtml5(){this.audio.preload!=="auto"&&(this.audio.preload="auto");let t=this.audio.play();t&&t.catch(e=>{e instanceof Error&&e.name==="NotAllowedError"?this.queueRef.onPlayBlocked():e instanceof Error&&e.name==="AbortError"||this.queueRef.onError(e instanceof Error?e:new Error(String(e)))})}get _isUsingWebAudio(){return this._actor.getSnapshot().value==="webaudio"}_playWebAudio(){if(!this.ctx||!this.audioBuffer||!this.gainNode)return this.queueRef.onDebug(`_playWebAudio BAIL track=${this.index} ctx=${!!this.ctx} buf=${!!this.audioBuffer} gain=${!!this.gainNode}`),!1;let e=this._actor.getSnapshot().context.isPlaying?0:this.pausedAtTrackTime;return this._startSourceNode(e),!0}_startSourceNode(t){!this.ctx||!this.audioBuffer||!this.gainNode||(this._stopSourceNode(),this.ctx.state==="suspended"&&this.ctx.resume(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.connect(this.gainNode),this.gainNode.connect(this.ctx.destination),this.sourceNode.onended=this._handleWebAudioEnded,this.webAudioStartedAt=this.ctx.currentTime-t,this.sourceNode.start(0,t))}_stopSourceNode(){if(this.sourceNode){this.sourceNode.onended=null;try{this.sourceNode.stop()}catch{}try{this.sourceNode.disconnect()}catch{}this.sourceNode=null}}_disconnectGain(){if(!(!this.gainNode||!this.ctx))try{this.gainNode.disconnect(this.ctx.destination)}catch{}}_handleWebAudioEnded=()=>{this.queueRef.onDebug(`_handleWebAudioEnded track=${this.index} sourceNode=${!!this.sourceNode} queueIdx=${this.queueRef.currentTrackIndex}`),this.sourceNode&&(this._actor.send({type:"WEBAUDIO_ENDED"}),this._stopProgressLoop(),this.queueRef.onTrackEnded(this))};_startLoad(){let t=this._actor.getSnapshot();if(!this.ctx||this.audioBuffer||t.context.webAudioLoadingState!=="NONE"){this.queueRef.onDebug(`_startLoad() SKIPPED track=${this.index} hasCtx=${!!this.ctx} hasBuffer=${!!this.audioBuffer} loadingState=${t.context.webAudioLoadingState}`);return}this.queueRef.onDebug(`_startLoad() STARTING track=${this.index} url=${this._resolvedUrl.slice(0,60)}`),this._actor.send({type:"BUFFER_LOADING"}),this.abortController=new AbortController;let e=s=>{fetch(s,{signal:this.abortController.signal}).then(i=>{if(!i.ok)throw new Error(`HTTP ${i.status} for ${s}`);return i.arrayBuffer()}).then(i=>this.ctx.decodeAudioData(i)).then(i=>{this.audioBuffer=i,this._actor.send({type:"BUFFER_READY"}),this.queueRef.onTrackBufferReady(this)}).catch(i=>{i instanceof Error&&i.name==="AbortError"||(console.error(`gapless.js: decode failed for track ${this.index}`,i),this._actor.send({type:"BUFFER_ERROR"}))})};this.skipHEAD||this.loadedHEAD?e(this._resolvedUrl):fetch(this._trackUrl,{method:"HEAD",signal:this.abortController.signal}).then(s=>{s.redirected&&s.url&&(this._resolvedUrl=s.url,this.audio.src=s.url,this._actor.send({type:"URL_RESOLVED",url:s.url})),this.loadedHEAD=!0,e(this._resolvedUrl)}).catch(s=>{s instanceof Error&&s.name==="AbortError"||(this.loadedHEAD=!0,e(this._trackUrl))})}startProgressLoop(){if(this.rafId!==null)return;let t=()=>{if(this.isPaused||!this.isPlaying){this.rafId=null;return}this.queueRef.onProgress(this.toInfo());let e=this.duration-this.currentTime;!this._notifiedLookahead&&!isNaN(e)&&e<=kn&&(this._notifiedLookahead=!0,this.queueRef.onTrackBufferReady(this)),this.rafId=requestAnimationFrame(t)};this.rafId=requestAnimationFrame(t)}_stopProgressLoop(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}};function me(n,t){let e=0;return(...s)=>{let i=performance.now();i-e<t||(e=i,n(...s))}}var bn=2,lt=class{_tracks=[];_actor;_onProgress;_onEnded;_onPlayNextTrack;_onPlayPreviousTrack;_onStartNewTrack;_onError;_onPlayBlocked;_onDebug;webAudioIsDisabled;_volume;_scheduledIndices=new Set;_throttledUpdatePositionState=me((t,e)=>ge(t,e),1e3);constructor(t={}){let{tracks:e=[],onProgress:s,onEnded:i,onPlayNextTrack:r,onPlayPreviousTrack:o,onStartNewTrack:a,onError:c,onPlayBlocked:f,onDebug:p,webAudioIsDisabled:d=!1,trackMetadata:u=[],volume:l=1}=t;this._volume=Math.min(1,Math.max(0,l)),this.webAudioIsDisabled=d,this._onProgress=s,this._onEnded=i,this._onPlayNextTrack=r,this._onPlayPreviousTrack=o,this._onStartNewTrack=a,this._onError=c,this._onPlayBlocked=f,this._onDebug=p,this._tracks=e.map((h,y)=>new Q({trackUrl:h,index:y,queue:this,metadata:u[y]})),this._actor=v(ye({currentTrackIndex:0,trackCount:this._tracks.length})),this._actor.subscribe(h=>{pe(h.value==="playing")}),this._actor.start(),fe({onPlay:()=>this.play(),onPause:()=>{this._actor.getSnapshot().value==="playing"&&this.pause()},onNext:()=>this.next(),onPrevious:()=>this.previous(),onSeek:h=>this.seek(h)})}play(){let t=this._currentTrack;t&&(t.play(),this._actor.send({type:"PLAY"}),D(t.metadata),this._preloadAhead(t.index),this._tryScheduleGapless(t))}pause(){var t;this._actor.send({type:"PAUSE"}),this._cancelScheduledGapless(),(t=this._currentTrack)==null||t.pause()}togglePlayPause(){this._actor.getSnapshot().value==="playing"?this.pause():this.play()}next(){var i,r;if(this._actor.getSnapshot().context.currentTrackIndex+1>=this._tracks.length)return;this._deactivateCurrent(),this._cancelAllScheduledGapless(),this._actor.send({type:"NEXT"}),this._activateCurrent(!0);let s=this._currentTrack;s&&((i=this._onStartNewTrack)==null||i.call(this,s.toInfo()),(r=this._onPlayNextTrack)==null||r.call(this,s.toInfo()),D(s.metadata)),this._preloadAhead(this._actor.getSnapshot().context.currentTrackIndex)}previous(){var s,i;let t=this._currentTrack;if(t&&t.currentTime>8){t.seek(0),t.play();return}this._deactivateCurrent(),this._cancelAllScheduledGapless(),this._actor.send({type:"PREVIOUS"}),this._activateCurrent(!0);let e=this._currentTrack;e&&((s=this._onStartNewTrack)==null||s.call(this,e.toInfo()),(i=this._onPlayPreviousTrack)==null||i.call(this,e.toInfo()),D(e.metadata))}gotoTrack(t,e=!1){var r,o;if(t<0||t>=this._tracks.length)return;let s=this._actor.getSnapshot();this.onDebug(`gotoTrack(${t}, playImmediately=${e}) queueState=${s.value} curIdx=${s.context.currentTrackIndex}`),this._deactivateCurrent(),this._cancelAllScheduledGapless(),this._actor.send({type:"GOTO",index:t,playImmediately:e});let i=this._actor.getSnapshot();if(this.onDebug(`gotoTrack after GOTO \u2192 queueState=${i.value} curIdx=${i.context.currentTrackIndex}`),e){this._activateCurrent(!0);let a=this._currentTrack;a&&(this.onDebug(`gotoTrack activateCurrent done, track=${a.index} trackState=${a.playbackType} isPlaying=${a.isPlaying}`),(r=this._onStartNewTrack)==null||r.call(this,a.toInfo()),D(a.metadata)),this._preloadAhead(t)}else(o=this._currentTrack)==null||o.seek(0)}seek(t){var e;(e=this._currentTrack)==null||e.seek(t),this._cancelAndRescheduleGapless()}setVolume(t){let e=Math.min(1,Math.max(0,t));this._volume=e;for(let s of this._tracks)s.setVolume(e)}addTrack(t,e={}){let s=this._tracks.length,i=e.metadata??{};this._tracks.push(new Q({trackUrl:t,index:s,queue:this,skipHEAD:e.skipHEAD,metadata:i})),this._actor.send({type:"ADD_TRACK"})}removeTrack(t){if(!(t<0||t>=this._tracks.length)){this._tracks[t].destroy(),this._tracks.splice(t,1);for(let e=t;e<this._tracks.length;e++)this._tracks[e].index=e;this._scheduledIndices.delete(t),this._actor.send({type:"REMOVE_TRACK",index:t})}}resumeAudioContext(){return le()}destroy(){for(let t of this._tracks)t.destroy();this._tracks=[],this._actor.stop()}get currentTrack(){var t;return(t=this._currentTrack)==null?void 0:t.toInfo()}get currentTrackIndex(){return this._actor.getSnapshot().context.currentTrackIndex}get tracks(){return this._tracks.map(t=>t.toInfo())}get isPlaying(){return this._actor.getSnapshot().value==="playing"}get isPaused(){return this._actor.getSnapshot().value==="paused"}get volume(){return this._volume}get queueSnapshot(){let t=this._actor.getSnapshot();return{state:t.value,context:t.context}}onTrackEnded(t){var i,r,o,a;let e=this._actor.getSnapshot();if(this.onDebug(`onTrackEnded track=${t.index} queueState=${e.value} curIdx=${e.context.currentTrackIndex}`),t.index!==e.context.currentTrackIndex)return;t.deactivate(),this._actor.send({type:"TRACK_ENDED"});let s=this._actor.getSnapshot();if(this.onDebug(`onTrackEnded after TRACK_ENDED \u2192 queueState=${s.value} curIdx=${s.context.currentTrackIndex}`),s.value==="ended"){(i=this._onEnded)==null||i.call(this);return}if(s.value==="playing"){let c=this._currentTrack;c&&(this._scheduledIndices.has(c.index)?(this.onDebug(`onTrackEnded: gapless track ${c.index} \u2014 sourceNode=${c.hasSourceNode} isPlaying=${c.isPlaying} machineState=${c.machineState}`),c.startProgressLoop()):c.play(),(r=this._onStartNewTrack)==null||r.call(this,c.toInfo()),(o=this._onPlayNextTrack)==null||o.call(this,c.toInfo()),D(c.metadata),this._preloadAhead(c.index))}if(s.value==="paused"){let c=this._currentTrack;c&&((a=this._onStartNewTrack)==null||a.call(this,c.toInfo()),D(c.metadata))}}onTrackBufferReady(t){this._actor.send({type:"TRACK_LOADED",index:t.index}),this._tryScheduleGapless(t),this._preloadAhead(this._actor.getSnapshot().context.currentTrackIndex)}onProgress(t){var e;t.index===this._actor.getSnapshot().context.currentTrackIndex&&(isNaN(t.duration)||this._throttledUpdatePositionState(t.duration,t.currentTime),(e=this._onProgress)==null||e.call(this,t))}onError(t){var e;(e=this._onError)==null||e.call(this,t)}onPlayBlocked(){var t;(t=this._onPlayBlocked)==null||t.call(this)}onDebug(t){var e;(e=this._onDebug)==null||e.call(this,t)}get _currentTrack(){return this._tracks[this._actor.getSnapshot().context.currentTrackIndex]}_deactivateCurrent(){var t;(t=this._currentTrack)==null||t.deactivate()}_activateCurrent(t){let e=this._currentTrack;e&&(e.activate(),t&&!this._scheduledIndices.has(e.index)&&e.play())}_preloadAhead(t){let e=t+bn+1;this.onDebug(`_preloadAhead(${t}) limit=${e} trackCount=${this._tracks.length}`);for(let s=t+1;s<this._tracks.length&&s<e;s++){let i=this._tracks[s];if(i.isBufferLoaded)this.onDebug(`_preloadAhead: track ${s} already loaded`);else{this.onDebug(`_preloadAhead: starting preload for track ${s}`),i.preload();break}}}_cancelScheduledGapless(){let e=this._actor.getSnapshot().context.currentTrackIndex+1;e<this._tracks.length&&this._scheduledIndices.has(e)&&(this._tracks[e].cancelGaplessStart(),this._scheduledIndices.delete(e),this.onDebug(`_cancelScheduledGapless: cancelled track ${e}`))}_cancelAllScheduledGapless(){var t;for(let e of this._scheduledIndices)(t=this._tracks[e])==null||t.cancelGaplessStart();this._scheduledIndices.clear()}_cancelAndRescheduleGapless(){this._cancelScheduledGapless();let t=this._currentTrack;t&&this._tryScheduleGapless(t)}_tryScheduleGapless(t){let e=z();if(!e||this.webAudioIsDisabled)return;let i=this._actor.getSnapshot().context.currentTrackIndex,r=i+1;if(r>=this._tracks.length)return;let o=this._tracks[i],a=this._tracks[r];if(!o.isBufferLoaded||!a.isBufferLoaded||this._scheduledIndices.has(r)||!o.isPlaying)return;let c=this._computeTrackEndTime(o);c!==null&&(c<e.currentTime+.01||(a.scheduleGaplessStart(c),this._scheduledIndices.add(r)))}_computeTrackEndTime(t){let e=z();if(!e||!t.isBufferLoaded)return null;let s=t.duration;if(isNaN(s))return null;if(t.scheduledStartContextTime!==null)return t.scheduledStartContextTime+s;let i=s-t.currentTime;return i<=0?null:e.currentTime+i}};export{lt as Queue,lt as default};
2
4
  //# sourceMappingURL=index.mjs.map