gapless 4.2.3 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -13
- package/src/Queue.ts +86 -4
- package/src/Track.ts +119 -61
- package/src/machines/track.machine.ts +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -171,8 +171,14 @@ declare class Track {
|
|
|
171
171
|
activate(): void;
|
|
172
172
|
deactivate(): void;
|
|
173
173
|
destroy(): void;
|
|
174
|
+
/** Schedule the HTML5 gain node to mute at `when` — safety valve so an
|
|
175
|
+
* HTML5 element that runs past the predicted end is silenced instead of
|
|
176
|
+
* overlapping the next track. No-op if the HTML5 gain path isn't active. */
|
|
177
|
+
scheduleHtml5Mute(when: number): void;
|
|
178
|
+
/** Cancel any scheduled HTML5 gain mute (called when gapless is cancelled). */
|
|
179
|
+
cancelHtml5Mute(): void;
|
|
174
180
|
cancelGaplessStart(): void;
|
|
175
|
-
scheduleGaplessStart(when: number):
|
|
181
|
+
scheduleGaplessStart(when: number): boolean;
|
|
176
182
|
get currentTime(): number;
|
|
177
183
|
get duration(): number;
|
|
178
184
|
get isPaused(): boolean;
|
|
@@ -255,6 +261,8 @@ declare class Queue implements TrackQueueRef {
|
|
|
255
261
|
private _volume;
|
|
256
262
|
private _preloadNumTracks;
|
|
257
263
|
private _playbackRate;
|
|
264
|
+
/** Silent looping element that keeps the browser's MediaSession anchor alive. */
|
|
265
|
+
private _mediaSessionAnchor;
|
|
258
266
|
/** Index of the next track with a pre-scheduled gapless start, or null. */
|
|
259
267
|
private _scheduledNextIndex;
|
|
260
268
|
private _throttledUpdatePositionState;
|
|
@@ -303,6 +311,8 @@ declare class Queue implements TrackQueueRef {
|
|
|
303
311
|
private _cancelScheduledGapless;
|
|
304
312
|
private _tryScheduleGapless;
|
|
305
313
|
private _computeTrackEndTime;
|
|
314
|
+
private _startMediaSessionAnchor;
|
|
315
|
+
private _stopMediaSessionAnchor;
|
|
306
316
|
}
|
|
307
317
|
|
|
308
318
|
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,2 @@
|
|
|
1
|
-
import{createActor as j}from"xstate";var q=typeof window<"u",p;function V(){if(!q)return null;let o=window.AudioContext??window.webkitAudioContext;return o?new o:null}function k(){return p===void 0?null:p}function f(){p===void 0&&(p=V());let o=p;return o&&o.state==="suspended"?o.resume():Promise.resolve()}var g=typeof navigator<"u"&&"mediaSession"in navigator;function P(o){if(!g)return;let{mediaSession:e}=navigator;e.setActionHandler("play",o.onPlay),e.setActionHandler("pause",o.onPause),e.setActionHandler("nexttrack",o.onNext),e.setActionHandler("previoustrack",o.onPrevious),e.setActionHandler("seekto",t=>{t.seekTime!=null&&o.onSeek(t.seekTime)})}function b(o){if(g){if(!o){navigator.mediaSession.metadata=null;return}navigator.mediaSession.metadata=new MediaMetadata({title:o.title??"",artist:o.artist??"",album:o.album??"",artwork:o.artwork??[]})}}function N(o){g&&(navigator.mediaSession.playbackState=o?"playing":"paused")}function R(o,e,t=1){if(g)try{navigator.mediaSession.setPositionState({duration:o,position:e,playbackRate:t})}catch{}}import{setup as K,assign as h}from"xstate";function C(o){return K({types:{context:{},events:{}},guards:{hasNextTrack:({context:e})=>e.currentTrackIndex+1<e.trackCount,playImmediately:({event:e})=>!!e.playImmediately,willBeEmpty:({context:e})=>e.trackCount<=1,isRemovingCurrent:({context:e,event:t})=>t.index===e.currentTrackIndex},actions:{incrementTrackCount:h({trackCount:({context:e})=>e.trackCount+1}),decrementTrackCount:h({trackCount:({context:e})=>Math.max(0,e.trackCount-1),currentTrackIndex:({context:e,event:t})=>{let r=t,a=Math.max(0,e.trackCount-1);return r.index<e.currentTrackIndex?Math.max(0,e.currentTrackIndex-1):a>0?Math.min(e.currentTrackIndex,a-1):0}}),gotoTrackIndex:h({currentTrackIndex:({event:e})=>e.index}),advanceToNextTrack:h({currentTrackIndex:({context:e})=>{let t=e.currentTrackIndex+1;return t<e.trackCount?t:e.currentTrackIndex}}),goToPreviousTrack:h({currentTrackIndex:({context:e})=>Math.max(0,e.currentTrackIndex-1)}),advanceOnTrackEnd:h({currentTrackIndex:({context:e})=>Math.min(e.currentTrackIndex+1,e.trackCount-1)}),resetToFirstTrack:h({currentTrackIndex:()=>0}),deactivateCurrent:()=>{},deactivateEndedTrack:()=>{},activateAndPlayCurrent:()=>{},playOrContinueGapless:()=>{},cancelAllGapless:()=>{},notifyStartNewTrack:()=>{},notifyPlayNextTrack:()=>{},notifyPlayPreviousTrack:()=>{},notifyEnded:()=>{},updateMediaSessionMetadata:()=>{},preloadAhead:()=>{},playCurrent:()=>{},pauseCurrent:()=>{},seekCurrent:()=>{},seekCurrentToZero:()=>{},scheduleGapless:()=>{},cancelScheduledGapless:()=>{},cancelAndRescheduleGapless:()=>{}}}).createMachine({id:"queue",initial:"idle",context:o,on:{ADD_TRACK:{actions:"incrementTrackCount"},REMOVE_TRACK:{actions:"decrementTrackCount"}},states:{idle:{on:{PLAY:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"paused",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],TRACK_LOADED:{actions:["preloadAhead"]}}},playing:{on:{REMOVE_TRACK:[{guard:"willBeEmpty",target:"idle",actions:["cancelAllGapless","decrementTrackCount"]},{guard:"isRemovingCurrent",actions:["cancelAllGapless","decrementTrackCount","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["decrementTrackCount","cancelAndRescheduleGapless","preloadAhead"]}],PAUSE:{target:"paused",actions:["cancelScheduledGapless","pauseCurrent"]},TOGGLE:{target:"paused",actions:["cancelScheduledGapless","pauseCurrent"]},NEXT:{actions:["deactivateCurrent","cancelAllGapless","advanceToNextTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},PREVIOUS:{actions:["deactivateCurrent","cancelAllGapless","goToPreviousTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayPreviousTrack","updateMediaSessionMetadata","preloadAhead"]},GOTO:[{guard:"playImmediately",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],SEEK:{actions:["seekCurrent","cancelAndRescheduleGapless"]},TRACK_ENDED:[{guard:"hasNextTrack",target:"playing",actions:["deactivateEndedTrack","advanceOnTrackEnd","playOrContinueGapless","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"ended",actions:["deactivateEndedTrack","notifyEnded"]}],TRACK_LOADED:[{guard:({context:e,event:t})=>t.index===e.currentTrackIndex,actions:["cancelAndRescheduleGapless","preloadAhead"]},{actions:["scheduleGapless","preloadAhead"]}]}},paused:{on:{REMOVE_TRACK:[{guard:"willBeEmpty",target:"idle",actions:["cancelAllGapless","decrementTrackCount"]},{guard:"isRemovingCurrent",actions:["cancelAllGapless","decrementTrackCount","preloadAhead"]},{actions:["decrementTrackCount","preloadAhead"]}],PLAY:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},TOGGLE:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},NEXT:{actions:["deactivateCurrent","cancelAllGapless","advanceToNextTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},PREVIOUS:{actions:["deactivateCurrent","cancelAllGapless","goToPreviousTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayPreviousTrack","updateMediaSessionMetadata","preloadAhead"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],SEEK:{actions:["seekCurrent"]},TRACK_ENDED:[{guard:"hasNextTrack",target:"paused",actions:["deactivateEndedTrack","advanceOnTrackEnd","notifyStartNewTrack","updateMediaSessionMetadata"]},{target:"ended",actions:["deactivateEndedTrack","notifyEnded"]}],TRACK_LOADED:{actions:["preloadAhead"]}}},ended:{on:{ADD_TRACK:{target:"paused",actions:"incrementTrackCount"},PLAY:{target:"playing",actions:["resetToFirstTrack","playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"paused",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}]}}}})}import{createActor as X,fromPromise as x}from"xstate";import{setup as Q,assign as c,spawnChild as Z}from"xstate";import{setup as Y,assign as E,sendParent as T,fromPromise as S}from"xstate";var m=Y({types:{context:{},input:{}},actors:{resolveUrl:S(async()=>null),fetchAudio:S(async()=>{}),decodeAudio:S(async()=>{})},guards:{shouldSkipHEAD:({context:o})=>o.skipHEAD}}).createMachine({id:"fetchDecode",initial:"resolvingUrl",context:{trackUrl:"",resolvedUrl:"",skipHEAD:!1},entry:E(({event:o})=>{let{input:e}=o;return{trackUrl:e.trackUrl,resolvedUrl:e.resolvedUrl,skipHEAD:e.skipHEAD}}),states:{resolvingUrl:{always:{guard:"shouldSkipHEAD",target:"fetching"},invoke:{id:"resolveUrl",src:"resolveUrl",input:({context:o})=>({trackUrl:o.trackUrl}),onDone:{target:"fetching",actions:[E({resolvedUrl:({event:o,context:e})=>o.output??e.resolvedUrl,skipHEAD:()=>!0}),T(({event:o,context:e})=>({type:"URL_RESOLVED",url:o.output??e.resolvedUrl}))]},onError:{target:"fetching",actions:E({skipHEAD:()=>!0})}}},fetching:{invoke:{id:"fetchAudio",src:"fetchAudio",input:({context:o})=>({resolvedUrl:o.resolvedUrl}),onDone:"decoding",onError:{target:"error",actions:T({type:"BUFFER_ERROR"})}}},decoding:{invoke:{id:"decodeAudio",src:"decodeAudio",input:()=>{},onDone:{target:"done",actions:T({type:"BUFFER_READY"})},onError:{target:"error",actions:T({type:"BUFFER_ERROR"})}}},done:{type:"final"},error:{type:"final"}}});function L(o){return Q({types:{context:{},events:{}},actors:{fetchDecode:m},guards:{canPlayWebAudio:()=>!1,isWebAudioOnly:()=>!1,canStartFetch:({context:e})=>e.webAudioLoadingState==="NONE"&&!e.fetchStarted},actions:{playHtml5:()=>{},startSourceNode:()=>{},crossoverHtml5ToWebAudio:()=>{},notifyBufferReady:()=>{},startScheduledSourceNode:()=>{},startProgressLoop:()=>{},pauseHtml5:()=>{},freezePausedTime:()=>{},stopSourceNode:()=>{},stopProgressLoop:()=>{},reportProgress:()=>{},seekHtml5:()=>{},seekWebAudio:()=>{},resetHtml5Element:()=>{},resetTiming:()=>{},notifyTrackEnded:()=>{},triggerFetchForPendingPlay:()=>{},setPendingPlay:c({pendingPlay:()=>!0}),clearPendingPlay:c({pendingPlay:()=>!1}),setIsPlaying:c({isPlaying:()=>!0}),clearIsPlaying:c({isPlaying:()=>!1}),setLoadingState:c({webAudioLoadingState:()=>"LOADING"}),setLoadedState:c({webAudioLoadingState:()=>"LOADED"}),setErrorState:c({webAudioLoadingState:()=>"ERROR"}),clearScheduleAndLookahead:c({scheduledStartContextTime:()=>null,notifiedLookahead:()=>!1}),setPlayingWebAudio:c({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO"}),setScheduledGapless:c({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO",scheduledStartContextTime:({event:e})=>e.when}),clearPlayingAndSchedule:c({isPlaying:()=>!1,scheduledStartContextTime:()=>null,notifiedLookahead:()=>!1}),setNotifiedLookahead:c({notifiedLookahead:()=>!0}),setResolvedUrl:c({resolvedUrl:({event:e})=>e.url}),clearScheduledStart:c({scheduledStartContextTime:()=>null}),setPlayingWebAudioType:c({isPlaying:()=>!0,playbackType:()=>"WEBAUDIO"}),setPlaybackTypeWebAudio:c({playbackType:()=>"WEBAUDIO"}),clearNotifiedLookahead:c({notifiedLookahead:()=>!1})}}).createMachine({id:"track",initial:"idle",context:o,on:{START_FETCH:{guard:"canStartFetch",actions:[c({webAudioLoadingState:()=>"LOADING",fetchStarted:()=>!0}),Z("fetchDecode",{id:"fetchDecode",input:({context:e})=>({trackUrl:e.trackUrl,resolvedUrl:e.resolvedUrl,skipHEAD:e.skipHEAD})})]}},states:{idle:{on:{HTML5_ENDED:{actions:["notifyTrackEnded"]},DEACTIVATE:{actions:["pauseHtml5","resetHtml5Element","resetTiming","stopProgressLoop","clearScheduleAndLookahead"]},ACTIVATE:{actions:["resetTiming","resetHtml5Element","clearScheduleAndLookahead"]},PLAY:[{guard:"canPlayWebAudio",target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},{guard:"isWebAudioOnly",actions:["setPendingPlay","triggerFetchForPendingPlay"]},{target:"html5",actions:["setIsPlaying","playHtml5","startProgressLoop","triggerFetchForPendingPlay"]}],PLAY_WEBAUDIO:{target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},SCHEDULE_GAPLESS:{target:"webaudio",actions:["setScheduledGapless","startScheduledSourceNode"]},PRELOAD:{target:"loading"},BUFFER_LOADING:{actions:"setLoadingState"},BUFFER_READY:[{guard:({context:e})=>e.pendingPlay,target:"webaudio",actions:["clearPendingPlay","setPlayingWebAudio","startSourceNode","startProgressLoop","notifyBufferReady"]},{actions:["setLoadedState","notifyBufferReady"]}],BUFFER_ERROR:{actions:["setErrorState","clearPendingPlay"]},URL_RESOLVED:{actions:"setResolvedUrl"}}},html5:{on:{PAUSE:{actions:["clearIsPlaying","pauseHtml5","stopProgressLoop","reportProgress"]},PLAY:{actions:["setIsPlaying","playHtml5","startProgressLoop"]},BUFFER_LOADING:{actions:"setLoadingState"},PLAY_WEBAUDIO:{target:"webaudio",actions:"setPlayingWebAudio"},BUFFER_READY:{target:"webaudio",actions:["setLoadedState","crossoverHtml5ToWebAudio","setPlaybackTypeWebAudio","clearNotifiedLookahead","notifyBufferReady"]},BUFFER_ERROR:{actions:"setErrorState"},SEEK:{actions:["seekHtml5","reportProgress"]},LOOKAHEAD_REACHED:{actions:"setNotifiedLookahead"},HTML5_ENDED:{target:"idle",actions:["clearIsPlaying","stopProgressLoop","notifyTrackEnded"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","pauseHtml5","stopProgressLoop","resetTiming","resetHtml5Element"]},URL_RESOLVED:{actions:"setResolvedUrl"},DEACTIVATE:{target:"idle",actions:["clearIsPlaying","pauseHtml5","resetHtml5Element","resetTiming","stopProgressLoop"]}}},loading:{on:{BUFFER_LOADING:{actions:"setLoadingState"},BUFFER_READY:[{guard:({context:e})=>e.pendingPlay,target:"webaudio",actions:["clearPendingPlay","setPlayingWebAudio","startSourceNode","startProgressLoop","notifyBufferReady"]},{target:"idle",actions:["setLoadedState","notifyBufferReady"]}],BUFFER_ERROR:{target:"idle",actions:["setErrorState","clearPendingPlay"]},PLAY:[{guard:"canPlayWebAudio",target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},{guard:"isWebAudioOnly",actions:["setPendingPlay","triggerFetchForPendingPlay"]},{target:"html5",actions:["setIsPlaying","playHtml5","startProgressLoop","triggerFetchForPendingPlay"]}],PLAY_WEBAUDIO:{target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},SCHEDULE_GAPLESS:{target:"webaudio",actions:["setScheduledGapless","startScheduledSourceNode"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","resetTiming","resetHtml5Element"]},DEACTIVATE:{target:"idle",actions:["clearIsPlaying","resetTiming"]},URL_RESOLVED:{actions:"setResolvedUrl"}}},webaudio:{on:{PAUSE:{actions:["clearIsPlaying","freezePausedTime","clearScheduledStart","stopSourceNode","stopProgressLoop","reportProgress"]},PLAY:[{guard:"canPlayWebAudio",actions:["setIsPlaying","startSourceNode","startProgressLoop"]},{actions:"setIsPlaying"}],PLAY_WEBAUDIO:{actions:"setPlayingWebAudioType"},SEEK:{actions:["clearScheduledStart","seekWebAudio","reportProgress"]},SET_VOLUME:{},CANCEL_GAPLESS:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","stopProgressLoop","resetTiming"]},LOOKAHEAD_REACHED:{actions:"setNotifiedLookahead"},WEBAUDIO_ENDED:{target:"idle",actions:["clearIsPlaying","stopProgressLoop","notifyTrackEnded"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","stopProgressLoop","resetTiming","resetHtml5Element"]},DEACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","resetTiming","resetHtml5Element","stopProgressLoop"]}}}}})}var z=5,D=15,A=.03,y=class{index;metadata;_trackUrl;_resolvedUrl;skipHEAD;_pendingArrayBuffer=null;audio;_playbackMethod;get ctx(){if(this._playbackMethod==="HTML5_ONLY")return null;let e=k();if(e&&!this.gainNode){this.gainNode=e.createGain(),this.gainNode.gain.value=this.audio.volume,this.gainNode.connect(e.destination);try{this._mediaElementSource=e.createMediaElementSource(this.audio),this._html5GainNode=e.createGain(),this._html5GainNode.gain.value=1,this._mediaElementSource.connect(this._html5GainNode),this._html5GainNode.connect(this.gainNode),this.audio.volume=1}catch{this._mediaElementSource=null,this._html5GainNode=null}}return e}gainNode=null;_mediaElementSource=null;_html5GainNode=null;sourceNode=null;audioBuffer=null;_bufferStartPaddingSec=0;_bufferAlignmentMeasured=!1;_waRefCtxTime=0;_waRefTrackTime=0;pausedAtTrackTime=0;_actor;queueRef;rafId=null;_notifiedPreloadThreshold=!1;constructor(e){this.index=e.index,this._trackUrl=e.trackUrl,this._resolvedUrl=e.trackUrl,this.skipHEAD=e.skipHEAD??!1,this.metadata=e.metadata??{},this.queueRef=e.queue,this.audio=new Audio,this.audio.preload="none",e.queue.playbackMethod!=="HTML5_ONLY"&&(this.audio.crossOrigin="anonymous"),this.audio.src=this._trackUrl,this.audio.volume=e.queue.volume,this.audio.controls=!1,this.audio.onerror=()=>{var d,u;let a=(d=this.audio.error)==null?void 0:d.code;if(a===1)return;let n=((u=this.audio.error)==null?void 0:u.message)??"unknown";this.queueRef.onError(new Error(`HTML5 audio error on track ${this.index} (code ${a}): ${n}`))},this.audio.onended=()=>{this.queueRef.onDebug(`audio.onended track=${this.index} machineState=${this._actor.getSnapshot().value} queueIdx=${this.queueRef.currentTrackIndex}`),this._actor.send({type:"HTML5_ENDED"})},this._playbackMethod=e.queue.playbackMethod;let t={trackUrl:this._trackUrl,resolvedUrl:this._trackUrl,skipHEAD:this.skipHEAD,playbackType:"HTML5",webAudioLoadingState:"NONE",isPlaying:!1,scheduledStartContextTime:null,notifiedLookahead:!1,fetchStarted:!1,pendingPlay:!1},r=L(t).provide({guards:{canPlayWebAudio:()=>!!(this.ctx&&this.audioBuffer&&this.gainNode),isWebAudioOnly:()=>this._playbackMethod==="WEBAUDIO_ONLY"},actors:{fetchDecode:m.provide({actors:{resolveUrl:x(async({signal:a})=>{let n=await fetch(this._trackUrl,{method:"HEAD",signal:a});return n.redirected&&n.url?(this._resolvedUrl=n.url,n.url):null}),fetchAudio:x(async({input:a,signal:n})=>{let{resolvedUrl:d}=a,u=await fetch(d,{signal:n});if(!u.ok)throw new Error(`HTTP ${u.status} for ${d}`);this._pendingArrayBuffer=await u.arrayBuffer()}),decodeAudio:x(async()=>{let a=this._pendingArrayBuffer;if(this._pendingArrayBuffer=null,!a||!this.ctx)throw new Error("No ArrayBuffer or AudioContext");this.audioBuffer=await this.ctx.decodeAudioData(a),this._maybeComputeBufferAlignment()})}})},actions:{triggerFetchForPendingPlay:()=>{this.preload(),f()},playHtml5:()=>this._playHtml5(),startSourceNode:()=>{this._startSourceNode(this.pausedAtTrackTime)},crossoverHtml5ToWebAudio:({context:a})=>{this._crossoverHtml5ToWebAudio(a.isPlaying)},startScheduledSourceNode:({context:a})=>{let n=a.scheduledStartContextTime;n===null||!this.ctx||!this.audioBuffer||!this.gainNode||(this._maybeComputeBufferAlignment(),this._stopSourceNode(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.playbackRate.value=this.queueRef.playbackRate,this.sourceNode.connect(this.gainNode),this.sourceNode.onended=this._handleWebAudioEnded,this.sourceNode.start(n,this._bufferStartPaddingSec),this._waRefCtxTime=n,this._waRefTrackTime=0,this.queueRef.onDebug(`startScheduledSourceNode track=${this.index} when=${n.toFixed(3)} ctxNow=${this.ctx.currentTime.toFixed(3)} delta=${(n-this.ctx.currentTime).toFixed(3)}s padding=${this._bufferStartPaddingSec.toFixed(3)}s`))},startProgressLoop:()=>this.startProgressLoop(),pauseHtml5:()=>this.audio.pause(),freezePausedTime:()=>{let a=this.currentTime;this.pausedAtTrackTime=isFinite(a)?a:0},stopSourceNode:()=>this._stopSourceNode(),stopProgressLoop:()=>this._stopProgressLoop(),reportProgress:()=>{queueMicrotask(()=>this.queueRef.onProgress(this.toInfo()))},seekHtml5:()=>this._seekHtml5(),seekWebAudio:()=>this._seekWebAudio(),resetHtml5Element:()=>{this.audio.currentTime=0},resetTiming:()=>{this._waRefCtxTime=0,this._waRefTrackTime=0,this.pausedAtTrackTime=0},notifyTrackEnded:()=>{queueMicrotask(()=>this.queueRef.onTrackEnded(this))},notifyBufferReady:()=>{queueMicrotask(()=>this.queueRef.onTrackBufferReady(this))}}});this._actor=X(r),this._actor.start()}play(){this.queueRef.onDebug(`Track.play() track=${this.index} machineState=${this._actor.getSnapshot().value} hasBuffer=${!!this.audioBuffer} hasCtx=${!!this.ctx} audioPaused=${this.audio.paused}`),this._actor.send({type:"PLAY"})}pause(){this._actor.send({type:"PAUSE"})}seek(e){if(!isFinite(e))return;let t=Math.max(0,isNaN(this.duration)?e:Math.min(e,this.duration));this.pausedAtTrackTime=t,this._actor.send({type:"SEEK",time:t})}setVolume(e){let t=Math.min(1,Math.max(0,e));this._mediaElementSource?this.audio.volume=1:this.audio.volume=t,this.gainNode&&(this.gainNode.gain.value=t),this._actor.send({type:"SET_VOLUME",volume:t})}setPlaybackRate(e){if(this.ctx&&this.sourceNode&&this._actor.getSnapshot().context.isPlaying){let t=this.sourceNode.playbackRate.value;this._waRefTrackTime=this._waRefTrackTime+(this.ctx.currentTime-this._waRefCtxTime)*t,this._waRefCtxTime=this.ctx.currentTime}this.audio.playbackRate=e,this.sourceNode&&(this.sourceNode.playbackRate.value=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&&(f(),this.ctx&&this._actor.send({type:"START_FETCH"}))}seekToEnd(e=6){let t=this.duration;!isNaN(t)&&t>e&&this.seek(t-e)}activate(){this._actor.send({type:"ACTIVATE"})}deactivate(){this.queueRef.onDebug(`Track.deactivate() track=${this.index} machineState=${this._actor.getSnapshot().value} isPlaying=${this.isPlaying}`),this._notifiedPreloadThreshold=!1,this._actor.send({type:"DEACTIVATE"}),this.queueRef.onDebug(`Track.deactivate() done track=${this.index} machineState=${this._actor.getSnapshot().value}`)}destroy(){var e;this.deactivate(),this._pendingArrayBuffer=null,this.audioBuffer=null,(e=this.gainNode)==null||e.disconnect(),this.gainNode=null,this._actor.stop()}cancelGaplessStart(){this._actor.getSnapshot().context.scheduledStartContextTime!==null&&this._actor.send({type:"CANCEL_GAPLESS"})}scheduleGaplessStart(e){!this.ctx||!this.audioBuffer||!this.gainNode||this._actor.send({type:"SCHEDULE_GAPLESS",when:e})}get currentTime(){let e=this._actor.getSnapshot();return e.value==="webaudio"?e.context.isPlaying?this.ctx?Math.max(0,this._waRefTrackTime+(this.ctx.currentTime-this._waRefCtxTime)*this.queueRef.playbackRate):0:this.pausedAtTrackTime:this.audio.currentTime}get duration(){return this._actor.getSnapshot().value==="html5"&&!isNaN(this.audio.duration)?this.audio.duration:this.audioBuffer?this.audioBuffer.duration:this.audio.duration}get isPaused(){let e=this._actor.getSnapshot();return e.value==="webaudio"?!e.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 scheduledStartContextTime(){return this._actor.getSnapshot().context.scheduledStartContextTime}get playbackEndContextTime(){let e=this._actor.getSnapshot();if(e.value!=="webaudio"||!e.context.isPlaying||!this.sourceNode||!this.audioBuffer)return null;let t=this.sourceNode.playbackRate.value||1,r=this.audioBuffer.duration-this._bufferStartPaddingSec-this._waRefTrackTime;return this._waRefCtxTime+r/t}get isBufferLoaded(){return this.audioBuffer!==null}toInfo(){var e;return{index:this.index,currentTime:this.currentTime,duration:this.duration,isPlaying:this.isPlaying,isPaused:this.isPaused,volume:((e=this.gainNode)==null?void 0:e.gain.value)??this.audio.volume,trackUrl:this.trackUrl,playbackType:this.playbackType,webAudioLoadingState:this.webAudioLoadingState,metadata:this.metadata,playbackRate:this.queueRef.playbackRate,machineState:this.machineState}}_playHtml5(){this.audio.preload!=="auto"&&(this.audio.preload="auto"),this.audio.playbackRate=this.queueRef.playbackRate;let e=this.audio.play();e&&e.catch(t=>{t instanceof Error&&t.name==="NotAllowedError"?this.queueRef.onPlayBlocked():t instanceof Error&&t.name==="AbortError"||this.queueRef.onError(t instanceof Error?t:new Error(String(t)))})}_seekHtml5(){let e=this.pausedAtTrackTime;isFinite(e)&&(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()))}_crossoverHtml5ToWebAudio(e){if(!this.ctx||!this.audioBuffer||!this.gainNode)return;let t=this.audio.currentTime;if(this.pausedAtTrackTime=isFinite(t)?t:0,!e){this.audio.pause(),this.queueRef.onDebug(`crossoverHtml5ToWebAudio track=${this.index} offset=${this.pausedAtTrackTime.toFixed(3)} wasPlaying=false`);return}let r=this.ctx.currentTime,a=r+A;if(this._html5GainNode){this._html5GainNode.gain.cancelScheduledValues(r),this._html5GainNode.gain.setValueAtTime(1,r),this._html5GainNode.gain.linearRampToValueAtTime(0,a);let n=this.ctx,d=this._html5GainNode;setTimeout(()=>{this.audio.pause(),n&&d&&(d.gain.cancelScheduledValues(n.currentTime),d.gain.setValueAtTime(1,n.currentTime))},A*1e3+5)}else{let n=this.audio.volume;this.audio.volume=0,this.audio.pause(),this.audio.volume=n}this._startSourceNode(this.pausedAtTrackTime,A),this.queueRef.onDebug(`crossoverHtml5ToWebAudio track=${this.index} offset=${this.pausedAtTrackTime.toFixed(3)} wasPlaying=true fade=${A}s mediaSource=${!!this._html5GainNode}`)}_maybeComputeBufferAlignment(){this.audioBuffer&&(this._bufferAlignmentMeasured||(this._bufferStartPaddingSec=0,this._bufferAlignmentMeasured=!0,this.queueRef.onDebug(`_maybeComputeBufferAlignment track=${this.index} bufferDur=${this.audioBuffer.duration.toFixed(3)}s html5Dur=${isNaN(this.audio.duration)?"NaN":this.audio.duration.toFixed(3)+"s"} (alignment shift disabled \u2014 see comment)`)))}_startSourceNode(e,t=0){if(!(!this.ctx||!this.audioBuffer||!this.gainNode)){if(this._maybeComputeBufferAlignment(),this._stopSourceNode(),this.ctx.state==="suspended"&&this.ctx.resume(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.playbackRate.value=this.queueRef.playbackRate,t>0){let r=this.ctx.createGain(),a=this.ctx.currentTime;r.gain.setValueAtTime(0,a),r.gain.linearRampToValueAtTime(1,a+t),this.sourceNode.connect(r),r.connect(this.gainNode)}else this.sourceNode.connect(this.gainNode);this.sourceNode.onended=this._handleWebAudioEnded,this._waRefCtxTime=this.ctx.currentTime,this._waRefTrackTime=e,this.sourceNode.start(0,e+this._bufferStartPaddingSec)}}_stopSourceNode(){if(this.sourceNode){this.sourceNode.onended=null;try{this.sourceNode.stop()}catch{}try{this.sourceNode.disconnect()}catch{}this.sourceNode=null}}_seekWebAudio(){let t=this._actor.getSnapshot().context.isPlaying,r=this.pausedAtTrackTime;this._stopSourceNode(),t&&this._startSourceNode(r)}_handleWebAudioEnded=()=>{this.queueRef.onDebug(`_handleWebAudioEnded track=${this.index} sourceNode=${!!this.sourceNode} queueIdx=${this.queueRef.currentTrackIndex}`),this.sourceNode&&this._actor.send({type:"WEBAUDIO_ENDED"})};startProgressLoop(){if(this.rafId!==null)return;let e=()=>{if(this.isPaused||!this.isPlaying){this.rafId=null;return}this.queueRef.onProgress(this.toInfo());let t=this.duration-this.currentTime;!this._actor.getSnapshot().context.notifiedLookahead&&!isNaN(t)&&t<=z&&(this._actor.send({type:"LOOKAHEAD_REACHED"}),queueMicrotask(()=>this.queueRef.onTrackBufferReady(this)));let a=isNaN(this.duration)?D:Math.min(this.duration*.2,D);!this._notifiedPreloadThreshold&&this.currentTime>=a&&(this._notifiedPreloadThreshold=!0,queueMicrotask(()=>this.queueRef.onPreloadReady(this))),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}_stopProgressLoop(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}};function I(o,e){let t=0;return(...r)=>{let a=performance.now();a-t<e||(t=a,o(...r))}}var M=5,_=class{_tracks=[];_actor;_onProgress;_onEnded;_onPlayNextTrack;_onPlayPreviousTrack;_onStartNewTrack;_onError;_onPlayBlocked;_onDebug;playbackMethod;_volume;_preloadNumTracks;_playbackRate;_scheduledNextIndex=null;_throttledUpdatePositionState=I((e,t,r)=>R(e,t,r),1e3);constructor(e={}){let{tracks:t=[],onProgress:r,onEnded:a,onPlayNextTrack:n,onPlayPreviousTrack:d,onStartNewTrack:u,onError:O,onPlayBlocked:U,onDebug:w,playbackMethod:G="HYBRID",trackMetadata:H=[],volume:B=1,preloadNumTracks:F=2,playbackRate:$=1}=e;this._volume=Math.min(1,Math.max(0,B)),this._preloadNumTracks=Math.max(0,F),this._playbackRate=Math.min(4,Math.max(.25,$)),this.playbackMethod=G,this._onProgress=r,this._onEnded=a,this._onPlayNextTrack=n,this._onPlayPreviousTrack=d,this._onStartNewTrack=u,this._onError=O,this._onPlayBlocked=U,this._onDebug=w,this._tracks=t.map((s,i)=>new y({trackUrl:s,index:i,queue:this,metadata:H[i]}));let W=C({currentTrackIndex:0,trackCount:this._tracks.length}).provide({actions:{deactivateCurrent:({context:s})=>{var i;(i=this._trackAt(s.currentTrackIndex))==null||i.deactivate()},deactivateEndedTrack:({context:s})=>{var i;(i=this._trackAt(s.currentTrackIndex))==null||i.deactivate()},activateAndPlayCurrent:({context:s})=>{let i=this._trackAt(s.currentTrackIndex);i&&(i.activate(),this._scheduledNextIndex!==i.index&&i.play())},playOrContinueGapless:({context:s})=>{let i=this._trackAt(s.currentTrackIndex);i&&(this._scheduledNextIndex!==i.index?i.play():(this._scheduledNextIndex=null,this.onDebug(`onTrackEnded: gapless track ${i.index} \u2014 sourceNode=${i.hasSourceNode} isPlaying=${i.isPlaying} machineState=${i.machineState}`),i.startProgressLoop()))},cancelAllGapless:()=>this._cancelScheduledGapless(),notifyStartNewTrack:({context:s})=>{var l;let i=this._trackAt(s.currentTrackIndex);i&&((l=this._onStartNewTrack)==null||l.call(this,i.toInfo()))},notifyPlayNextTrack:({context:s})=>{var l;let i=this._trackAt(s.currentTrackIndex);i&&((l=this._onPlayNextTrack)==null||l.call(this,i.toInfo()))},notifyPlayPreviousTrack:({context:s})=>{var l;let i=this._trackAt(s.currentTrackIndex);i&&((l=this._onPlayPreviousTrack)==null||l.call(this,i.toInfo()))},notifyEnded:()=>{var s;return(s=this._onEnded)==null?void 0:s.call(this)},updateMediaSessionMetadata:({context:s})=>{let i=this._trackAt(s.currentTrackIndex);i&&b(i.metadata)},preloadAhead:({context:s})=>{this._preloadAhead(s.currentTrackIndex)},playCurrent:({context:s})=>{var i;(i=this._trackAt(s.currentTrackIndex))==null||i.play()},pauseCurrent:({context:s})=>{var i;(i=this._trackAt(s.currentTrackIndex))==null||i.pause()},seekCurrent:({context:s,event:i})=>{var v;let l=i;(v=this._trackAt(s.currentTrackIndex))==null||v.seek(l.time)},seekCurrentToZero:({context:s})=>{var i;(i=this._trackAt(s.currentTrackIndex))==null||i.seek(0)},scheduleGapless:({context:s})=>{this._tryScheduleGapless(s.currentTrackIndex)},cancelScheduledGapless:()=>{this._cancelScheduledGapless()},cancelAndRescheduleGapless:({context:s})=>{this._cancelScheduledGapless(),this._tryScheduleGapless(s.currentTrackIndex)}}});this._actor=j(W),this._actor.subscribe(s=>{N(s.value==="playing")}),this._actor.start(),P({onPlay:()=>this.play(),onPause:()=>{this._actor.getSnapshot().value==="playing"&&this.pause()},onNext:()=>this.next(),onPrevious:()=>this.previous(),onSeek:s=>this.seek(s)})}play(){this._currentTrack&&this._actor.send({type:"PLAY"})}pause(){this._actor.send({type:"PAUSE"})}togglePlayPause(){this._actor.getSnapshot().value==="playing"?this.pause():this.play()}next(){this._actor.getSnapshot().context.currentTrackIndex+1>=this._tracks.length||this._actor.send({type:"NEXT"})}previous(){let e=this._currentTrack;if(e&&e.currentTime>8){e.seek(0),e.play();return}this._actor.send({type:"PREVIOUS"})}gotoTrack(e,t=!1){e<0||e>=this._tracks.length||(this.onDebug(`gotoTrack(${e}, playImmediately=${t}) queueState=${this._actor.getSnapshot().value} curIdx=${this._actor.getSnapshot().context.currentTrackIndex}`),this._actor.send({type:"GOTO",index:e,playImmediately:t}))}seek(e){this._actor.send({type:"SEEK",time:e})}setVolume(e){let t=Math.min(1,Math.max(0,e));this._volume=t;for(let r of this._tracks)r.setVolume(t)}setPlaybackRate(e){var a;let t=Math.min(4,Math.max(.25,e));this._playbackRate=t,(a=this._currentTrack)==null||a.setPlaybackRate(t),this._cancelScheduledGapless();let r=this._actor.getSnapshot();r.value==="playing"&&this._tryScheduleGapless(r.context.currentTrackIndex)}addTrack(e,t={}){let r=this._tracks.length,a=t.metadata??{};this._tracks.push(new y({trackUrl:e,index:r,queue:this,skipHEAD:t.skipHEAD,metadata:a})),this._actor.send({type:"ADD_TRACK"})}removeTrack(e){if(!(e<0||e>=this._tracks.length)){this._tracks[e].destroy(),this._tracks.splice(e,1);for(let t=e;t<this._tracks.length;t++)this._tracks[t].index=t;this._scheduledNextIndex===e?this._scheduledNextIndex=null:this._scheduledNextIndex!==null&&this._scheduledNextIndex>e&&this._scheduledNextIndex--,this._actor.send({type:"REMOVE_TRACK",index:e})}}resumeAudioContext(){return f()}destroy(){for(let e of this._tracks)e.destroy();this._tracks=[],this._actor.stop()}get currentTrack(){var e;return(e=this._currentTrack)==null?void 0:e.toInfo()}get currentTrackIndex(){return this._actor.getSnapshot().context.currentTrackIndex}get tracks(){return this._tracks.map(e=>e.toInfo())}get isPlaying(){return this._actor.getSnapshot().value==="playing"}get isPaused(){return this._actor.getSnapshot().value==="paused"}get volume(){return this._volume}get preloadNumTracks(){return this._preloadNumTracks}set preloadNumTracks(e){this._preloadNumTracks=Math.max(0,e);let t=this._actor.getSnapshot();t.value==="playing"&&this._preloadAhead(t.context.currentTrackIndex)}get playbackRate(){return this._playbackRate}get queueSnapshot(){let e=this._actor.getSnapshot();return{state:e.value,context:e.context}}onTrackEnded(e){let t=this._actor.getSnapshot();if(this.onDebug(`onTrackEnded track=${e.index} queueState=${t.value} curIdx=${t.context.currentTrackIndex}`),e!==this._trackAt(t.context.currentTrackIndex))return;this._actor.send({type:"TRACK_ENDED"});let r=this._actor.getSnapshot();this.onDebug(`onTrackEnded after TRACK_ENDED \u2192 queueState=${r.value} curIdx=${r.context.currentTrackIndex}`)}onTrackBufferReady(e){this._actor.send({type:"TRACK_LOADED",index:e.index})}onProgress(e){var t;e.index===this._actor.getSnapshot().context.currentTrackIndex&&(isNaN(e.duration)||this._throttledUpdatePositionState(e.duration,e.currentTime,this._playbackRate),(t=this._onProgress)==null||t.call(this,e))}onError(e){var t;(t=this._onError)==null||t.call(this,e)}onPlayBlocked(){var e;this._actor.send({type:"PAUSE"}),(e=this._onPlayBlocked)==null||e.call(this)}onPreloadReady(e){let t=this._actor.getSnapshot();e.index===t.context.currentTrackIndex&&this._preloadAhead(t.context.currentTrackIndex)}onDebug(e){var t;(t=this._onDebug)==null||t.call(this,e)}_trackAt(e){return this._tracks[e]}get _currentTrack(){return this._tracks[this._actor.getSnapshot().context.currentTrackIndex]}_preloadAhead(e){let t=this._trackAt(e);if(t!=null&&t.isPlaying&&t.playbackType==="HTML5"&&t.webAudioLoadingState==="LOADING"){this.onDebug(`_preloadAhead(${e}): deferring all \u2014 current track buffer still loading`);return}let r=t!=null&&t.isPlaying&&(()=>{let n=isNaN(t.duration)?15:Math.min(t.duration*.2,15);return t.currentTime<n})(),a=e+this._preloadNumTracks+1;this.onDebug(`_preloadAhead(${e}) limit=${a} trackCount=${this._tracks.length} belowThreshold=${r}`);for(let n=e+1;n<this._tracks.length&&n<a;n++){let d=this._tracks[n];if(n>e+1&&r){this.onDebug(`_preloadAhead: deferring track ${n} (current at ${t.currentTime.toFixed(1)}s, below threshold)`);return}if(d.isBufferLoaded)this.onDebug(`_preloadAhead: track ${n} already loaded`);else{this.onDebug(`_preloadAhead: starting preload for track ${n}`),d.preload();return}}}_cancelScheduledGapless(){if(this._scheduledNextIndex===null)return;let e=this._trackAt(this._scheduledNextIndex);e&&(e.cancelGaplessStart(),this.onDebug(`_cancelScheduledGapless: cancelled track ${this._scheduledNextIndex}`)),this._scheduledNextIndex=null}_tryScheduleGapless(e){let t=k();if(!t||this.playbackMethod==="HTML5_ONLY")return;let r=e+1;if(r>=this._tracks.length)return;let a=this._tracks[e],n=this._tracks[r];if(!a.isBufferLoaded||!n.isBufferLoaded||this._scheduledNextIndex===r||!a.isPlaying)return;let d=this._computeTrackEndTime(a);if(d===null||d<t.currentTime+.01)return;let u=d-t.currentTime;if(a.playbackType==="HTML5"&&u>M){this.onDebug(`_tryScheduleGapless: deferring \u2014 HTML5 track ${e} has ${u.toFixed(1)}s remaining (max lookahead=${M}s)`);return}n.scheduleGaplessStart(d),this.onDebug(`_tryScheduleGapless: scheduled track ${r} at endTime=${d.toFixed(3)} (in ${(d-t.currentTime).toFixed(1)}s) curPlaybackType=${a.playbackType}`),this._scheduledNextIndex=r}_computeTrackEndTime(e){let t=k();if(!t||!e.isBufferLoaded)return null;let r=e.playbackEndContextTime;if(r!==null)return r>t.currentTime?r:null;let a=e.duration;if(isNaN(a))return null;let n=(a-e.currentTime)/this._playbackRate;return n<=0?null:t.currentTime+n}};export{_ as Queue,_ as default};
|
|
1
|
+
import{createActor as J}from"xstate";var q=typeof window<"u",y;function K(){if(!q)return null;let n=window.AudioContext??window.webkitAudioContext;return n?new n:null}function k(){return y===void 0?null:y}function m(){y===void 0&&(y=K());let n=y;return n&&n.state==="suspended"?n.resume():Promise.resolve()}var A=typeof navigator<"u"&&"mediaSession"in navigator;function C(n){if(!A)return;let{mediaSession:e}=navigator;e.setActionHandler("play",n.onPlay),e.setActionHandler("pause",n.onPause),e.setActionHandler("nexttrack",n.onNext),e.setActionHandler("previoustrack",n.onPrevious),e.setActionHandler("seekto",t=>{t.seekTime!=null&&n.onSeek(t.seekTime)})}function L(n){if(A){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 D(n){A&&(navigator.mediaSession.playbackState=n?"playing":"paused")}function M(n,e,t=1){if(A)try{navigator.mediaSession.setPositionState({duration:n,position:e,playbackRate:t})}catch{}}import{setup as Y,assign as p}from"xstate";function I(n){return Y({types:{context:{},events:{}},guards:{hasNextTrack:({context:e})=>e.currentTrackIndex+1<e.trackCount,playImmediately:({event:e})=>!!e.playImmediately,willBeEmpty:({context:e})=>e.trackCount<=1,isRemovingCurrent:({context:e,event:t})=>t.index===e.currentTrackIndex},actions:{incrementTrackCount:p({trackCount:({context:e})=>e.trackCount+1}),decrementTrackCount:p({trackCount:({context:e})=>Math.max(0,e.trackCount-1),currentTrackIndex:({context:e,event:t})=>{let r=t,a=Math.max(0,e.trackCount-1);return r.index<e.currentTrackIndex?Math.max(0,e.currentTrackIndex-1):a>0?Math.min(e.currentTrackIndex,a-1):0}}),gotoTrackIndex:p({currentTrackIndex:({event:e})=>e.index}),advanceToNextTrack:p({currentTrackIndex:({context:e})=>{let t=e.currentTrackIndex+1;return t<e.trackCount?t:e.currentTrackIndex}}),goToPreviousTrack:p({currentTrackIndex:({context:e})=>Math.max(0,e.currentTrackIndex-1)}),advanceOnTrackEnd:p({currentTrackIndex:({context:e})=>Math.min(e.currentTrackIndex+1,e.trackCount-1)}),resetToFirstTrack:p({currentTrackIndex:()=>0}),deactivateCurrent:()=>{},deactivateEndedTrack:()=>{},activateAndPlayCurrent:()=>{},playOrContinueGapless:()=>{},cancelAllGapless:()=>{},notifyStartNewTrack:()=>{},notifyPlayNextTrack:()=>{},notifyPlayPreviousTrack:()=>{},notifyEnded:()=>{},updateMediaSessionMetadata:()=>{},preloadAhead:()=>{},playCurrent:()=>{},pauseCurrent:()=>{},seekCurrent:()=>{},seekCurrentToZero:()=>{},scheduleGapless:()=>{},cancelScheduledGapless:()=>{},cancelAndRescheduleGapless:()=>{}}}).createMachine({id:"queue",initial:"idle",context:n,on:{ADD_TRACK:{actions:"incrementTrackCount"},REMOVE_TRACK:{actions:"decrementTrackCount"}},states:{idle:{on:{PLAY:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"paused",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],TRACK_LOADED:{actions:["preloadAhead"]}}},playing:{on:{REMOVE_TRACK:[{guard:"willBeEmpty",target:"idle",actions:["cancelAllGapless","decrementTrackCount"]},{guard:"isRemovingCurrent",actions:["cancelAllGapless","decrementTrackCount","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["decrementTrackCount","cancelAndRescheduleGapless","preloadAhead"]}],PAUSE:{target:"paused",actions:["cancelScheduledGapless","pauseCurrent"]},TOGGLE:{target:"paused",actions:["cancelScheduledGapless","pauseCurrent"]},NEXT:{actions:["deactivateCurrent","cancelAllGapless","advanceToNextTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},PREVIOUS:{actions:["deactivateCurrent","cancelAllGapless","goToPreviousTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayPreviousTrack","updateMediaSessionMetadata","preloadAhead"]},GOTO:[{guard:"playImmediately",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],SEEK:{actions:["seekCurrent","cancelAndRescheduleGapless"]},TRACK_ENDED:[{guard:"hasNextTrack",target:"playing",actions:["deactivateEndedTrack","advanceOnTrackEnd","playOrContinueGapless","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"ended",actions:["deactivateEndedTrack","notifyEnded"]}],TRACK_LOADED:[{guard:({context:e,event:t})=>t.index===e.currentTrackIndex,actions:["cancelAndRescheduleGapless","preloadAhead"]},{actions:["scheduleGapless","preloadAhead"]}]}},paused:{on:{REMOVE_TRACK:[{guard:"willBeEmpty",target:"idle",actions:["cancelAllGapless","decrementTrackCount"]},{guard:"isRemovingCurrent",actions:["cancelAllGapless","decrementTrackCount","preloadAhead"]},{actions:["decrementTrackCount","preloadAhead"]}],PLAY:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},TOGGLE:{target:"playing",actions:["playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},NEXT:{actions:["deactivateCurrent","cancelAllGapless","advanceToNextTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayNextTrack","updateMediaSessionMetadata","preloadAhead"]},PREVIOUS:{actions:["deactivateCurrent","cancelAllGapless","goToPreviousTrack","activateAndPlayCurrent","notifyStartNewTrack","notifyPlayPreviousTrack","updateMediaSessionMetadata","preloadAhead"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}],SEEK:{actions:["seekCurrent"]},TRACK_ENDED:[{guard:"hasNextTrack",target:"paused",actions:["deactivateEndedTrack","advanceOnTrackEnd","notifyStartNewTrack","updateMediaSessionMetadata"]},{target:"ended",actions:["deactivateEndedTrack","notifyEnded"]}],TRACK_LOADED:{actions:["preloadAhead"]}}},ended:{on:{ADD_TRACK:{target:"paused",actions:"incrementTrackCount"},PLAY:{target:"playing",actions:["resetToFirstTrack","playCurrent","updateMediaSessionMetadata","preloadAhead","scheduleGapless"]},GOTO:[{guard:"playImmediately",target:"playing",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","activateAndPlayCurrent","notifyStartNewTrack","updateMediaSessionMetadata","preloadAhead"]},{target:"paused",actions:["deactivateCurrent","cancelAllGapless","gotoTrackIndex","seekCurrentToZero","preloadAhead"]}]}}}})}import{createActor as z,fromPromise as N}from"xstate";import{setup as Z,assign as u,spawnChild as X}from"xstate";import{setup as Q,assign as P,sendParent as _,fromPromise as b}from"xstate";var S=Q({types:{context:{},input:{}},actors:{resolveUrl:b(async()=>null),fetchAudio:b(async()=>{}),decodeAudio:b(async()=>{})},guards:{shouldSkipHEAD:({context:n})=>n.skipHEAD}}).createMachine({id:"fetchDecode",initial:"resolvingUrl",context:{trackUrl:"",resolvedUrl:"",skipHEAD:!1},entry:P(({event:n})=>{let{input:e}=n;return{trackUrl:e.trackUrl,resolvedUrl:e.resolvedUrl,skipHEAD:e.skipHEAD}}),states:{resolvingUrl:{always:{guard:"shouldSkipHEAD",target:"fetching"},invoke:{id:"resolveUrl",src:"resolveUrl",input:({context:n})=>({trackUrl:n.trackUrl}),onDone:{target:"fetching",actions:[P({resolvedUrl:({event:n,context:e})=>n.output??e.resolvedUrl,skipHEAD:()=>!0}),_(({event:n,context:e})=>({type:"URL_RESOLVED",url:n.output??e.resolvedUrl}))]},onError:{target:"fetching",actions:P({skipHEAD:()=>!0})}}},fetching:{invoke:{id:"fetchAudio",src:"fetchAudio",input:({context:n})=>({resolvedUrl:n.resolvedUrl}),onDone:"decoding",onError:{target:"error",actions:_({type:"BUFFER_ERROR"})}}},decoding:{invoke:{id:"decodeAudio",src:"decodeAudio",input:()=>{},onDone:{target:"done",actions:_({type:"BUFFER_READY"})},onError:{target:"error",actions:_({type:"BUFFER_ERROR"})}}},done:{type:"final"},error:{type:"final"}}});function U(n){return Z({types:{context:{},events:{}},actors:{fetchDecode:S},guards:{canPlayWebAudio:()=>!1,isWebAudioOnly:()=>!1,canStartFetch:({context:e})=>e.webAudioLoadingState==="NONE"&&!e.fetchStarted},actions:{playHtml5:()=>{},startSourceNode:()=>{},crossoverHtml5ToWebAudio:()=>{},notifyBufferReady:()=>{},startScheduledSourceNode:()=>{},startProgressLoop:()=>{},pauseHtml5:()=>{},freezePausedTime:()=>{},stopSourceNode:()=>{},stopProgressLoop:()=>{},reportProgress:()=>{},seekHtml5:()=>{},seekWebAudio:()=>{},resetHtml5Element:()=>{},resetTiming:()=>{},notifyTrackEnded:()=>{},triggerFetchForPendingPlay:()=>{},setPendingPlay:u({pendingPlay:()=>!0}),clearPendingPlay:u({pendingPlay:()=>!1}),setIsPlaying:u({isPlaying:()=>!0}),clearIsPlaying:u({isPlaying:()=>!1}),setLoadingState:u({webAudioLoadingState:()=>"LOADING"}),setLoadedState:u({webAudioLoadingState:()=>"LOADED"}),setErrorState:u({webAudioLoadingState:()=>"ERROR"}),clearScheduleAndLookahead:u({scheduledStartContextTime:()=>null,notifiedLookahead:()=>!1}),setPlayingWebAudio:u({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO"}),setScheduledGapless:u({isPlaying:()=>!0,webAudioLoadingState:()=>"LOADED",playbackType:()=>"WEBAUDIO",scheduledStartContextTime:({event:e})=>e.when}),clearPlayingAndSchedule:u({isPlaying:()=>!1,scheduledStartContextTime:()=>null,notifiedLookahead:()=>!1}),setNotifiedLookahead:u({notifiedLookahead:()=>!0}),setResolvedUrl:u({resolvedUrl:({event:e})=>e.url}),clearScheduledStart:u({scheduledStartContextTime:()=>null}),setPlayingWebAudioType:u({isPlaying:()=>!0,playbackType:()=>"WEBAUDIO"}),setPlaybackTypeWebAudio:u({playbackType:()=>"WEBAUDIO"}),clearNotifiedLookahead:u({notifiedLookahead:()=>!1})}}).createMachine({id:"track",initial:"idle",context:n,on:{START_FETCH:{guard:"canStartFetch",actions:[u({webAudioLoadingState:()=>"LOADING",fetchStarted:()=>!0}),X("fetchDecode",{id:"fetchDecode",input:({context:e})=>({trackUrl:e.trackUrl,resolvedUrl:e.resolvedUrl,skipHEAD:e.skipHEAD})})]}},states:{idle:{on:{HTML5_ENDED:{actions:["notifyTrackEnded"]},DEACTIVATE:{actions:["pauseHtml5","resetHtml5Element","resetTiming","stopProgressLoop","clearScheduleAndLookahead","clearPendingPlay"]},ACTIVATE:{actions:["resetTiming","resetHtml5Element","clearScheduleAndLookahead","clearPendingPlay"]},PLAY:[{guard:"canPlayWebAudio",target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},{guard:"isWebAudioOnly",actions:["setPendingPlay","triggerFetchForPendingPlay"]},{target:"html5",actions:["setIsPlaying","playHtml5","startProgressLoop","triggerFetchForPendingPlay"]}],PLAY_WEBAUDIO:{target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},SCHEDULE_GAPLESS:{target:"webaudio",actions:["setScheduledGapless","startScheduledSourceNode"]},PRELOAD:{target:"loading"},BUFFER_LOADING:{actions:"setLoadingState"},BUFFER_READY:[{guard:({context:e})=>e.pendingPlay,target:"webaudio",actions:["clearPendingPlay","setPlayingWebAudio","startSourceNode","startProgressLoop","notifyBufferReady"]},{actions:["setLoadedState","notifyBufferReady"]}],BUFFER_ERROR:{actions:["setErrorState","clearPendingPlay"]},URL_RESOLVED:{actions:"setResolvedUrl"}}},html5:{on:{PAUSE:{actions:["clearIsPlaying","pauseHtml5","stopProgressLoop","reportProgress"]},PLAY:{actions:["setIsPlaying","playHtml5","startProgressLoop"]},BUFFER_LOADING:{actions:"setLoadingState"},PLAY_WEBAUDIO:{target:"webaudio",actions:"setPlayingWebAudio"},BUFFER_READY:{target:"webaudio",actions:["setLoadedState","crossoverHtml5ToWebAudio","setPlaybackTypeWebAudio","clearNotifiedLookahead","notifyBufferReady"]},BUFFER_ERROR:{actions:"setErrorState"},SEEK:{actions:["seekHtml5","reportProgress"]},LOOKAHEAD_REACHED:{actions:"setNotifiedLookahead"},HTML5_ENDED:{target:"idle",actions:["clearIsPlaying","stopProgressLoop","notifyTrackEnded"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","pauseHtml5","stopProgressLoop","resetTiming","resetHtml5Element"]},URL_RESOLVED:{actions:"setResolvedUrl"},DEACTIVATE:{target:"idle",actions:["clearIsPlaying","pauseHtml5","resetHtml5Element","resetTiming","stopProgressLoop"]}}},loading:{on:{BUFFER_LOADING:{actions:"setLoadingState"},BUFFER_READY:[{guard:({context:e})=>e.pendingPlay,target:"webaudio",actions:["clearPendingPlay","setPlayingWebAudio","startSourceNode","startProgressLoop","notifyBufferReady"]},{target:"idle",actions:["setLoadedState","notifyBufferReady"]}],BUFFER_ERROR:{target:"idle",actions:["setErrorState","clearPendingPlay"]},PLAY:[{guard:"canPlayWebAudio",target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},{guard:"isWebAudioOnly",actions:["setPendingPlay","triggerFetchForPendingPlay"]},{target:"html5",actions:["setIsPlaying","playHtml5","startProgressLoop","triggerFetchForPendingPlay"]}],PLAY_WEBAUDIO:{target:"webaudio",actions:["setPlayingWebAudio","startSourceNode","startProgressLoop"]},SCHEDULE_GAPLESS:{target:"webaudio",actions:["setScheduledGapless","startScheduledSourceNode"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","clearPendingPlay","resetTiming","resetHtml5Element"]},DEACTIVATE:{target:"idle",actions:["clearIsPlaying","clearPendingPlay","resetTiming"]},URL_RESOLVED:{actions:"setResolvedUrl"}}},webaudio:{on:{PAUSE:{actions:["clearIsPlaying","freezePausedTime","clearScheduledStart","stopSourceNode","stopProgressLoop","reportProgress"]},PLAY:[{guard:"canPlayWebAudio",actions:["setIsPlaying","startSourceNode","startProgressLoop"]},{actions:"setIsPlaying"}],PLAY_WEBAUDIO:{actions:"setPlayingWebAudioType"},SEEK:{actions:["clearScheduledStart","seekWebAudio","reportProgress"]},SET_VOLUME:{},CANCEL_GAPLESS:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","stopProgressLoop","resetTiming"]},LOOKAHEAD_REACHED:{actions:"setNotifiedLookahead"},WEBAUDIO_ENDED:{target:"idle",actions:["clearIsPlaying","stopProgressLoop","notifyTrackEnded"]},ACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","stopProgressLoop","resetTiming","resetHtml5Element"]},DEACTIVATE:{target:"idle",actions:["clearPlayingAndSchedule","stopSourceNode","resetTiming","resetHtml5Element","stopProgressLoop"]}}}}})}var j=5,w=15,x=.03,g=class{index;metadata;_trackUrl;_resolvedUrl;skipHEAD;_pendingArrayBuffer=null;audio;_playbackMethod;get ctx(){if(this._playbackMethod==="HTML5_ONLY")return null;let e=k();if(e&&!this.gainNode){this.gainNode=e.createGain(),this.gainNode.gain.value=this.audio.volume,this.gainNode.connect(e.destination);try{this._mediaElementSource=e.createMediaElementSource(this.audio),this._html5GainNode=e.createGain(),this._html5GainNode.gain.value=1,this._mediaElementSource.connect(this._html5GainNode),this._html5GainNode.connect(this.gainNode),this.audio.volume=1}catch{this._mediaElementSource=null,this._html5GainNode=null}}return e}gainNode=null;_mediaElementSource=null;_html5GainNode=null;sourceNode=null;audioBuffer=null;_bufferStartPaddingSec=0;_bufferAlignmentMeasured=!1;_waRefCtxTime=0;_waRefTrackTime=0;pausedAtTrackTime=0;_actor;queueRef;rafId=null;_notifiedPreloadThreshold=!1;constructor(e){this.index=e.index,this._trackUrl=e.trackUrl,this._resolvedUrl=e.trackUrl,this.skipHEAD=e.skipHEAD??!1,this.metadata=e.metadata??{},this.queueRef=e.queue,this.audio=new Audio,this.audio.preload="none",e.queue.playbackMethod!=="HTML5_ONLY"&&(this.audio.crossOrigin="anonymous"),this.audio.src=this._trackUrl,this.audio.volume=e.queue.volume,this.audio.controls=!1,this.audio.onerror=()=>{var d,c;let a=(d=this.audio.error)==null?void 0:d.code;if(a===1)return;let i=((c=this.audio.error)==null?void 0:c.message)??"unknown";this.queueRef.onError(new Error(`HTML5 audio error on track ${this.index} (code ${a}): ${i}`))},this.audio.onended=()=>{this.queueRef.onDebug(`audio.onended track=${this.index} machineState=${this._actor.getSnapshot().value} queueIdx=${this.queueRef.currentTrackIndex}`),this._actor.send({type:"HTML5_ENDED"})},this._playbackMethod=e.queue.playbackMethod;let t={trackUrl:this._trackUrl,resolvedUrl:this._trackUrl,skipHEAD:this.skipHEAD,playbackType:"HTML5",webAudioLoadingState:"NONE",isPlaying:!1,scheduledStartContextTime:null,notifiedLookahead:!1,fetchStarted:!1,pendingPlay:!1},r=U(t).provide({guards:{canPlayWebAudio:()=>!!(this.ctx&&this.audioBuffer&&this.gainNode),isWebAudioOnly:()=>this._playbackMethod==="WEBAUDIO_ONLY"},actors:{fetchDecode:S.provide({actors:{resolveUrl:N(async({signal:a})=>{let i=await fetch(this._trackUrl,{method:"HEAD",signal:a});return i.redirected&&i.url?(this._resolvedUrl=i.url,i.url):null}),fetchAudio:N(async({input:a,signal:i})=>{let{resolvedUrl:d}=a,c=await fetch(d,{signal:i});if(!c.ok)throw new Error(`HTTP ${c.status} for ${d}`);this._pendingArrayBuffer=await c.arrayBuffer()}),decodeAudio:N(async()=>{let a=this._pendingArrayBuffer;if(this._pendingArrayBuffer=null,!a||!this.ctx)throw new Error("No ArrayBuffer or AudioContext");this.audioBuffer=await this.ctx.decodeAudioData(a),this._maybeComputeBufferAlignment()})}})},actions:{triggerFetchForPendingPlay:()=>{this.preload(),m()},playHtml5:()=>this._playHtml5(),startSourceNode:()=>{this._startSourceNode(this.pausedAtTrackTime)},crossoverHtml5ToWebAudio:({context:a})=>{this._crossoverHtml5ToWebAudio(a.isPlaying)},startScheduledSourceNode:({context:a})=>{let i=a.scheduledStartContextTime;if(i===null||!this.ctx||!this.audioBuffer||!this.gainNode)return;this._maybeComputeBufferAlignment(),this._stopSourceNode(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.playbackRate.value=this.queueRef.playbackRate,this.sourceNode.connect(this.gainNode),this.sourceNode.onended=this._handleWebAudioEnded,this.sourceNode.start(i,this._bufferStartPaddingSec);let d=this.audioBuffer.duration-this._bufferStartPaddingSec,c=this.sourceNode.playbackRate.value||1;d>0&&this.sourceNode.stop(i+d/c),this._waRefCtxTime=i,this._waRefTrackTime=0,this.queueRef.onDebug(`startScheduledSourceNode track=${this.index} when=${i.toFixed(3)} ctxNow=${this.ctx.currentTime.toFixed(3)} delta=${(i-this.ctx.currentTime).toFixed(3)}s padding=${this._bufferStartPaddingSec.toFixed(3)}s`)},startProgressLoop:()=>this.startProgressLoop(),pauseHtml5:()=>this.audio.pause(),freezePausedTime:()=>{let a=this.currentTime;this.pausedAtTrackTime=isFinite(a)?a:0},stopSourceNode:()=>this._stopSourceNode(),stopProgressLoop:()=>this._stopProgressLoop(),reportProgress:()=>{queueMicrotask(()=>this.queueRef.onProgress(this.toInfo()))},seekHtml5:()=>this._seekHtml5(),seekWebAudio:()=>this._seekWebAudio(),resetHtml5Element:()=>{this.audio.currentTime=0},resetTiming:()=>{this._waRefCtxTime=0,this._waRefTrackTime=0,this.pausedAtTrackTime=0},notifyTrackEnded:()=>{queueMicrotask(()=>this.queueRef.onTrackEnded(this))},notifyBufferReady:()=>{queueMicrotask(()=>this.queueRef.onTrackBufferReady(this))}}});this._actor=z(r),this._actor.start()}play(){this.queueRef.onDebug(`Track.play() track=${this.index} machineState=${this._actor.getSnapshot().value} hasBuffer=${!!this.audioBuffer} hasCtx=${!!this.ctx} audioPaused=${this.audio.paused}`),this._actor.send({type:"PLAY"})}pause(){this._actor.send({type:"PAUSE"})}seek(e){if(!isFinite(e))return;let t=Math.max(0,isNaN(this.duration)?e:Math.min(e,this.duration));this.pausedAtTrackTime=t,this._actor.send({type:"SEEK",time:t})}setVolume(e){let t=Math.min(1,Math.max(0,e));this._mediaElementSource?this.audio.volume=1:this.audio.volume=t,this.gainNode&&(this.gainNode.gain.value=t),this._actor.send({type:"SET_VOLUME",volume:t})}setPlaybackRate(e){if(this.ctx&&this.sourceNode&&this._actor.getSnapshot().context.isPlaying&&this.ctx.currentTime>=this._waRefCtxTime){let t=this.sourceNode.playbackRate.value;this._waRefTrackTime=this._waRefTrackTime+(this.ctx.currentTime-this._waRefCtxTime)*t,this._waRefCtxTime=this.ctx.currentTime}if(this.audio.playbackRate=e,this.sourceNode&&(this.sourceNode.playbackRate.value=e,this.audioBuffer&&this.ctx)){let t=this.audioBuffer.duration-this._bufferStartPaddingSec-this._waRefTrackTime;if(t>0)try{this.sourceNode.stop(this._waRefCtxTime+t/e)}catch{}}}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&&(m(),this.ctx&&this._actor.send({type:"START_FETCH"}))}seekToEnd(e=6){let t=this.duration;!isNaN(t)&&t>e&&this.seek(t-e)}activate(){this._actor.send({type:"ACTIVATE"})}deactivate(){this.queueRef.onDebug(`Track.deactivate() track=${this.index} machineState=${this._actor.getSnapshot().value} isPlaying=${this.isPlaying}`),this._notifiedPreloadThreshold=!1,this._actor.send({type:"DEACTIVATE"}),this.queueRef.onDebug(`Track.deactivate() done track=${this.index} machineState=${this._actor.getSnapshot().value}`)}destroy(){var e;this.deactivate(),this._pendingArrayBuffer=null,this.audioBuffer=null,(e=this.gainNode)==null||e.disconnect(),this.gainNode=null,this._actor.stop()}scheduleHtml5Mute(e){!this._html5GainNode||!this.ctx||(this._html5GainNode.gain.setValueAtTime(1,e-.005),this._html5GainNode.gain.linearRampToValueAtTime(0,e))}cancelHtml5Mute(){!this._html5GainNode||!this.ctx||(this._html5GainNode.gain.cancelScheduledValues(this.ctx.currentTime),this._html5GainNode.gain.setValueAtTime(1,this.ctx.currentTime))}cancelGaplessStart(){this._actor.getSnapshot().context.scheduledStartContextTime!==null&&this._actor.send({type:"CANCEL_GAPLESS"})}scheduleGaplessStart(e){if(!this.ctx||!this.audioBuffer||!this.gainNode)return!1;let t=this._actor.getSnapshot().value;return t!=="idle"&&t!=="loading"?!1:(this._actor.send({type:"SCHEDULE_GAPLESS",when:e}),!0)}get currentTime(){let e=this._actor.getSnapshot();return e.value==="webaudio"?e.context.isPlaying?this.ctx?Math.max(0,this._waRefTrackTime+(this.ctx.currentTime-this._waRefCtxTime)*this.queueRef.playbackRate):0:this.pausedAtTrackTime:this.audio.currentTime}get duration(){return this._actor.getSnapshot().value==="html5"&&!isNaN(this.audio.duration)?this.audio.duration:this.audioBuffer?this.audioBuffer.duration:this.audio.duration}get isPaused(){let e=this._actor.getSnapshot();return e.value==="webaudio"?!e.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 scheduledStartContextTime(){return this._actor.getSnapshot().context.scheduledStartContextTime}get playbackEndContextTime(){let e=this._actor.getSnapshot();if(e.value!=="webaudio"||!e.context.isPlaying||!this.sourceNode||!this.audioBuffer)return null;let t=this.sourceNode.playbackRate.value||1,r=this.audioBuffer.duration-this._bufferStartPaddingSec-this._waRefTrackTime;return this._waRefCtxTime+r/t}get isBufferLoaded(){return this.audioBuffer!==null}toInfo(){var e;return{index:this.index,currentTime:this.currentTime,duration:this.duration,isPlaying:this.isPlaying,isPaused:this.isPaused,volume:((e=this.gainNode)==null?void 0:e.gain.value)??this.audio.volume,trackUrl:this.trackUrl,playbackType:this.playbackType,webAudioLoadingState:this.webAudioLoadingState,metadata:this.metadata,playbackRate:this.queueRef.playbackRate,machineState:this.machineState}}_playHtml5(){this.audio.preload!=="auto"&&(this.audio.preload="auto"),this.audio.playbackRate=this.queueRef.playbackRate;let e=this.audio.play();e&&e.catch(t=>{t instanceof Error&&t.name==="NotAllowedError"?this.queueRef.onPlayBlocked():t instanceof Error&&t.name==="AbortError"||this.queueRef.onError(t instanceof Error?t:new Error(String(t)))})}_seekHtml5(){let e=this.pausedAtTrackTime;isFinite(e)&&(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()))}_crossoverHtml5ToWebAudio(e){if(!this.ctx||!this.audioBuffer||!this.gainNode)return;let t=this.audio.currentTime;if(this.pausedAtTrackTime=isFinite(t)?t:0,!e){this.audio.pause(),this.queueRef.onDebug(`crossoverHtml5ToWebAudio track=${this.index} offset=${this.pausedAtTrackTime.toFixed(3)} wasPlaying=false`);return}let r=this._startSourceNode(this.pausedAtTrackTime,x);if(r!==null&&this._html5GainNode){this._html5GainNode.gain.cancelScheduledValues(r),this._html5GainNode.gain.setValueAtTime(1,r),this._html5GainNode.gain.linearRampToValueAtTime(0,r+x);let a=this.ctx,i=this._html5GainNode,d=(r-this.ctx.currentTime+x)*1e3+5;setTimeout(()=>{this.audio.pause(),a&&i&&(i.gain.cancelScheduledValues(a.currentTime),i.gain.setValueAtTime(1,a.currentTime))},d)}else if(!this._html5GainNode)if(r!==null&&this.ctx){let a=(r-this.ctx.currentTime)*1e3;setTimeout(()=>{this.audio.volume=0,this.audio.pause(),this.audio.volume=1},Math.max(0,a))}else this.audio.volume=0,this.audio.pause(),this.audio.volume=1;this.queueRef.onDebug(`crossoverHtml5ToWebAudio track=${this.index} offset=${this.pausedAtTrackTime.toFixed(3)} wasPlaying=true fade=${x}s mediaSource=${!!this._html5GainNode} when=${(r==null?void 0:r.toFixed(3))??"null"}`)}_maybeComputeBufferAlignment(){this.audioBuffer&&(this._bufferAlignmentMeasured||(this._bufferStartPaddingSec=0,this._bufferAlignmentMeasured=!0,this.queueRef.onDebug(`_maybeComputeBufferAlignment track=${this.index} bufferDur=${this.audioBuffer.duration.toFixed(3)}s html5Dur=${isNaN(this.audio.duration)?"NaN":this.audio.duration.toFixed(3)+"s"} (alignment shift disabled \u2014 see comment)`)))}_startSourceNode(e,t=0){if(!this.ctx||!this.audioBuffer||!this.gainNode)return null;this._maybeComputeBufferAlignment(),this._stopSourceNode();let r=this.ctx.state==="suspended";r&&this.ctx.resume(),this.sourceNode=this.ctx.createBufferSource(),this.sourceNode.buffer=this.audioBuffer,this.sourceNode.playbackRate.value=this.queueRef.playbackRate;let a=r?.15:Math.max(.02,2*(this.ctx.baseLatency||0)+.01),i=this.ctx.currentTime+a,d=this.queueRef.playbackRate,c=this.audioBuffer.duration-this._bufferStartPaddingSec,l=Math.min(e+a*d,c);if(t>0){let f=this.ctx.createGain();f.gain.setValueAtTime(0,i),f.gain.linearRampToValueAtTime(1,i+t),this.sourceNode.connect(f),f.connect(this.gainNode)}else this.sourceNode.connect(this.gainNode);this.sourceNode.onended=this._handleWebAudioEnded,this._waRefCtxTime=i,this._waRefTrackTime=l,this.sourceNode.start(i,l+this._bufferStartPaddingSec);let T=this.audioBuffer.duration-this._bufferStartPaddingSec-l;return T>0&&this.sourceNode.stop(i+T/d),i}_stopSourceNode(){if(this.sourceNode){this.sourceNode.onended=null;try{this.sourceNode.stop()}catch{}try{this.sourceNode.disconnect()}catch{}this.sourceNode=null}}_seekWebAudio(){let t=this._actor.getSnapshot().context.isPlaying,r=this.pausedAtTrackTime;this._stopSourceNode(),t&&this._startSourceNode(r)}_handleWebAudioEnded=()=>{this.queueRef.onDebug(`_handleWebAudioEnded track=${this.index} sourceNode=${!!this.sourceNode} queueIdx=${this.queueRef.currentTrackIndex}`),this.sourceNode&&this._actor.send({type:"WEBAUDIO_ENDED"})};startProgressLoop(){if(this.rafId!==null)return;let e=()=>{if(this.isPaused||!this.isPlaying){this.rafId=null;return}this.queueRef.onProgress(this.toInfo());let t=this.duration-this.currentTime;!this._actor.getSnapshot().context.notifiedLookahead&&!isNaN(t)&&t<=j&&(this._actor.send({type:"LOOKAHEAD_REACHED"}),queueMicrotask(()=>this.queueRef.onTrackBufferReady(this)));let a=isNaN(this.duration)?w:Math.min(this.duration*.2,w);!this._notifiedPreloadThreshold&&this.currentTime>=a&&(this._notifiedPreloadThreshold=!0,queueMicrotask(()=>this.queueRef.onPreloadReady(this))),this.rafId=requestAnimationFrame(e)};this.rafId=requestAnimationFrame(e)}_stopProgressLoop(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null)}};function O(n,e){let t=0;return(...r)=>{let a=performance.now();a-t<e||(t=a,n(...r))}}var G=5,E=null;function ee(){if(E)return E;let n=8e3,e=n*10,t=44+e,r=new ArrayBuffer(t),a=new DataView(r),i=(d,c)=>{for(let l=0;l<c.length;l++)a.setUint8(d+l,c.charCodeAt(l))};return i(0,"RIFF"),a.setUint32(4,t-8,!0),i(8,"WAVE"),i(12,"fmt "),a.setUint32(16,16,!0),a.setUint16(20,1,!0),a.setUint16(22,1,!0),a.setUint32(24,n,!0),a.setUint32(28,n,!0),a.setUint16(32,1,!0),a.setUint16(34,8,!0),i(36,"data"),a.setUint32(40,e,!0),new Uint8Array(r,44).fill(128),E=URL.createObjectURL(new Blob([r],{type:"audio/wav"})),E}var v=class{_tracks=[];_actor;_onProgress;_onEnded;_onPlayNextTrack;_onPlayPreviousTrack;_onStartNewTrack;_onError;_onPlayBlocked;_onDebug;playbackMethod;_volume;_preloadNumTracks;_playbackRate;_mediaSessionAnchor=null;_scheduledNextIndex=null;_throttledUpdatePositionState=O((e,t,r)=>M(e,t,r),1e3);constructor(e={}){let{tracks:t=[],onProgress:r,onEnded:a,onPlayNextTrack:i,onPlayPreviousTrack:d,onStartNewTrack:c,onError:l,onPlayBlocked:T,onDebug:f,playbackMethod:H="HYBRID",trackMetadata:B=[],volume:F=1,preloadNumTracks:$=2,playbackRate:W=1}=e;this._volume=Math.min(1,Math.max(0,F)),this._preloadNumTracks=Math.max(0,$),this._playbackRate=Math.min(4,Math.max(.25,W)),this.playbackMethod=H,this._onProgress=r,this._onEnded=a,this._onPlayNextTrack=i,this._onPlayPreviousTrack=d,this._onStartNewTrack=c,this._onError=l,this._onPlayBlocked=T,this._onDebug=f,this._tracks=t.map((s,o)=>new g({trackUrl:s,index:o,queue:this,metadata:B[o]}));let V=I({currentTrackIndex:0,trackCount:this._tracks.length}).provide({actions:{deactivateCurrent:({context:s})=>{var o;(o=this._trackAt(s.currentTrackIndex))==null||o.deactivate()},deactivateEndedTrack:({context:s})=>{var o;(o=this._trackAt(s.currentTrackIndex))==null||o.deactivate()},activateAndPlayCurrent:({context:s})=>{let o=this._trackAt(s.currentTrackIndex);o&&(o.activate(),this._scheduledNextIndex!==o.index&&o.play())},playOrContinueGapless:({context:s})=>{let o=this._trackAt(s.currentTrackIndex);o&&(this._scheduledNextIndex!==o.index?o.play():(this._scheduledNextIndex=null,this.onDebug(`onTrackEnded: gapless track ${o.index} \u2014 sourceNode=${o.hasSourceNode} isPlaying=${o.isPlaying} machineState=${o.machineState}`),o.startProgressLoop()))},cancelAllGapless:()=>this._cancelScheduledGapless(),notifyStartNewTrack:({context:s})=>{var h;let o=this._trackAt(s.currentTrackIndex);o&&((h=this._onStartNewTrack)==null||h.call(this,o.toInfo()))},notifyPlayNextTrack:({context:s})=>{var h;let o=this._trackAt(s.currentTrackIndex);o&&((h=this._onPlayNextTrack)==null||h.call(this,o.toInfo()))},notifyPlayPreviousTrack:({context:s})=>{var h;let o=this._trackAt(s.currentTrackIndex);o&&((h=this._onPlayPreviousTrack)==null||h.call(this,o.toInfo()))},notifyEnded:()=>{var s;return(s=this._onEnded)==null?void 0:s.call(this)},updateMediaSessionMetadata:({context:s})=>{let o=this._trackAt(s.currentTrackIndex);o&&L(o.metadata)},preloadAhead:({context:s})=>{this._preloadAhead(s.currentTrackIndex)},playCurrent:({context:s})=>{var o;(o=this._trackAt(s.currentTrackIndex))==null||o.play()},pauseCurrent:({context:s})=>{var o;(o=this._trackAt(s.currentTrackIndex))==null||o.pause()},seekCurrent:({context:s,event:o})=>{var R;let h=o;(R=this._trackAt(s.currentTrackIndex))==null||R.seek(h.time)},seekCurrentToZero:({context:s})=>{var o;(o=this._trackAt(s.currentTrackIndex))==null||o.seek(0)},scheduleGapless:({context:s})=>{this._tryScheduleGapless(s.currentTrackIndex)},cancelScheduledGapless:()=>{this._cancelScheduledGapless()},cancelAndRescheduleGapless:({context:s})=>{this._cancelScheduledGapless(),this._tryScheduleGapless(s.currentTrackIndex)}}});this._actor=J(V),this._actor.subscribe(s=>{let o=s.value==="playing";D(o),o?this._startMediaSessionAnchor():this._stopMediaSessionAnchor()}),this._actor.start(),C({onPlay:()=>this.play(),onPause:()=>{this._actor.getSnapshot().value==="playing"&&this.pause()},onNext:()=>this.next(),onPrevious:()=>this.previous(),onSeek:s=>this.seek(s)})}play(){this._currentTrack&&this._actor.send({type:"PLAY"})}pause(){this._actor.send({type:"PAUSE"})}togglePlayPause(){this._actor.getSnapshot().value==="playing"?this.pause():this.play()}next(){this._actor.getSnapshot().context.currentTrackIndex+1>=this._tracks.length||this._actor.send({type:"NEXT"})}previous(){let e=this._currentTrack;if(e&&e.currentTime>8){this._actor.send({type:"SEEK",time:0});return}this._actor.send({type:"PREVIOUS"})}gotoTrack(e,t=!1){e<0||e>=this._tracks.length||(this.onDebug(`gotoTrack(${e}, playImmediately=${t}) queueState=${this._actor.getSnapshot().value} curIdx=${this._actor.getSnapshot().context.currentTrackIndex}`),this._actor.send({type:"GOTO",index:e,playImmediately:t}))}seek(e){this._actor.send({type:"SEEK",time:e})}setVolume(e){let t=Math.min(1,Math.max(0,e));this._volume=t;for(let r of this._tracks)r.setVolume(t)}setPlaybackRate(e){var a;let t=Math.min(4,Math.max(.25,e));this._playbackRate=t,(a=this._currentTrack)==null||a.setPlaybackRate(t),this._cancelScheduledGapless();let r=this._actor.getSnapshot();r.value==="playing"&&this._tryScheduleGapless(r.context.currentTrackIndex)}addTrack(e,t={}){let r=this._tracks.length,a=t.metadata??{};this._tracks.push(new g({trackUrl:e,index:r,queue:this,skipHEAD:t.skipHEAD,metadata:a})),this._actor.send({type:"ADD_TRACK"})}removeTrack(e){if(!(e<0||e>=this._tracks.length)){this._tracks[e].destroy(),this._tracks.splice(e,1);for(let t=e;t<this._tracks.length;t++)this._tracks[t].index=t;this._scheduledNextIndex===e?this._scheduledNextIndex=null:this._scheduledNextIndex!==null&&this._scheduledNextIndex>e&&this._scheduledNextIndex--,this._actor.send({type:"REMOVE_TRACK",index:e})}}resumeAudioContext(){return m()}destroy(){this._stopMediaSessionAnchor(),this._mediaSessionAnchor=null;for(let e of this._tracks)e.destroy();this._tracks=[],this._actor.stop()}get currentTrack(){var e;return(e=this._currentTrack)==null?void 0:e.toInfo()}get currentTrackIndex(){return this._actor.getSnapshot().context.currentTrackIndex}get tracks(){return this._tracks.map(e=>e.toInfo())}get isPlaying(){return this._actor.getSnapshot().value==="playing"}get isPaused(){return this._actor.getSnapshot().value==="paused"}get volume(){return this._volume}get preloadNumTracks(){return this._preloadNumTracks}set preloadNumTracks(e){this._preloadNumTracks=Math.max(0,e);let t=this._actor.getSnapshot();t.value==="playing"&&this._preloadAhead(t.context.currentTrackIndex)}get playbackRate(){return this._playbackRate}get queueSnapshot(){let e=this._actor.getSnapshot();return{state:e.value,context:e.context}}onTrackEnded(e){let t=this._actor.getSnapshot();if(this.onDebug(`onTrackEnded track=${e.index} queueState=${t.value} curIdx=${t.context.currentTrackIndex}`),e!==this._trackAt(t.context.currentTrackIndex))return;this._actor.send({type:"TRACK_ENDED"});let r=this._actor.getSnapshot();this.onDebug(`onTrackEnded after TRACK_ENDED \u2192 queueState=${r.value} curIdx=${r.context.currentTrackIndex}`)}onTrackBufferReady(e){this._actor.send({type:"TRACK_LOADED",index:e.index})}onProgress(e){var t;e.index===this._actor.getSnapshot().context.currentTrackIndex&&(isNaN(e.duration)||this._throttledUpdatePositionState(e.duration,e.currentTime,this._playbackRate),(t=this._onProgress)==null||t.call(this,e))}onError(e){var t;(t=this._onError)==null||t.call(this,e)}onPlayBlocked(){var e;this._actor.send({type:"PAUSE"}),(e=this._onPlayBlocked)==null||e.call(this)}onPreloadReady(e){let t=this._actor.getSnapshot();e.index===t.context.currentTrackIndex&&this._preloadAhead(t.context.currentTrackIndex)}onDebug(e){var t;(t=this._onDebug)==null||t.call(this,e)}_trackAt(e){return this._tracks[e]}get _currentTrack(){return this._tracks[this._actor.getSnapshot().context.currentTrackIndex]}_preloadAhead(e){let t=this._trackAt(e);if(t!=null&&t.isPlaying&&t.playbackType==="HTML5"&&t.webAudioLoadingState==="LOADING"){this.onDebug(`_preloadAhead(${e}): deferring all \u2014 current track buffer still loading`);return}let r=t!=null&&t.isPlaying&&(()=>{let i=isNaN(t.duration)?15:Math.min(t.duration*.2,15);return t.currentTime<i})(),a=e+this._preloadNumTracks+1;this.onDebug(`_preloadAhead(${e}) limit=${a} trackCount=${this._tracks.length} belowThreshold=${r}`);for(let i=e+1;i<this._tracks.length&&i<a;i++){let d=this._tracks[i];if(i>e+1&&r){this.onDebug(`_preloadAhead: deferring track ${i} (current at ${t.currentTime.toFixed(1)}s, below threshold)`);return}if(d.isBufferLoaded)this.onDebug(`_preloadAhead: track ${i} already loaded`);else{this.onDebug(`_preloadAhead: starting preload for track ${i}`),d.preload();return}}}_cancelScheduledGapless(){if(this._scheduledNextIndex===null)return;let e=this._trackAt(this._scheduledNextIndex);e&&(e.cancelGaplessStart(),this.onDebug(`_cancelScheduledGapless: cancelled track ${this._scheduledNextIndex}`));let t=this._trackAt(this._actor.getSnapshot().context.currentTrackIndex);t&&t.playbackType==="HTML5"&&t.cancelHtml5Mute(),this._scheduledNextIndex=null}_tryScheduleGapless(e){let t=k();if(!t||this.playbackMethod==="HTML5_ONLY")return;let r=e+1;if(r>=this._tracks.length)return;let a=this._tracks[e],i=this._tracks[r];if(!a.isBufferLoaded||!i.isBufferLoaded||this._scheduledNextIndex===r||!a.isPlaying)return;let d=this._computeTrackEndTime(a);if(d===null||d<t.currentTime+.01)return;let c=d-t.currentTime;if(a.playbackType==="HTML5"&&c>G){this.onDebug(`_tryScheduleGapless: deferring \u2014 HTML5 track ${e} has ${c.toFixed(1)}s remaining (max lookahead=${G}s)`);return}if(!i.scheduleGaplessStart(d)){this.onDebug(`_tryScheduleGapless: track ${r} rejected SCHEDULE_GAPLESS (state=${i.machineState})`);return}a.playbackType==="HTML5"&&a.scheduleHtml5Mute(d),this.onDebug(`_tryScheduleGapless: scheduled track ${r} at endTime=${d.toFixed(3)} (in ${(d-t.currentTime).toFixed(1)}s) curPlaybackType=${a.playbackType}`),this._scheduledNextIndex=r}_computeTrackEndTime(e){let t=k();if(!t||!e.isBufferLoaded)return null;let r=e.playbackEndContextTime;if(r!==null)return r>t.currentTime?r:null;let a=e.duration;if(isNaN(a))return null;let i=(a-e.currentTime)/this._playbackRate;return i<=0?null:t.currentTime+i}_startMediaSessionAnchor(){typeof Audio>"u"||(this._mediaSessionAnchor||(this._mediaSessionAnchor=new Audio(ee()),this._mediaSessionAnchor.loop=!0),this._mediaSessionAnchor.paused&&this._mediaSessionAnchor.play().catch(()=>{}))}_stopMediaSessionAnchor(){this._mediaSessionAnchor&&!this._mediaSessionAnchor.paused&&this._mediaSessionAnchor.pause()}};export{v as Queue,v as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|