From 3fa52c73df4c6a4a0ad9a8d796acac6d0d110b37 Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Wed, 6 Mar 2024 08:05:53 -0800 Subject: [PATCH] add unsynced lyrics view (not tested yet) --- ui/browsing/nowplayingpage.go | 14 ++++++++++-- ui/browsing/router.go | 4 +--- ui/controller/routes.go | 1 - ui/widgets/lyricsviewer.go | 42 ++++++++++++++++++++++++++++++++--- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/ui/browsing/nowplayingpage.go b/ui/browsing/nowplayingpage.go index 8f9d0ab..b1757b6 100644 --- a/ui/browsing/nowplayingpage.go +++ b/ui/browsing/nowplayingpage.go @@ -46,6 +46,7 @@ type NowPlayingPage struct { type nowPlayingPageState struct { contr *controller.Controller pool *util.WidgetPool + sm *backend.ServerManager pm *backend.PlaybackManager im *backend.ImageManager canRate bool @@ -55,13 +56,14 @@ type nowPlayingPageState struct { func NewNowPlayingPage( contr *controller.Controller, pool *util.WidgetPool, + sm *backend.ServerManager, im *backend.ImageManager, pm *backend.PlaybackManager, canRate bool, canShare bool, ) *NowPlayingPage { a := &NowPlayingPage{nowPlayingPageState: nowPlayingPageState{ - contr: contr, pool: pool, im: im, pm: pm, canRate: canRate, canShare: canShare, + contr: contr, pool: pool, sm: sm, im: im, pm: pm, canRate: canRate, canShare: canShare, }} a.ExtendBaseWidget(a) @@ -181,6 +183,14 @@ func (a *NowPlayingPage) OnSongChange(song, lastScrobbledIfAny *mediaprovider.Tr a.card.SetCoverImage(nil) return } + if lp, ok := a.sm.Server.(mediaprovider.LyricsProvider); ok { + lyrics, err := lp.GetLyrics(song) + if err == nil { + a.lyricsViewer.SetLyrics(lyrics) + } else { + a.lyricsViewer.SetLyrics(nil) + } + } a.imageLoadCancel = a.im.GetFullSizeCoverArtAsync(song.CoverArtID, func(img image.Image, err error) { if err != nil { log.Printf("error loading cover art: %v\n", err) @@ -209,7 +219,7 @@ func (s *nowPlayingPageState) Restore() Page { page.Reload() return page } - return NewNowPlayingPage(s.contr, s.pool, s.im, s.pm, s.canRate, s.canShare) + return NewNowPlayingPage(s.contr, s.pool, s.sm, s.im, s.pm, s.canRate, s.canShare) } var _ CanShowPlayTime = (*NowPlayingPage)(nil) diff --git a/ui/browsing/router.go b/ui/browsing/router.go index c92d2e9..65aa5ed 100644 --- a/ui/browsing/router.go +++ b/ui/browsing/router.go @@ -43,14 +43,12 @@ func (r Router) CreatePage(rte controller.Route) Page { return NewArtistsPage(r.Controller, r.widgetPool, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager) case controller.Favorites: return NewFavoritesPage(&r.App.Config.FavoritesPage, r.widgetPool, r.Controller, r.App.ServerManager.Server, r.App.PlaybackManager, r.App.ImageManager) - case controller.Fullscreen: - return NewNowPlayingPage(r.Controller, r.widgetPool, r.App.ImageManager, r.App.PlaybackManager, canRate, canShare) case controller.Genre: return NewGenrePage(rte.Arg, r.widgetPool, r.Controller, r.App.PlaybackManager, r.App.ServerManager.Server, r.App.ImageManager) case controller.Genres: return NewGenresPage(r.Controller, r.App.ServerManager.Server) case controller.NowPlaying: - return NewNowPlayingPage(r.Controller, r.widgetPool, r.App.ImageManager, r.App.PlaybackManager, canRate, canShare) + return NewNowPlayingPage(r.Controller, r.widgetPool, r.App.ServerManager, r.App.ImageManager, r.App.PlaybackManager, 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: diff --git a/ui/controller/routes.go b/ui/controller/routes.go index a351b8f..dc2255a 100644 --- a/ui/controller/routes.go +++ b/ui/controller/routes.go @@ -8,7 +8,6 @@ const ( Albums Artist Artists - Fullscreen Genre Genres Favorites diff --git a/ui/widgets/lyricsviewer.go b/ui/widgets/lyricsviewer.go index 683771f..d40ea8c 100644 --- a/ui/widgets/lyricsviewer.go +++ b/ui/widgets/lyricsviewer.go @@ -1,15 +1,51 @@ package widgets -import "fyne.io/fyne/v2/widget" +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" + "github.com/dweymouth/supersonic/backend/mediaprovider" +) type LyricsViewer struct { - widget.Label + widget.BaseWidget + + noLyricsLabel widget.Label + unsyncedViewer *widget.RichText + + container *container.Scroll } func NewLyricsViewer() *LyricsViewer { - l := &LyricsViewer{Label: widget.Label{ + l := &LyricsViewer{noLyricsLabel: widget.Label{ Text: "Lyrics not available", }} l.ExtendBaseWidget(l) + l.container = container.NewVScroll(&l.noLyricsLabel) return l } + +func (l *LyricsViewer) SetLyrics(lyrics *mediaprovider.Lyrics) { + if lyrics == nil { + l.container.Content = &l.noLyricsLabel + l.Refresh() + return + } + + if l.unsyncedViewer == nil { + l.unsyncedViewer = widget.NewRichText() + } + l.unsyncedViewer.Segments = l.unsyncedViewer.Segments[:0] + for _, line := range lyrics.Lines { + ts := &widget.TextSegment{Text: line.Text} + ts.Style.Alignment = fyne.TextAlignCenter + ts.Style.Inline = false + l.unsyncedViewer.Segments = append(l.unsyncedViewer.Segments, ts) + } + l.container.Content = l.unsyncedViewer + l.Refresh() +} + +func (l *LyricsViewer) CreateRenderer() fyne.WidgetRenderer { + return widget.NewSimpleRenderer(l.container) +}