diff --git a/backend/app.go b/backend/app.go index 8a5bb2e..e5cf402 100644 --- a/backend/app.go +++ b/backend/app.go @@ -44,6 +44,7 @@ var ( type App struct { Config *Config ServerManager *ServerManager + LyricsManager *LyricsManager ImageManager *ImageManager AudioCache *AudioCache PlaybackManager *PlaybackManager @@ -52,7 +53,6 @@ type App struct { MPRISHandler *MPRISHandler WinSMTC *windows.SMTC ipcServer ipc.IPCServer - LrcLibFetcher *LrcLibFetcher // UI callbacks to be set in main OnReactivate func() @@ -158,10 +158,12 @@ func StartupApp(appName, displayAppName, appVersion, appVersionTag, latestReleas a.ServerManager.SetPrefetchAlbumCoverCallback(func(coverID string) { _, _ = a.ImageManager.GetCoverThumbnail(coverID) }) + var fetch *LrcLibFetcher if a.Config.Application.EnableLrcLib { timeout := time.Duration(a.Config.Application.RequestTimeoutSeconds) * time.Second - a.LrcLibFetcher = NewLrcLibFetcher(a.cacheDir, a.Config.Application.CustomLrcLibUrl, timeout) + fetch = NewLrcLibFetcher(a.cacheDir, a.Config.Application.CustomLrcLibUrl, timeout) } + a.LyricsManager = NewLyricsManager(a.ServerManager, fetch) // Periodically scan for remote players go a.PlaybackManager.ScanRemotePlayers(a.bgrndCtx, true /*fastScan*/) diff --git a/ui/browsing/nowplayingpage.go b/ui/browsing/nowplayingpage.go index 7059d34..82514b6 100644 --- a/ui/browsing/nowplayingpage.go +++ b/ui/browsing/nowplayingpage.go @@ -61,7 +61,6 @@ type NowPlayingPage struct { container *fyne.Container // cancel funcs for background fetch tasks - lyricFetchCancel context.CancelFunc imageLoadCancel context.CancelFunc relatedFetchCancel context.CancelFunc } @@ -72,11 +71,11 @@ type nowPlayingPageState struct { pool *util.WidgetPool sm *backend.ServerManager pm *backend.PlaybackManager + lm *backend.LyricsManager im *backend.ImageManager mp mediaprovider.MediaProvider canRate bool canShare bool - lrcFetch *backend.LrcLibFetcher } func NewNowPlayingPage( @@ -84,15 +83,15 @@ func NewNowPlayingPage( contr *controller.Controller, pool *util.WidgetPool, sm *backend.ServerManager, + lm *backend.LyricsManager, im *backend.ImageManager, pm *backend.PlaybackManager, mp mediaprovider.MediaProvider, canRate bool, canShare bool, - lrcLibFetcher *backend.LrcLibFetcher, ) *NowPlayingPage { state := nowPlayingPageState{ - conf: conf, contr: contr, pool: pool, sm: sm, im: im, pm: pm, mp: mp, canRate: canRate, canShare: canShare, lrcFetch: lrcLibFetcher, + conf: conf, contr: contr, pool: pool, sm: sm, lm: lm, im: im, pm: pm, mp: mp, canRate: canRate, canShare: canShare, } if page, ok := pool.Obtain(util.WidgetTypeNowPlayingPage).(*NowPlayingPage); ok && page != nil { page.nowPlayingPageState = state @@ -336,10 +335,6 @@ func (a *NowPlayingPage) onImageLoaded(img image.Image, err error) { } func (a *NowPlayingPage) updateLyrics() { - if a.lyricFetchCancel != nil { - a.lyricFetchCancel() - } - if a.nowPlayingID == a.curLyricsID { if a.nowPlayingID != "" { // just need to sync the current time @@ -354,8 +349,6 @@ func (a *NowPlayingPage) updateLyrics() { return } a.curLyricsID = a.nowPlayingID - ctx, cancel := context.WithCancel(context.Background()) - a.lyricFetchCancel = cancel a.lyricsLoading.Start() // set the widget to an empty (not nil) lyric during fetch // to keep it from showing "Lyrics not available" @@ -365,27 +358,11 @@ func (a *NowPlayingPage) updateLyrics() { Lines: []mediaprovider.LyricLine{{Text: ""}}, }) tr, _ := a.nowPlaying.(*mediaprovider.Track) - go a.fetchLyrics(ctx, tr) -} -func (a *NowPlayingPage) fetchLyrics(ctx context.Context, song *mediaprovider.Track) { - var lyrics *mediaprovider.Lyrics - var err error - if lp, ok := a.sm.Server.(mediaprovider.LyricsProvider); ok { - if lyrics, err = lp.GetLyrics(song); err != nil { - log.Printf("Error fetching lyrics: %v", err) + a.lm.FetchLyricsAsync(tr, func(id string, lyrics *mediaprovider.Lyrics) { + if id != a.nowPlayingID { + return } - } - if lyrics == nil && a.lrcFetch != nil { - lyrics, err = a.lrcFetch.FetchLrcLibLyrics(song.Title, song.ArtistNames[0], song.Album, int(song.Duration.Seconds())) - if err != nil { - log.Println(err.Error()) - } - } - select { - case <-ctx.Done(): - return - default: fyne.Do(func() { a.lyricsLoading.Stop() a.lyricsViewer.EnableTapToSeek() @@ -395,7 +372,7 @@ func (a *NowPlayingPage) fetchLyrics(ctx context.Context, song *mediaprovider.Tr a.lyricsViewer.OnSeeked(a.lastPlayPos) } }) - } + }) } func (a *NowPlayingPage) updateRelatedList() { @@ -464,7 +441,7 @@ func (a *NowPlayingPage) Reload() { } func (s *nowPlayingPageState) Restore() Page { - return NewNowPlayingPage(s.conf, s.contr, s.pool, s.sm, s.im, s.pm, s.mp, s.canRate, s.canShare, s.lrcFetch) + return NewNowPlayingPage(s.conf, s.contr, s.pool, s.sm, s.lm, s.im, s.pm, s.mp, s.canRate, s.canShare) } var _ CanShowPlayTime = (*NowPlayingPage)(nil) diff --git a/ui/browsing/router.go b/ui/browsing/router.go index 80e631d..601a68f 100644 --- a/ui/browsing/router.go +++ b/ui/browsing/router.go @@ -48,7 +48,7 @@ func (r Router) CreatePage(rte controller.Route) Page { case controller.Genres: return NewGenresPage(r.Controller, r.App.ServerManager.Server) case controller.NowPlaying: - return NewNowPlayingPage(&r.App.Config.NowPlayingConfig, r.Controller, r.widgetPool, r.App.ServerManager, r.App.ImageManager, r.App.PlaybackManager, r.App.ServerManager.Server, canRate, canShare, r.App.LrcLibFetcher) + return NewNowPlayingPage(&r.App.Config.NowPlayingConfig, r.Controller, r.widgetPool, r.App.ServerManager, r.App.LyricsManager, r.App.ImageManager, r.App.PlaybackManager, r.App.ServerManager.Server, canRate, canShare) case controller.Playlist: return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager) case controller.Playlists: