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 )