add LyricsProvider / GetLyrics
This commit is contained in:
@@ -154,6 +154,10 @@ type SupportsSharing interface {
|
||||
CanShareArtists() bool
|
||||
}
|
||||
|
||||
type LyricsProvider interface {
|
||||
GetLyrics(track *Track) (*Lyrics, error)
|
||||
}
|
||||
|
||||
type JukeboxProvider interface {
|
||||
JukeboxStart() error
|
||||
JukeboxStop() error
|
||||
|
||||
@@ -120,6 +120,18 @@ type PlaylistWithTracks struct {
|
||||
Tracks []*Track
|
||||
}
|
||||
|
||||
type Lyrics struct {
|
||||
Title string
|
||||
Artist string
|
||||
Synced bool
|
||||
Lines []LyricLine
|
||||
}
|
||||
|
||||
type LyricLine struct {
|
||||
Text string
|
||||
Start float64 // seconds
|
||||
}
|
||||
|
||||
type ContentType int
|
||||
|
||||
const (
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"net/url"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -345,6 +346,53 @@ func (s *subsonicMediaProvider) RescanLibrary() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// LyricsProvider interface
|
||||
var _ mediaprovider.LyricsProvider = (*subsonicMediaProvider)(nil)
|
||||
|
||||
func (s *subsonicMediaProvider) GetLyrics(track *mediaprovider.Track) (*mediaprovider.Lyrics, error) {
|
||||
ext, err := s.client.GetOpenSubsonicExtensions()
|
||||
supportsSynced := err == nil &&
|
||||
slices.ContainsFunc(ext, func(ext *subsonic.OpenSubsonicExtension) bool {
|
||||
return ext.Name == subsonic.SongLyricsExtension
|
||||
})
|
||||
if supportsSynced {
|
||||
lyrics, err := s.client.GetLyricsBySongId(track.ID)
|
||||
if err != nil || len(lyrics.StructuredLyrics) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
lyric := lyrics.StructuredLyrics[0]
|
||||
mpLyrics := &mediaprovider.Lyrics{
|
||||
Title: lyric.DisplayTitle,
|
||||
Artist: lyric.DisplayArtist,
|
||||
Synced: lyric.Synced,
|
||||
}
|
||||
for _, line := range lyric.Lines {
|
||||
mpLyrics.Lines = append(mpLyrics.Lines, mediaprovider.LyricLine{
|
||||
Text: line.Text,
|
||||
Start: float64(line.Start) / 1000,
|
||||
})
|
||||
}
|
||||
return mpLyrics, nil
|
||||
}
|
||||
// fallback to legacy getLyrics endpoint
|
||||
lyrics, err := s.client.GetLyrics(track.Name, track.ArtistNames[0])
|
||||
if err != nil || lyrics == nil || lyrics.Text == "" {
|
||||
return nil, err
|
||||
}
|
||||
mpLyrics := &mediaprovider.Lyrics{
|
||||
Title: lyrics.Title,
|
||||
Artist: lyrics.Artist,
|
||||
Synced: false,
|
||||
}
|
||||
lines := strings.Split(lyrics.Text, "\n")
|
||||
for _, line := range lines {
|
||||
mpLyrics.Lines = append(mpLyrics.Lines, mediaprovider.LyricLine{
|
||||
Text: line,
|
||||
})
|
||||
}
|
||||
return mpLyrics, nil
|
||||
}
|
||||
|
||||
func toTrack(ch *subsonic.Child) *mediaprovider.Track {
|
||||
if ch == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user