connect

package
v1.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: AGPL-3.0 Imports: 7 Imported by: 0

Documentation

Overview

Package connect implements OpenDeezer Connect: LAN discovery and remote control of OpenDeezer devices, in both directions.

OpenDeezer Connect is symmetric — this package exposes both sides:

  • out — discover and control other devices: Discover + RemoteClient
  • in — be discoverable and controllable: Host (and the lower-level Advertise if you manage your own control server)

Transport: IPv4 UDP multicast (group 239.255.42.99, port 7655) with a directed-broadcast fallback so it works on networks that filter multicast. Only LAN/loopback sources are answered; no credentials are exchanged during discovery.

Out: discover devices

devices, err := connect.Discover(2*time.Second, 0)
for _, d := range devices {
    fmt.Printf("%s at %s (client: %s)\n", d.Name, d.Addr, d.Client)
}

Out: drive a device

rc := connect.NewRemoteClient(devices[0].Addr, token, "")
st, _ := rc.PlayPause()
fmt.Println("state:", st.State)

In: be a controllable device

Host ties a control endpoint together with LAN advertising, so this process becomes discoverable and accepts the same commands a RemoteClient sends:

host := connect.NewHost(
    connect.HostConfig{
        Control: connect.Config{Addr: ":7654", SameAccountOnly: true},
        Name:    "My Player", Client: "myapp", Version: "1.0",
    },
    func() connect.State { return snapshot() },
    func() connect.Account { return connect.Account{UserID: uid, Name: name} },
    connect.Commands{PlayPause: player.TogglePause, Stop: player.Stop},
    dzClient, // browse routes; nil to disable
)
host.Start()
defer host.Close()

In: advertise only (custom control server)

resp, _ := connect.Advertise(func() connect.AdvertiseInfo {
    return connect.AdvertiseInfo{Name: "My Player", Client: "myapp", Version: "1.0"}
}, controlPort)
defer resp.Close()

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Account

type Account = internalcontrol.Account

Account is this device's Deezer identity snapshot, provided to NewHost. It is the same type as control.Account.

type AdvertiseInfo

type AdvertiseInfo = internaldiscovery.Info

AdvertiseInfo is the identity advertised to probers. The function you pass to Advertise returns one of these on each probe so changes (e.g. a re-login updating the display name) are reflected immediately.

type Commands

type Commands = internalcontrol.Commands

Commands are the playback actions an inbound controller can dispatch to this device via a Host. It is the same type as control.Commands.

type Config

type Config = internalcontrol.Config

Config configures the control endpoint a Host exposes (the inbound side). It is the same type as control.Config.

type Device

type Device = internaldiscovery.Device

Device is a discovered OpenDeezer instance.

  • Name — the account's display name
  • Addr — control API address (host:port) to pass to NewRemoteClient
  • Client — client/platform id (e.g. "tui", "macos", "gnome")
  • Version — OpenDeezer version

func Discover

func Discover(timeout time.Duration, selfPort int) ([]Device, error)

Discover multicasts a discovery probe and returns all OpenDeezer devices that reply within timeout.

selfPort is this device's own control port. Replies arriving from a local interface with that port are filtered out so you never list yourself. Pass 0 if you are not running a control server.

type Host

type Host struct {
	// contains filtered or unexported fields
}

Host is the inbound side of OpenDeezer Connect: a control endpoint other devices can drive, advertised on the LAN so Discover finds it. It is the mirror image of RemoteClient (which drives a host) and pairs with Advertise/Discover.

Construct one with NewHost, call Host.Start to bind and advertise, and Host.Close to stop. Host is safe for concurrent use once started.

func NewHost

func NewHost(
	cfg HostConfig,
	status func() State,
	account func() Account,
	cmds Commands,
	dz *sdkdeezer.Client,
) *Host

NewHost builds a Connect host.

  • cfg — control bind/auth + advertised identity
  • status — playback snapshot provider (race-free reads)
  • account — logged-in identity provider; its Name is preferred for the advertised name. Pass nil to advertise cfg.Name only.
  • cmds — the actions remote controllers can dispatch (same command set a RemoteClient sends)
  • dz — Deezer client for the endpoint's browse routes; nil to disable

func (*Host) Addr

func (h *Host) Addr() string

Addr returns the control endpoint's listen address (valid after Host.Start).

func (*Host) Close

func (h *Host) Close()

Close stops advertising and shuts down the control endpoint.

func (*Host) Server

func (h *Host) Server() *sdkcontrol.Server

Server returns the underlying control server so callers can enable web-remote pairing (sdkcontrol.Server.EnablePairing), read the listen address, or override the device label.

func (*Host) Start

func (h *Host) Start() error

