Documentation
¶
Overview ¶
Package control exposes playback control + status over a small HTTP/JSON API. It is the shared foundation for remote control (one OpenDeezer client driving another) and the MCP server (an AI agent driving playback). A frontend wires it like the MPRIS bridge: provide a status snapshot func + a set of command callbacks, plus the Deezer client for read-only browse (search/playlists).
Auth has three modes, picked by Config. Credentials are accepted via request HEADERS only (never the query string, which leaks into logs/history):
- Token: a bearer token in "X-OpenDeezer-Token". Strongest.
- Same-account: no token, but a controller must prove it is logged into the SAME Deezer account by sending its OWN Deezer user id in "X-OpenDeezer-Account". A controller learns that id from its own login, not from this server — /whoami deliberately does NOT echo the user id, so a bystander can't read the credential and replay it. Convenience auth for a trusted LAN: the user copies no token; their own devices just connect. The user id is only semi-private, so this is LAN-trust grade, not a secret.
- None: open (only safe bound to localhost).
Mutating endpoints require POST and reject requests carrying a browser Origin header, so a web page the user happens to visit can't drive playback (CSRF). GET /whoami is unauthenticated so a controller can discover the account NAME (not id) and auth mode of a server before connecting.
Index ¶
- type Account
- type Client
- func (c *Client) CycleRepeat() (State, error)
- func (c *Client) Next() (State, error)
- func (c *Client) PlayPause() (State, error)
- func (c *Client) PlayPlaylist(id string) (State, error)
- func (c *Client) PlayTrack(id string) (State, error)
- func (c *Client) Playlists() (json.RawMessage, error)
- func (c *Client) Prev() (State, error)
- func (c *Client) Restart() (State, error)
- func (c *Client) Search(q string) (json.RawMessage, error)
- func (c *Client) Seek(ms int64) (State, error)
- func (c *Client) SetVolume(v float64) (State, error)
- func (c *Client) Status() (State, error)
- func (c *Client) Stop() (State, error)
- func (c *Client) ToggleShuffle() (State, error)
- func (c *Client) Whoami() (Whoami, error)
- type Commands
- type Config
- type Server
- type State
- type Track
- type Whoami
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Account ¶
Account is the controlled client's Deezer identity, supplied by a snapshot provider so the HTTP goroutine never reads the deezer.Client's login fields directly (those are written by Login on another goroutine).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to a control Server over HTTP. It is the shared driver for the MCP server and the TUI's remote-play feature: both point it at another OpenDeezer client's control API and issue the same commands a local user would.
func NewClient ¶
NewClient builds a control client. base is the server's URL; token/account are the credentials (send whichever the server requires; empty ones are omitted).
func (*Client) CycleRepeat ¶
func (*Client) Playlists ¶
func (c *Client) Playlists() (json.RawMessage, error)
Playlists returns the raw playlists JSON from the server.
func (*Client) Search ¶
func (c *Client) Search(q string) (json.RawMessage, error)
Search returns the raw search-results JSON from the server.
func (*Client) ToggleShuffle ¶
type Commands ¶
type Commands struct {
PlayPause func()
Next func()
Prev func()
Stop func()
Restart func() // seek to 0
CycleRepeat func()
ToggleShuffle func()
Seek func(ms int64)
SetVolume func(v float64)
PlayTrack func(id string)
PlayPlaylist func(id string)
}
Commands are the mutating actions a controller exposes (each may be nil).
type Config ¶
type Config struct {
Addr string // host:port ("127.0.0.1:7654" localhost, ":7654" LAN)
Token string // bearer token; "" disables token auth
SameAccountOnly bool // when Token=="", require a matching Deezer account id
}
Config configures the control server.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server serves the control API.
func New ¶
func New(cfg Config, status func() State, account func() Account, cmds Commands, client *deezer.Client) *Server
New builds a control server from cfg. status + account are snapshot providers (called from the HTTP goroutine, so they must be race-free reads); client supplies the browse endpoints (search/playlists).
func (*Server) SetClientInfo ¶
SetClientInfo records the client/platform id + device label for /whoami.
func (*Server) SetVersion ¶
SetVersion records the app version reported by /whoami.
type State ¶
type State struct {
State string `json:"state"` // playing | paused | stopped | loading | error
Track *Track `json:"track,omitempty"`
PositionMS int64 `json:"positionMs"`
DurationMS int64 `json:"durationMs"`
Volume float64 `json:"volume"` // 0..1
Repeat string `json:"repeat"` // off | all | one
Shuffle bool `json:"shuffle"`
Format string `json:"format,omitempty"`
Queue []Track `json:"queue,omitempty"`
}
State is the playback snapshot returned by GET /status.
type Track ¶
type Track struct {
ID string `json:"id"`
Title string `json:"title"`
Artist string `json:"artist"`
Album string `json:"album"`
Explicit bool `json:"explicit"`
DurationMS int64 `json:"durationMs"`
}
Track is a now-playing / queue entry in the API.
type Whoami ¶
type Whoami struct {
Name string `json:"name"`
Offer string `json:"offer,omitempty"`
Auth string `json:"auth"` // token | account | none
Version string `json:"version,omitempty"` // OpenDeezer version
Client string `json:"client,omitempty"` // client/platform id (tui, macos, gnome…)
Device string `json:"device,omitempty"` // human device label ("OpenDeezer TUI")
}
Whoami is the unauthenticated identity returned by GET /whoami. It carries the account display NAME (for the controller to recognise its own device) but never the user id: in same-account mode that id IS the credential, so echoing it here would let any bystander read and replay it.