Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions cmd/pipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ var pipeCmd = &cobra.Command{
if err != nil {
return fmt.Errorf("couldn't load config: %w", err)
}
player, err := loadPlayer(conf)
players, err := loadPlayers(conf)
if err != nil {
return fmt.Errorf("couldn't load player: %w", err)
return fmt.Errorf("couldn't load players: %w", err)
}
provider, err := loadProvider(conf, player)
provider, err := loadProvider(conf)
if err != nil {
return fmt.Errorf("couldn't load provider: %w", err)
}

ch := make(chan pool.Update)
go pool.Listen(player, provider, conf, ch)
go pool.Listen(players, provider, conf, ch)

for update := range ch {
printUpdate(update, conf)
Expand Down
44 changes: 23 additions & 21 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sptlrx/lyrics"
"sptlrx/player"
"sptlrx/pool"
"sptlrx/services/combo"
"sptlrx/services/hosted"
"sptlrx/services/local"
"sptlrx/services/spotify"
Expand Down Expand Up @@ -35,7 +36,6 @@ const help = ` 1. Open your browser.

var (
FlagCookie string
FlagPlayer string
FlagConfig string

FlagStyleBefore string
Expand All @@ -58,17 +58,17 @@ var rootCmd = &cobra.Command{
if err != nil {
return fmt.Errorf("couldn't load config: %w", err)
}
player, err := loadPlayer(conf)
players, err := loadPlayers(conf)
if err != nil {
return fmt.Errorf("couldn't load player: %w", err)
}
provider, err := loadProvider(conf, player)
provider, err := loadProvider(conf)
if err != nil {
return fmt.Errorf("couldn't load provider: %w", err)
}

ch := make(chan pool.Update)
go pool.Listen(player, provider, conf, ch)
go pool.Listen(players, provider, conf, ch)

_, err = tea.NewProgram(
&ui.Model{
Expand Down Expand Up @@ -109,9 +109,6 @@ func loadConfig(cmd *cobra.Command) (*config.Config, error) {
conf.IgnoreErrors = false
}

if cmd.Flags().Changed("player") {
conf.Player = FlagPlayer
}
if cmd.Flags().Changed("before") {
conf.Style.Before = parseStyleFlag(FlagStyleBefore)
}
Expand All @@ -127,31 +124,37 @@ func loadConfig(cmd *cobra.Command) (*config.Config, error) {
return conf, nil
}

func loadPlayer(conf *config.Config) (player.Player, error) {
player, err := config.GetPlayer(conf)
func loadPlayers(conf *config.Config) ([]*player.Player, error) {
players, err := config.GetPlayers(conf)
if err != nil {
if errors.Is(err, spotify.ErrInvalidCookie) {
fmt.Println("If you want to use Spotify as your player, you need to set up your cookie.")
fmt.Println(help)
}
return nil, err
}
return player, nil
return players, nil
}

func loadProvider(conf *config.Config, player player.Player) (lyrics.Provider, error) {
if conf.Local.Folder != "" {
return local.New(conf.Local.Folder)
}
func loadProvider(conf *config.Config) (lyrics.Provider, error) {
providers := []lyrics.Provider{}

if conf.Cookie == "" {
return hosted.New(conf.Host), nil

coovieProv := hosted.New(conf.Host)
providers = append(providers, coovieProv)
} else {
var s, _ = spotify.NewProvider(conf.Cookie)
providers = append(providers, s)
}
if spt, ok := player.(*spotify.Client); ok {
// use existing spotify client
return spt, nil
if conf.Local.Folder != "" {
localProv, err := local.New(conf.Local.Folder)
if err == nil {
providers = append(providers, localProv)
}
// return local.New(conf.Local.Folder)
}
// create new spotify client
return spotify.New(conf.Cookie)
return combo.New(providers)
}

func parseStyleFlag(value string) config.Style {
Expand Down Expand Up @@ -183,7 +186,6 @@ func parseStyleFlag(value string) config.Style {

func init() {
rootCmd.PersistentFlags().StringVarP(&FlagCookie, "cookie", "c", "", "your cookie")
rootCmd.PersistentFlags().StringVarP(&FlagPlayer, "player", "p", "spotify", "what player to use")
rootCmd.PersistentFlags().StringVar(&FlagConfig, "config", config.Path, "path to config file")

rootCmd.Flags().StringVar(&FlagStyleBefore, "before", "bold", "style of the lines before the current one")
Expand Down
55 changes: 34 additions & 21 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ func init() {
}

type Config struct {
Cookie string `yaml:"cookie"`
Player string `default:"spotify" yaml:"player"`
Host string `default:"lyricsapi.vercel.app" yaml:"host"`
IgnoreErrors bool `default:"true" yaml:"ignoreErrors"`
TimerInterval int `default:"200" yaml:"timerInterval"`
UpdateInterval int `default:"2000" yaml:"updateInterval"`
Cookie string `yaml:"cookie"`
Players []string `default:"[spotify]" yaml:"players"`
Host string `default:"lyricsapi.vercel.app" yaml:"host"`
IgnoreErrors bool `default:"true" yaml:"ignoreErrors"`
TimerInterval int `default:"200" yaml:"timerInterval"`
UpdateInterval int `default:"2000" yaml:"updateInterval"`

Style struct {
HAlignment string `default:"center" yaml:"hAlignment"`
Expand Down Expand Up @@ -172,19 +172,32 @@ func validateColor(color string) bool {
return false
}

// GetPlayer returns a player based on config values
func GetPlayer(conf *Config) (player.Player, error) {
switch conf.Player {
case "spotify":
return spotify.New(conf.Cookie)
case "mpd":
return mpd.New(conf.Mpd.Address, conf.Mpd.Password), nil
case "mopidy":
return mopidy.New(conf.Mopidy.Address), nil
case "mpris":
return mpris.New(conf.Mpris.Players)
case "browser":
return browser.New(conf.Browser.Port)
}
return nil, fmt.Errorf("unknown player: \"%s\"", conf.Player)
// GetPlayers returns a player based on config values
func GetPlayers(conf *Config) ([]*player.Player, error) {
var players []*player.Player
for _, p := range conf.Players {
os.Stderr.WriteString("LOADR: Processing " + p)
switch p {
case "spotify":
spotifyPlayer, _ := spotify.NewPlayer(conf.Cookie)
players = append(players, &spotifyPlayer)
case "mpd":
mpdPlayer := mpd.New(conf.Mpd.Address, conf.Mpd.Password)
players = append(players, &mpdPlayer)
case "mopidy":
mopidyPlayer := mopidy.New(conf.Mopidy.Address)
players = append(players, &mopidyPlayer)
case "mpris":
mprisPlayer, _ := mpris.New(conf.Mpris.Players)
players = append(players, &mprisPlayer)
case "browser":
browserPlayer, _ := browser.New(conf.Browser.Port)
players = append(players, &browserPlayer)
}
}
if len(players) > 0 {
return players, nil
}

return nil, fmt.Errorf("unknown players: \"%s\"", conf.Players)
}
5 changes: 4 additions & 1 deletion lyrics/lyrics.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package lyrics

import "sptlrx/player"

type Provider interface {
Lyrics(id, query string) ([]Line, error)
Lyrics(state player.State) ([]Line, error)
Name() string
}

type Line struct {
Expand Down
6 changes: 5 additions & 1 deletion player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ type State struct {
// ID of the current track.
ID string
// Query is a string that can be used to find lyrics.
Query string
TrackNumber int
Artist string
Album string
Title string
SongPath string
// Position of the current track in ms.
Position int
// Playing means whether the track is playing at the moment.
Expand Down
14 changes: 9 additions & 5 deletions pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ type Update struct {

// Listen polls for lyrics updates and writes them to the channel.
func Listen(
player player.Player,
players []*player.Player,
provider lyrics.Provider,
conf *config.Config,
ch chan Update,
) {
stateCh := make(chan playerState)
go listenPlayer(player, stateCh, conf.UpdateInterval)
for _, p := range players {
go listenPlayer(*p, stateCh, conf.UpdateInterval)
}

ticker := time.NewTicker(
time.Millisecond * time.Duration(conf.TimerInterval),
Expand All @@ -47,7 +49,7 @@ func Listen(
if newState.ID != state.ID {
changed = true
if newState.ID != "" {
newLines, err := provider.Lyrics(newState.ID, newState.Query)
newLines, err := provider.Lyrics(newState.State)
if err != nil {
state.Err = err
}
Expand Down Expand Up @@ -100,12 +102,14 @@ func listenPlayer(player player.Player, ch chan playerState, interval int) {
st := playerState{Err: err}
if state != nil {
st.ID = state.ID
st.Query = state.Query
st.Album = state.Album
st.Artist = state.Artist
st.Title = state.Title
st.TrackNumber = state.TrackNumber
st.Playing = state.Playing
st.Position = state.Position
}
ch <- st

time.Sleep(time.Millisecond * time.Duration(interval))
}
}
Expand Down
23 changes: 17 additions & 6 deletions services/browser/browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"net"
"net/http"
"os"
"sptlrx/player"
"strconv"
"strings"
Expand All @@ -24,7 +25,7 @@ const (
playing
)

func New(port int) (*Client, error) {
func New(port int) (player.Player, error) {
c := &Client{}
return c, c.start(port)
}
Expand Down Expand Up @@ -73,6 +74,8 @@ func (c *Client) handler(w http.ResponseWriter, r *http.Request) {
if err != nil {
return
}

os.Stderr.WriteString("BRWSR: msg: " + string(msg) + "\n")
if t != websocket.MessageText || len(msg) == 0 {
continue
}
Expand All @@ -81,6 +84,8 @@ func (c *Client) handler(w http.ResponseWriter, r *http.Request) {
}

func (c *Client) processMessage(msg string) {

os.Stderr.WriteString("BRWSR: Recieved message" + "\n")
spaceIndex := strings.IndexByte(msg, ' ')
if spaceIndex == -1 {
return
Expand Down Expand Up @@ -140,21 +145,27 @@ func (c *Client) State() (*player.State, error) {
if c.state == stopped {
return nil, nil
}
os.Stderr.WriteString("BRWSR: Found Song" + "\n")

var query string
var id string
if c.artist != "" {
query = c.artist + " " + c.title
id = c.artist + " " + c.title
} else {
query = c.title
id = c.title
}

os.Stderr.WriteString("BRWSR: Artist" + c.artist + "\n")
os.Stderr.WriteString("BRWSR: Title" + c.title + "\n")
os.Stderr.WriteString("BRWSR: Position" + strconv.Itoa(c.position) + "\n")

position := c.position
if c.state != paused {
position += int(time.Since(c.updateTime).Milliseconds())
}
return &player.State{
ID: query,
Query: query,
ID: id,
Artist: c.artist,
Title: c.title,
Position: position,
Playing: c.state == playing,
}, nil
Expand Down
32 changes: 32 additions & 0 deletions services/combo/combo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package combo

import (
"sptlrx/lyrics"
"sptlrx/player"
)

func New(providers []lyrics.Provider) (*ComboClient, error) {

return &ComboClient{providers: providers}, nil
}

type ComboClient struct {
providers []lyrics.Provider
}

func (c *ComboClient) Lyrics(state player.State) ([]lyrics.Line, error) {
for _, p := range c.providers {
provider := p
newLines, err := provider.Lyrics(state)
if err != nil || newLines == nil {
continue
} else {
return newLines, nil
}
}
return nil, nil
}

func (c *ComboClient) Name() string {
return "COMBO"
}
Loading