Documentation
¶
Overview ¶
Package spotify integrates Spotify playback into cliamp via go-librespot.
Index ¶
- Constants
- func CredsPath() (string, error)
- func DeleteCreds() (bool, error)
- func SetAuthURLObserver(fn func(string))
- type Session
- type SpotifyProvider
- func (p *SpotifyProvider) AddTrackToPlaylist(ctx context.Context, playlistID string, track playlist.Track) error
- func (p *SpotifyProvider) Authenticate() error
- func (p *SpotifyProvider) Close()
- func (p *SpotifyProvider) CreatePlaylist(ctx context.Context, name string) (string, error)
- func (p *SpotifyProvider) Name() string
- func (p *SpotifyProvider) NewStreamer(uri string) (beep.StreamSeekCloser, beep.Format, time.Duration, error)
- func (p *SpotifyProvider) Playlists() ([]playlist.PlaylistInfo, error)
- func (p *SpotifyProvider) SearchTracks(ctx context.Context, query string, limit int) ([]playlist.Track, error)
- func (p *SpotifyProvider) Tracks(playlistID string) ([]playlist.Track, error)
- func (p *SpotifyProvider) URISchemes() []string
Constants ¶
const CallbackPort = 19872
CallbackPort is the fixed port for the OAuth2 callback server. Must match the redirect URI registered in the Spotify Developer app.
const DefaultClientID = "65b708073fc0480ea92a077233ca87bd"
DefaultClientID is the librespot keymaster client_id, shared by spotify-player and other librespot-based players. Used when the user hasn't configured their own client_id — Spotify's loopback exception lets it work with any 127.0.0.1 port, and it predates the Nov 27, 2024 dev-mode quota restriction so /v1/search and other catalog endpoints stay accessible.
Variables ¶
This section is empty.
Functions ¶
func DeleteCreds ¶
DeleteCreds removes the stored Spotify credentials file. Returns true if a file was removed, false if it did not exist.
func SetAuthURLObserver ¶
func SetAuthURLObserver(fn func(string))
SetAuthURLObserver registers a callback invoked once with the OAuth URL at the start of an interactive sign-in. Pass nil to remove.
Types ¶
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session manages a go-librespot session and player for Spotify integration.
func NewSession ¶
NewSession creates a go-librespot session, using stored credentials if available, otherwise starting an interactive OAuth2 flow. clientID is the Spotify Developer app client ID for Web API access.
func NewSessionSilent ¶
NewSessionSilent is like NewSession but only uses stored credentials. Returns an error if interactive auth is required.
func (*Session) NewStream ¶
func (s *Session) NewStream(ctx context.Context, spotID librespot.SpotifyId, bitrate int) (*librespotPlayer.Stream, error)
NewStream creates a decoded audio stream for the given Spotify track ID.
Holds s.mu.RLock() across the librespot network call. Multiple concurrent NewStream / webApi callers can run in parallel (RLock is shared), so rapid track skipping does not serialize. reconnect() and Close() take the full Lock and will wait for in-flight callers to finish before tearing down the player — without this, the swap could call oldPlayer.Close() while we are still reading from it.
type SpotifyProvider ¶
type SpotifyProvider struct {
// contains filtered or unexported fields
}
func New ¶
func New(session *Session, clientID string, bitrate int) *SpotifyProvider
New creates a SpotifyProvider. If session is nil, authentication is deferred until the user first selects the Spotify provider. bitrate sets the preferred Spotify stream quality in kbps (96, 160, or 320).
func (*SpotifyProvider) AddTrackToPlaylist ¶
func (p *SpotifyProvider) AddTrackToPlaylist(ctx context.Context, playlistID string, track playlist.Track) error
AddTrackToPlaylist adds a track to an existing Spotify playlist. The track's Path is used as the Spotify URI (e.g. "spotify:track:..." or "spotify:episode:..."); the Spotify API accepts either. Implements provider.PlaylistWriter.
func (*SpotifyProvider) Authenticate ¶
func (p *SpotifyProvider) Authenticate() error
Authenticate runs the interactive sign-in flow (opens browser, waits for callback). Any previous in-progress OAuth flow is cancelled first to free the callback port.
func (*SpotifyProvider) Close ¶
func (p *SpotifyProvider) Close()
Close releases the session if one was created.
func (*SpotifyProvider) CreatePlaylist ¶
CreatePlaylist creates a new private Spotify playlist and returns its ID.
func (*SpotifyProvider) Name ¶
func (p *SpotifyProvider) Name() string
func (*SpotifyProvider) NewStreamer ¶
func (p *SpotifyProvider) NewStreamer(uri string) (beep.StreamSeekCloser, beep.Format, time.Duration, error)
NewStreamer creates a SpotifyStreamer for the given spotify: URI (track or episode). If the stream fails due to an auth error (e.g. expired session, AES key rejection), the player tries a silent reconnect from cached credentials. If that fails — or the retry still hits an auth error — the streamer surfaces playlist.ErrNeedsAuth so the UI can prompt the user to sign in. We deliberately do NOT auto-launch a browser-based OAuth flow from this path: rapid track skipping can produce transient stream errors and a browser tab popping up mid-skip.
Implements provider.CustomStreamer.
func (*SpotifyProvider) Playlists ¶
func (p *SpotifyProvider) Playlists() ([]playlist.PlaylistInfo, error)
Playlists returns the authenticated user's Spotify playlists. Only playlists owned by the user or marked as collaborative are returned; playlists saved from other users are excluded because the Spotify API returns 403 when trying to list their tracks.
func (*SpotifyProvider) SearchTracks ¶
func (p *SpotifyProvider) SearchTracks(ctx context.Context, query string, limit int) ([]playlist.Track, error)
SearchTracks searches Spotify for tracks and podcast episodes, returning up to limit results of each. Episodes (e.g. podcasts) are routed through their spotify:episode: URI so they play correctly. limit is clamped to Spotify's accepted range of 1..50.
func (*SpotifyProvider) Tracks ¶
func (p *SpotifyProvider) Tracks(playlistID string) ([]playlist.Track, error)
Tracks returns all tracks for the given Spotify playlist ID. Track.Path is set to the canonical spotify: URI for the player to resolve. Results are cached by snapshot_id; unchanged playlists skip the API call.
func (*SpotifyProvider) URISchemes ¶
func (p *SpotifyProvider) URISchemes() []string
URISchemes returns the URI prefixes handled by this provider. Implements provider.CustomStreamer.