diff --git a/backend/audiocache.go b/backend/audiocache.go index fb5ba4a..48e0af6 100644 --- a/backend/audiocache.go +++ b/backend/audiocache.go @@ -100,7 +100,7 @@ func (a *AudioCache) cacheFile(id, dlURL string) { e.done = true } a.mutex.Unlock() - } else if err != context.DeadlineExceeded { + } else if err != nil && err != context.DeadlineExceeded { log.Printf("error downloading audio file: %v", err) } cancel() // release ctx resources when done @@ -120,9 +120,9 @@ func (a *AudioCache) CacheOnly(keep string, fetch []AudioCacheRequest) { return a.ID == id }) { _ = e - //e.cancel() - //_ = os.Remove(a.pathForID(id)) - //delete(a.entries, id) + e.cancel() + _ = os.Remove(a.pathForID(id)) + delete(a.entries, id) } } diff --git a/backend/playbackengine.go b/backend/playbackengine.go index 1d5b109..5c55dd7 100644 --- a/backend/playbackengine.go +++ b/backend/playbackengine.go @@ -584,7 +584,6 @@ func (p *playbackEngine) cacheNextTracks() { id = np.Metadata().ID } p.audiocache.CacheOnly(id, fetch) - log.Println("fetching files", sharedutil.MapSlice(fetch, func(a AudioCacheRequest) string { return a.ID })) } } @@ -685,7 +684,6 @@ func (p *playbackEngine) setTrack(idx int, next bool, startTime float64) error { if isTrack && p.audiocache != nil { if filepath := p.audiocache.PathForCachedFile(track.ID); filepath != "" { url = filepath - log.Println("playing file from cache") } } if url == "" { diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 67360c2..b1a3fa8 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -84,34 +84,44 @@ func (p *PlaybackManager) addOnTrackChangeHook() { p.lastPlayTime = curTime }) - var curWaveformJob *WaveformImageJob - var nextWaveformJob *WaveformImageJob - var refreshCancel context.CancelFunc + var waveformJobs [3]*WaveformImageJob + findJob := func(id string) (*WaveformImageJob, bool) { + for _, j := range waveformJobs { + if j != nil && j.ItemID == id { + return j, true + } + } + return nil, false + } + addJob := func(job *WaveformImageJob) { + waveformJobs[0].Cancel() + waveformJobs[0] = waveformJobs[1] + waveformJobs[1] = waveformJobs[2] + waveformJobs[2] = job + } p.engine.onBeforeSongChange = append(p.engine.onBeforeSongChange, func(item mediaprovider.MediaItem) { if p.wfmGen != nil && item != nil && item.Metadata().Type == mediaprovider.MediaItemTypeTrack { - log.Println("preparing waveform image for next track ", item.Metadata().ID) - id := item.Metadata().ID - _ = p.cache.PathForCachedOrDownloadingFile(id) - - curWaveformJob.Cancel() - curWaveformJob = nextWaveformJob - nextWaveformJob = p.wfmGen.StartWaveformGeneration(item.(*mediaprovider.Track)) + // start generating waveform image for next-up track + addJob(p.wfmGen.StartWaveformGeneration(item.(*mediaprovider.Track))) } }) + lastPlayingID := "" + var wfmImageUpdateCancel context.CancelFunc + p.OnSongChange(func(item mediaprovider.MediaItem, _ *mediaprovider.Track) { // Autoplay if enabled and we are on the last track if p.autoplay && p.NowPlayingIndex() == len(p.engine.playQueue)-1 { p.enqueueAutoplayTracks() } - if refreshCancel != nil { - refreshCancel() + if wfmImageUpdateCancel != nil { + wfmImageUpdateCancel() } updateUnfinishedJob := func(job *WaveformImageJob) { ctx, c := context.WithCancel(p.cache.rootCtx) - refreshCancel = c + wfmImageUpdateCancel = c go func(ctx context.Context, job *WaveformImageJob) { for { time.Sleep(333 * time.Millisecond) @@ -132,24 +142,27 @@ func (p *PlaybackManager) addOnTrackChangeHook() { } if item != nil { - log.Println("Playing track ", item.Metadata().ID) - var im *WaveformImage - done := false - if nextWaveformJob.ItemID == item.Metadata().ID { - log.Println("Have waveform in progress for", item.Metadata().ID) - done = nextWaveformJob.Done() - im = nextWaveformJob.Get() + // cancel possible waveform generation job for previous track + if old, ok := findJob(lastPlayingID); ok { + old.Cancel() } - if im != nil { - for _, cb := range p.onWaveformImgUpdate { - cb(im) - } - if !done { - updateUnfinishedJob(nextWaveformJob) - } + lastPlayingID = item.Metadata().ID + + var job *WaveformImageJob + if j, ok := findJob(item.Metadata().ID); ok { + job = j } else if tr, ok := item.(*mediaprovider.Track); ok { - curWaveformJob = p.wfmGen.StartWaveformGeneration(tr) - updateUnfinishedJob(curWaveformJob) + job = p.wfmGen.StartWaveformGeneration(tr) + addJob(job) + } + if job != nil { + img := job.Get() + for _, cb := range p.onWaveformImgUpdate { + cb(img) + } + if !job.done && job != nil { + updateUnfinishedJob(job) + } } } diff --git a/backend/waveformimage.go b/backend/waveformimage.go index 2f46bef..30aec38 100644 --- a/backend/waveformimage.go +++ b/backend/waveformimage.go @@ -64,7 +64,6 @@ func (w *WaveformImageJob) Err() error { func (w *WaveformImageJob) Get() *WaveformImage { if w.Done() { - log.Println("returning image directly") return w.img } // return a new *WaveformImage with data copied @@ -143,7 +142,6 @@ func (w *WaveformImageGenerator) StartWaveformGeneration(item *mediaprovider.Tra path = srv.Addr() - log.Println("streaming file to MPV at ", path) go srv.Serve() time.Sleep(10 * time.Millisecond) // make sure server has time to come up } @@ -155,7 +153,6 @@ func (w *WaveformImageGenerator) StartWaveformGeneration(item *mediaprovider.Tra err := convertToWav(ctx, path, transcodeFile) wavConvertDone = true if err != nil { - log.Println("Error converting to wav", err) job.setError(err) } }() @@ -178,7 +175,6 @@ func (w *WaveformImageGenerator) StartWaveformGeneration(item *mediaprovider.Tra go func() { err := analyzeWavFile(ctx, transcodeFile, data, item.Duration.Milliseconds(), func() bool { return wavConvertDone }) if err != nil { - log.Println("error analyzing wav", err.Error()) job.setError(err) } data.done = true @@ -249,7 +245,6 @@ func generateWaveformImage(ctx context.Context, data *waveformData, job *Wavefor func analyzeWavFile(ctx context.Context, transcodeFile string, data *waveformData, millisecs int64, fileDone func() bool) error { f, err := os.Open(transcodeFile) if err != nil { - log.Println("error opening transcoded file") return err } defer f.Close() @@ -409,6 +404,8 @@ func convertToWav(ctx context.Context, inPath, outPath string) error { return err } + defer m.TerminateDestroy() + m.Command([]string{"loadfile", inPath, "replace"}) // Wait for MPV idle or ctx expiry