Start binds the control endpoint and begins advertising it on the LAN via OpenDeezer Connect (UDP port 7655). The advertised control port is taken from the endpoint's actual listen address.

Advertising is only useful when the control endpoint binds a LAN-reachable (non-loopback) address; a loopback bind is advertised but reachable only on this machine.

type HostConfig

type HostConfig struct {
	// Control is the control-endpoint configuration (listen address and auth
	// mode). For a LAN-reachable device, bind a non-loopback address such as
	// ":7654" and set Token or SameAccountOnly.
	Control Config

	// Name is the advertised display name. When an account snapshot is provided
	// to [NewHost] and reports a non-empty name, that name is used instead so a
	// re-login is reflected automatically.
	Name string
	// Client is the advertised client/platform id (e.g. "myapp").
	Client string
	// Version is the advertised OpenDeezer/app version.
	Version string
}

HostConfig configures a Host: how the control endpoint binds and authenticates, plus the identity advertised over LAN discovery.

type RemoteClient

type RemoteClient struct {
	// contains filtered or unexported fields
}

RemoteClient drives a discovered OpenDeezer device via its HTTP/JSON control API. All mutation methods return the device's post-command playback snapshot.

Thread-safe.

func NewRemoteClient

func NewRemoteClient(addr, token, accountID string) *RemoteClient

NewRemoteClient builds a remote-control client for the device at addr (host:port as returned by [Device.Addr]). Provide token or accountID depending on the device's auth mode (see RemoteClient.Whoami):

  • token auth → token="<bearer>", accountID=""
  • account auth → token="", accountID="<your Deezer user id>"
  • session auth → use the session token obtained by pairing
  • none → token="", accountID=""

func (*RemoteClient) Next

func (rc *RemoteClient) Next() (State, error)

Next skips to the next track.

func (*RemoteClient) PlayPause

func (rc *RemoteClient) PlayPause() (State, error)

PlayPause toggles play/pause on the device.

func (*RemoteClient) PlayPlaylist

func (rc *RemoteClient) PlayPlaylist(id string) (State, error)

PlayPlaylist instructs the device to play the playlist with the given id.

func (*RemoteClient) PlayTrack

func (rc *RemoteClient) PlayTrack(id string) (State, error)

PlayTrack instructs the device to play the track with the given Deezer id.

func (*RemoteClient) Prev

func (rc *RemoteClient) Prev() (State, error)

Prev jumps to the previous track.

func (*RemoteClient) Restart

func (rc *RemoteClient) Restart() (State, error)

Restart seeks to position 0 in the current track.

func (*RemoteClient) SeekMS

func (rc *RemoteClient) SeekMS(ms int64) (State, error)

SeekMS seeks to ms milliseconds from the start of the current track.

func (*RemoteClient) SetRepeat

func (rc *RemoteClient) SetRepeat(mode string) (State, error)

SetRepeat sets the repeat mode: "off", "all", or "one".

func (*RemoteClient) SetShuffle

func (rc *RemoteClient) SetShuffle(on bool) (State, error)

SetShuffle enables (true) or disables (false) shuffle on the device.

func (*RemoteClient) SetVolume

func (rc *RemoteClient) SetVolume(v float64) (State, error)

SetVolume sets the volume on the device (0.0 = silent, 1.0 = full).

func (*RemoteClient) Status

func (rc *RemoteClient) Status() (State, error)

Status returns the device's current playback snapshot.

func (*RemoteClient) Stop

func (rc *RemoteClient) Stop() (State, error)

Stop halts playback.

func (*RemoteClient) Whoami

func (rc *RemoteClient) Whoami() (Whoami, error)

Whoami fetches the device's identity and auth mode. This endpoint is unauthenticated and can be called before supplying credentials.

type Responder

type Responder = internaldiscovery.Responder

Responder is a running OpenDeezer Connect discovery responder. Stop it with Close.

func Advertise(info func() AdvertiseInfo, controlPort int) (*Responder, error)

Advertise starts an OpenDeezer Connect responder on UDP port 7655. info is called on each incoming probe to get the current display name and version. controlPort is the TCP port of the local control server that controllers should connect to.

Call Close on the returned Responder to stop advertising.

type State

type State = internalcontrol.State

State is the playback snapshot returned by RemoteClient.Status and all mutation methods.

type Track

type Track = internalcontrol.Track

Track is a now-playing or queue entry in a State.

type Whoami

type Whoami = internalcontrol.Whoami

Whoami holds a device's identity and the auth mode it requires.

  • Name — account display name (not the user id)
  • Offer — plan name (e.g. "Deezer Premium")
  • Auth — "token" | "account" | "session" | "none"
  • Client — client/platform id
  • Device — human device label

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL