From 61a04e86b58f0171927785709dff42398650044b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sat, 1 Nov 2025 11:26:49 -0700 Subject: [PATCH] add new lyricsmanager missed in last commit --- backend/lyricsmanager.go | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 backend/lyricsmanager.go diff --git a/backend/lyricsmanager.go b/backend/lyricsmanager.go new file mode 100644 index 0000000..1da38df --- /dev/null +++ b/backend/lyricsmanager.go @@ -0,0 +1,75 @@ +package backend + +import ( + "context" + "log" + "sync" + + "github.com/dweymouth/supersonic/backend/mediaprovider" +) + +type LyricsManager struct { + sm *ServerManager + lrclib *LrcLibFetcher + + // right now only one song can have lyrics being fetched + // at any given time (b/c we only show lyrics for the currently playing song) + lock sync.Mutex + fetchInProgressID string + fetchInProgressCancel context.CancelFunc + cbs []func(string, *mediaprovider.Lyrics) +} + +func NewLyricsManager(sm *ServerManager, lrclib *LrcLibFetcher) *LyricsManager { + return &LyricsManager{ + sm: sm, + lrclib: lrclib, + } +} + +func (lm *LyricsManager) FetchLyricsAsync(song *mediaprovider.Track, cb func(string, *mediaprovider.Lyrics)) { + lm.lock.Lock() + defer lm.lock.Unlock() + + if lm.fetchInProgressID == song.ID { + lm.cbs = append(lm.cbs, cb) + return + } + lm.fetchInProgressID = song.ID + + if lm.fetchInProgressCancel != nil { + lm.fetchInProgressCancel() + } + lm.cbs = []func(string, *mediaprovider.Lyrics){cb} + ctx, cancel := context.WithCancel(context.Background()) + lm.fetchInProgressCancel = cancel + go lm.fetchLyrics(ctx, song, func(id string, lyrics *mediaprovider.Lyrics) { + lm.lock.Lock() + defer lm.lock.Unlock() + for _, cb := range lm.cbs { + cb(id, lyrics) + } + }) +} + +func (lm *LyricsManager) fetchLyrics(ctx context.Context, song *mediaprovider.Track, cb func(string, *mediaprovider.Lyrics)) { + var lyrics *mediaprovider.Lyrics + var err error + if lp, ok := lm.sm.Server.(mediaprovider.LyricsProvider); ok { + if lyrics, err = lp.GetLyrics(song); err != nil { + log.Printf("Error fetching lyrics: %v", err) + } + } + if lyrics == nil && lm.lrclib != nil { + lyrics, err = lm.lrclib.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: + cb(song.ID, lyrics) + } +}