App-MHFS
view release on metacpan or search on metacpan
share/public_html/static/music_worklet_inprogress/player/mhfsplayer.js view on Meta::CPAN
// open the track in the decoder and seek to where we want to start decoding if necessary
const start_output_time = time;
const pbtrack = {
'track' : track,
'skiptime' : start_output_time,
'sampleCount' : 0,
'startedLoading' : 1
};
that.AudioQueue.push(pbtrack)
time = 0;
try {
const md = await decoder.openTrack(mysignal, track.md, start_output_time);
if(md) {
track.md.duration ??= md.duration;
track.md.mediametadata ??= md.mediametadata;
}
}
catch(error) {
pbtrack.startedLoading = undefined;
pbtrack.donedecode = 1;
pbtrack.queued = 1;
console.error(error);
if(mysignal.aborted) {
break;
}
if(firstFailedTrack === track) {
console.error("FAQ done, encountered same track failing again");
break;
}
firstFailedTrack ||= track;
continue;
}
firstFailedTrack = undefined;
// We better not modify the AQ if we're cancelled
if(mysignal.aborted) break;
// art
LoadTrackArt(track, decoder.track);
// decode the track
const todec = that.ac.sampleRate;
SAMPLELOOP: while(1) {
// yield so buffers can be queued
if(pbtrack.sampleCount > 0) {
if(!(await abortablesleep_status(0, mysignal)))
{
break TRACKLOOP;
}
}
// wait for there to be space
while(that.decoderdatawriter.getspace() < that.ac.sampleRate) {
if(!(await abortablesleep_status(250, mysignal)))
{
break TRACKLOOP;
}
}
// decode
let decdata;
try {
decdata = await decoder.read_pcm_frames_f32_arrs(todec, mysignal);
pbtrack.startedLoading = undefined;
if(!decdata) break SAMPLELOOP;
}
catch(error) {
console.error(error);
if(mysignal.aborted) {
break TRACKLOOP;
}
await decoder.closeCurrentTrack();
break SAMPLELOOP;
}
// We better not modify the AQ if we're cancelled
if(mysignal.aborted) break TRACKLOOP;
pbtrack.sampleCount += decdata.length;
that.decoderdatawriter.write(decdata.chanData);
// break out at end
if(decdata.length < todec) {
break SAMPLELOOP;
}
}
pbtrack.donedecode = 1;
pbtrack.queued = (pbtrack.sampleCount === 0);
}
decoder.flush();
unlock();
that.QState = that.STATES.NEED_FAQ;
}
let FAQPromise;
const StartQueue = function(track, time) {
FAQPromise = fillAudioQueue(track, time);
};
const StopQueue = async function() {
that.FACAbortController.abort();
await FAQPromise;
}
that.StartQueue = StartQueue;
that.StopQueue = StopQueue;
// Main playlist queuing. must be done when holding the USERMUTEX
that.USERMUTEX = new Mutex();
const Track = function(trackname) {
that.trackdb[trackname] ??= {'trackname' : trackname, 'url' : that.gui.geturl(trackname)}
return { md : that.trackdb[trackname]};
};
that._queuetracks = function(tracknames, after) {
// build a linked list of tracks to append
const HEAD = Track(tracknames[0]);
let TAIL = HEAD;
for(let i = 1; i < tracknames.length; i++) {
const track = Track(tracknames[i]);
TAIL.next = track;
track.prev = TAIL;
TAIL = track;
}
// add the linked list to the queue linked list
after = after || that.Tracks_TAIL;
if(after) {
if(after.next) {
TAIL.next = after.next;
after.next.prev = TAIL;
}
else {
that.Tracks_TAIL = TAIL;
}
after.next = HEAD;
HEAD.prev = after;
}
else {
that.Tracks_HEAD = HEAD;
that.Tracks_TAIL = TAIL;
}
( run in 1.452 second using v1.01-cache-2.11-cpan-39bf76dae61 )