From e7b2b821f3ee77017d42224768e9608c1d6012d1 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Thu, 16 May 2024 19:22:08 -0700 Subject: [PATCH] hook up seek for synced lyrics --- backend/playbackengine.go | 16 ++++++++-------- backend/playbackmanager.go | 2 +- ui/bottompanel.go | 2 +- ui/browsing/browsingpane.go | 6 +++--- ui/browsing/nowplayingpage.go | 8 ++++++-- ui/widgets/lyricsviewer.go | 7 +++++++ 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/backend/playbackengine.go b/backend/playbackengine.go index 3cb61ac..3a089d4 100644 --- a/backend/playbackengine.go +++ b/backend/playbackengine.go @@ -61,7 +61,7 @@ type playbackEngine struct { // registered callbacks onSongChange []func(nowPlaying, justScrobbledIfAny *mediaprovider.Track) - onPlayTimeUpdate []func(float64, float64) + onPlayTimeUpdate []func(float64, float64, bool) onLoopModeChange []func(LoopMode) onVolumeChange []func(int) onSeek []func() @@ -92,7 +92,7 @@ func NewPlaybackEngine( } p.OnTrackChange(pm.handleOnTrackChange) p.OnSeek(func() { - pm.doUpdateTimePos() + pm.doUpdateTimePos(true) pm.invokeNoArgCallbacks(pm.onSeek) }) p.OnStopped(pm.handleOnStopped) @@ -239,7 +239,7 @@ func (p *playbackEngine) LoadTracks(tracks []*mediaprovider.Track, insertQueueMo func (p *playbackEngine) StopAndClearPlayQueue() { changed := len(p.playQueue) > 0 p.player.Stop() - p.doUpdateTimePos() + p.doUpdateTimePos(false) p.playQueue = nil p.nowPlayingIdx = -1 if changed { @@ -399,7 +399,7 @@ func (p *playbackEngine) handleOnTrackChange() { p.curTrackTime = float64(p.playQueue[p.nowPlayingIdx].Duration) p.sendNowPlayingScrobble() // Must come before invokeOnChangeCallbacks b/c track may immediately be scrobbled p.invokeOnSongChangeCallbacks() - p.doUpdateTimePos() + p.doUpdateTimePos(false) p.setNextTrackBasedOnLoopMode(false) } @@ -407,7 +407,7 @@ func (p *playbackEngine) handleOnStopped() { p.playTimeStopwatch.Stop() p.checkScrobble() p.stopPollTimePos() - p.doUpdateTimePos() + p.doUpdateTimePos(false) p.invokeOnSongChangeCallbacks() p.invokeNoArgCallbacks(p.onStopped) p.wasStopped = true @@ -568,7 +568,7 @@ func (p *playbackEngine) startPollTimePos() { pollingTick.Stop() return case <-pollingTick.C: - p.doUpdateTimePos() + p.doUpdateTimePos(false) } } }() @@ -581,7 +581,7 @@ func (p *playbackEngine) stopPollTimePos() { } } -func (p *playbackEngine) doUpdateTimePos() { +func (p *playbackEngine) doUpdateTimePos(seeked bool) { if p.callbacksDisabled { return } @@ -590,6 +590,6 @@ func (p *playbackEngine) doUpdateTimePos() { p.latestTrackPosition = s.TimePos } for _, cb := range p.onPlayTimeUpdate { - cb(s.TimePos, s.Duration) + cb(s.TimePos, s.Duration, seeked) } } diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 4f577c2..2fdab18 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -60,7 +60,7 @@ func (p *PlaybackManager) OnSongChange(cb func(nowPlaying *mediaprovider.Track, } // Registers a callback that is notified whenever the play time should be updated. -func (p *PlaybackManager) OnPlayTimeUpdate(cb func(float64, float64)) { +func (p *PlaybackManager) OnPlayTimeUpdate(cb func(curTime float64, totalTime float64, seeked bool)) { p.engine.onPlayTimeUpdate = append(p.engine.onPlayTimeUpdate, cb) } diff --git a/ui/bottompanel.go b/ui/bottompanel.go index 1f2b9c1..7af0d53 100644 --- a/ui/bottompanel.go +++ b/ui/bottompanel.go @@ -35,7 +35,7 @@ func NewBottomPanel(pm *backend.PlaybackManager, contr *controller.Controller) * bp.ExtendBaseWidget(bp) pm.OnSongChange(bp.onSongChange) - pm.OnPlayTimeUpdate(func(cur, total float64) { + pm.OnPlayTimeUpdate(func(cur, total float64, _ bool) { if !pm.IsSeeking() { bp.Controls.UpdatePlayTime(cur, total) } diff --git a/ui/browsing/browsingpane.go b/ui/browsing/browsingpane.go index 15098ce..347941c 100644 --- a/ui/browsing/browsingpane.go +++ b/ui/browsing/browsingpane.go @@ -46,7 +46,7 @@ type CanShowNowPlaying interface { } type CanShowPlayTime interface { - OnPlayTimeUpdate(curTime, totalTime float64) + OnPlayTimeUpdate(curTime, totalTime float64, seeked bool) } type CanShowPlayQueue interface { @@ -222,12 +222,12 @@ func (b *BrowsingPane) onSongChange(song, lastScrobbledIfAny *mediaprovider.Trac } } -func (b *BrowsingPane) onPlayTimeUpdate(cur, total float64) { +func (b *BrowsingPane) onPlayTimeUpdate(cur, total float64, seeked bool) { if b.curPage == nil { return } if p, ok := b.curPage.(CanShowPlayTime); ok { - p.OnPlayTimeUpdate(cur, total) + p.OnPlayTimeUpdate(cur, total, seeked) } } diff --git a/ui/browsing/nowplayingpage.go b/ui/browsing/nowplayingpage.go index c3a9ea5..7c2f95a 100644 --- a/ui/browsing/nowplayingpage.go +++ b/ui/browsing/nowplayingpage.go @@ -241,9 +241,13 @@ func (s *nowPlayingPageState) Restore() Page { var _ CanShowPlayTime = (*NowPlayingPage)(nil) -func (a *NowPlayingPage) OnPlayTimeUpdate(curTime, _ float64) { +func (a *NowPlayingPage) OnPlayTimeUpdate(curTime, _ float64, seeked bool) { a.formatStatusLine() - a.lyricsViewer.UpdatePlayPos(curTime) + if seeked { + a.lyricsViewer.OnSeeked(curTime) + } else { + a.lyricsViewer.UpdatePlayPos(curTime) + } } var _ CanSelectAll = (*NowPlayingPage)(nil) diff --git a/ui/widgets/lyricsviewer.go b/ui/widgets/lyricsviewer.go index 7d7c09f..4df1796 100644 --- a/ui/widgets/lyricsviewer.go +++ b/ui/widgets/lyricsviewer.go @@ -15,6 +15,7 @@ type LyricsViewer struct { viewer *fynelyrics.LyricsViewer lyrics *mediaprovider.Lyrics nextLyricLine int + lastPlayPos float64 container *fyne.Container isEmpty bool @@ -61,6 +62,11 @@ func (l *LyricsViewer) UpdatePlayPos(timeSecs float64) { if l.lyrics == nil || !l.lyrics.Synced { return } + if timeSecs < l.lastPlayPos { + l.OnSeeked(timeSecs) + return + } + l.lastPlayPos = timeSecs // advance if needed if l.lyrics.Lines[l.nextLyricLine].Start <= timeSecs { l.viewer.NextLine() @@ -71,6 +77,7 @@ func (l *LyricsViewer) UpdatePlayPos(timeSecs float64) { } func (l *LyricsViewer) OnSeeked(timeSecs float64) { + l.lastPlayPos = timeSecs if l.lyrics == nil || !l.lyrics.Synced { return }