sonos

package
v0.0.0-...-957713d Latest Latest
Warning

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

Go to latest
Published: Jan 22, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AlbumArtURL

func AlbumArtURL(deviceIP string, albumArtURI string) string

AlbumArtURL returns an absolute URL for album art when Sonos returns a relative path.

func BuildRadioMeta

func BuildRadioMeta(title string) string

BuildRadioMeta builds minimal DIDL metadata suitable for playing radio streams.

func ForceRadioURI

func ForceRadioURI(uri string) string

ForceRadioURI converts an http/https/aac URI to the Sonos "mp3radio" scheme to force radio-style playback controls in the Sonos UI.

func JoinURI

func JoinURI(coordinatorUUID string) (string, error)

func ParseEvent

func ParseEvent(payload []byte) (map[string]string, error)

ParseEvent decodes a UPnP event propertyset payload into a flat map. If a LastChange property is present, it is decoded and flattened.

Types

type AppleMusicKind

type AppleMusicKind string

AppleMusicKind represents the type of Apple Music content.

const (
	AppleMusicAlbum    AppleMusicKind = "album"
	AppleMusicSong     AppleMusicKind = "song"
	AppleMusicPlaylist AppleMusicKind = "playlist"
	AppleMusicStation  AppleMusicKind = "station"
)

type AppleMusicRef

type AppleMusicRef struct {
	Kind        AppleMusicKind
	ID          string
	Canonical   string // Original URL or constructed identifier
	ServiceNums []int  // Sonos service numbers for Apple Music
}

AppleMusicRef holds parsed Apple Music reference information.

func ParseAppleMusicRef

func ParseAppleMusicRef(input string) (AppleMusicRef, bool)

ParseAppleMusicRef parses an Apple Music URL or identifier and returns a reference.

type BrowseResponse

type BrowseResponse struct {
	Result         string
	NumberReturned int
	TotalMatches   int
	UpdateID       int
}

type Client

type Client struct {
	IP   string
	Port int
	HTTP *http.Client
}

func NewClient

func NewClient(ip string, timeout time.Duration) *Client

func (*Client) AddURIToQueue

func (c *Client) AddURIToQueue(ctx context.Context, enqueuedURI, enqueuedMeta string, desiredFirstTrackNumber int, enqueueAsNext bool) (firstTrackNumber int, err error)

func (*Client) BecomeCoordinatorOfStandaloneGroup

func (c *Client) BecomeCoordinatorOfStandaloneGroup(ctx context.Context) error

func (*Client) Browse

func (c *Client) Browse(ctx context.Context, objectID string, start, count int) (BrowseResponse, error)

func (*Client) ClearQueue

func (c *Client) ClearQueue(ctx context.Context) error

func (*Client) EnqueueAppleMusic

func (c *Client) EnqueueAppleMusic(ctx context.Context, input string, opts EnqueueOptions) (int, error)

EnqueueAppleMusic enqueues Apple Music content to the speaker's queue. This method uses SMAPI search results which return properly formatted IDs.

func (*Client) EnqueueAppleMusicFromSMAPI

func (c *Client) EnqueueAppleMusicFromSMAPI(ctx context.Context, item SMAPIItem, serviceNum int, opts EnqueueOptions) (int, error)

EnqueueAppleMusicFromSMAPI enqueues an Apple Music item returned from SMAPI search. The item parameter should have ID and Title from the SMAPI search result.

func (*Client) EnqueueSpotify

func (c *Client) EnqueueSpotify(ctx context.Context, input string, opts EnqueueOptions) (int, error)

func (*Client) GetDeviceDescription

func (c *Client) GetDeviceDescription(ctx context.Context) (Device, error)

func (*Client) GetGroupMute

func (c *Client) GetGroupMute(ctx context.Context) (bool, error)

func (*Client) GetGroupVolume

func (c *Client) GetGroupVolume(ctx context.Context) (int, error)

func (*Client) GetHouseholdID

func (c *Client) GetHouseholdID(ctx context.Context) (string, error)

func (*Client) GetMute

func (c *Client) GetMute(ctx context.Context) (bool, error)

func (*Client) GetPositionInfo

func (c *Client) GetPositionInfo(ctx context.Context) (PositionInfo, error)

func (*Client) GetString

func (c *Client) GetString(ctx context.Context, variableName string) (string, error)

func (*Client) GetTopology

func (c *Client) GetTopology(ctx context.Context) (Topology, error)

func (*Client) GetTransportInfo

func (c *Client) GetTransportInfo(ctx context.Context) (TransportInfo, error)

func (*Client) GetTransportSettings

func (c *Client) GetTransportSettings(ctx context.Context) (TransportSettings, error)

GetTransportSettings returns the current play mode (shuffle/repeat) settings.

func (*Client) GetVolume

func (c *Client) GetVolume(ctx context.Context) (int, error)

func (*Client) JoinGroup

func (c *Client) JoinGroup(ctx context.Context, coordinatorUUID string) error

JoinGroup makes this speaker join the group coordinated by coordinatorUUID. This is typically done by sending AVTransport.SetAVTransportURI to the joining speaker with:

CurrentURI = x-rincon:<COORDINATOR_UUID>

func (*Client) LeaveGroup

func (c *Client) LeaveGroup(ctx context.Context) error

LeaveGroup ungroups this speaker, making it the coordinator of a standalone group.

func (*Client) ListAvailableServices

func (c *Client) ListAvailableServices(ctx context.Context) ([]MusicServiceDescriptor, error)

func (*Client) ListFavorites

func (c *Client) ListFavorites(ctx context.Context, start, count int) (FavoritesPage, error)

func (*Client) ListQueue

func (c *Client) ListQueue(ctx context.Context, start, count int) (QueuePage, error)

func (*Client) Next

func (c *Client) Next(ctx context.Context) error

func (*Client) Pause

func (c *Client) Pause(ctx context.Context) error

func (*Client) Play

func (c *Client) Play(ctx context.Context) error

func (*Client) PlayFavorite

func (c *Client) PlayFavorite(ctx context.Context, favorite DIDLItem) error

func (*Client) PlayQueuePosition

func (c *Client) PlayQueuePosition(ctx context.Context, position int) error

func (*Client) PlayURI

func (c *Client) PlayURI(ctx context.Context, uri, meta string) error

func (*Client) Previous

func (c *Client) Previous(ctx context.Context) error

func (*Client) PreviousOrRestart

func (c *Client) PreviousOrRestart(ctx context.Context) error

PreviousOrRestart attempts to go to the previous track. If the device rejects the transition (common for some streaming sources), it falls back to restarting the current track by seeking to 0:00:00.

func (*Client) RemoveAllTracksFromQueue

func (c *Client) RemoveAllTracksFromQueue(ctx context.Context) error

func (*Client) RemoveQueuePosition

func (c *Client) RemoveQueuePosition(ctx context.Context, position int) error

func (*Client) RemoveTrackFromQueue

func (c *Client) RemoveTrackFromQueue(ctx context.Context, oneBasedTrackNumber int) error

func (*Client) Renew

func (c *Client) Renew(ctx context.Context, sub Subscription, requestedTimeout time.Duration) (Subscription, error)

func (*Client) SeekRelTime

func (c *Client) SeekRelTime(ctx context.Context, hhmmss string) error

func (*Client) SeekTrackNumber

func (c *Client) SeekTrackNumber(ctx context.Context, oneBasedTrackNumber int) error

func (*Client) SetAVTransportURI

func (c *Client) SetAVTransportURI(ctx context.Context, uri, meta string) error

func (*Client) SetGroupMute

func (c *Client) SetGroupMute(ctx context.Context, mute bool) error

func (*Client) SetGroupVolume

func (c *Client) SetGroupVolume(ctx context.Context, volume int) error

func (*Client) SetMute

func (c *Client) SetMute(ctx context.Context, mute bool) error

func (*Client) SetPlayMode

func (c *Client) SetPlayMode(ctx context.Context, mode PlayMode) error

SetPlayMode sets the playback mode (shuffle/repeat). Valid modes: NORMAL, SHUFFLE, SHUFFLE_NOREPEAT, REPEAT_ALL, REPEAT_ONE

func (*Client) SetVolume

func (c *Client) SetVolume(ctx context.Context, volume int) error

func (*Client) SnapshotGroupVolume

func (c *Client) SnapshotGroupVolume(ctx context.Context) error

func (*Client) Stop

func (c *Client) Stop(ctx context.Context) error

func (*Client) StopOrNoop

func (c *Client) StopOrNoop(ctx context.Context) error

StopOrNoop attempts to stop playback. Some sources (e.g. TV input via x-sonos-htastream) reject Stop with UPnP error 701 (Transition not available). In that case, this is treated as a successful no-op.

func (*Client) Subscribe

func (c *Client) Subscribe(ctx context.Context, eventPath string, callbackURL string, requestedTimeout time.Duration) (Subscription, error)

func (*Client) SubscribeAVTransport

func (c *Client) SubscribeAVTransport(ctx context.Context, callbackURL string, requestedTimeout time.Duration) (Subscription, error)

func (*Client) SubscribeRenderingControl

func (c *Client) SubscribeRenderingControl(ctx context.Context, callbackURL string, requestedTimeout time.Duration) (Subscription, error)

func (*Client) Unsubscribe

func (c *Client) Unsubscribe(ctx context.Context, sub Subscription) error

type DIDLItem

type DIDLItem struct {
	ID          string `json:"id"`
	Title       string `json:"title"`
	URI         string `json:"uri"`
	Class       string `json:"class,omitempty"`
	Artist      string `json:"artist,omitempty"`
	Album       string `json:"album,omitempty"`
	AlbumArtURI string `json:"albumArtURI,omitempty"`
	ResMD       string `json:"resMD,omitempty"`
}

func ParseDIDLItems

func ParseDIDLItems(didlXML string) ([]DIDLItem, error)

func ParseNowPlaying

func ParseNowPlaying(trackMetaData string) (DIDLItem, bool)

ParseNowPlaying attempts to parse a DIDL-Lite TrackMetaData payload into a single DIDLItem.

type Device

type Device struct {
	IP       string `json:"ip"`
	Name     string `json:"name"`
	UDN      string `json:"udn"`
	Location string `json:"location"`
}

func Discover

func Discover(ctx context.Context, opts DiscoverOptions) ([]Device, error)

type DiscoverOptions

type DiscoverOptions struct {
	Timeout          time.Duration
	IncludeInvisible bool
}

type EnqueueOptions

type EnqueueOptions struct {
	Title    string
	AsNext   bool
	PlayNow  bool
	Position int // 0 = append
}

type FavoriteItem

type FavoriteItem struct {
	Position int      `json:"position"` // 1-based
	Item     DIDLItem `json:"item"`
}

type FavoritesPage

type FavoritesPage struct {
	Items          []FavoriteItem `json:"items"`
	NumberReturned int            `json:"numberReturned"`
	TotalMatches   int            `json:"totalMatches"`
	UpdateID       int            `json:"updateID"`
}

type FileSMAPITokenStore

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

func NewDefaultSMAPITokenStore

func NewDefaultSMAPITokenStore() (*FileSMAPITokenStore, error)

func NewFileSMAPITokenStore

func NewFileSMAPITokenStore(path string) (*FileSMAPITokenStore, error)

func (*FileSMAPITokenStore) Has

func (s *FileSMAPITokenStore) Has(serviceID, householdID string) bool

func (*FileSMAPITokenStore) Load

func (s *FileSMAPITokenStore) Load(serviceID, householdID string) (SMAPITokenPair, bool, error)

func (*FileSMAPITokenStore) Save

func (s *FileSMAPITokenStore) Save(serviceID, householdID string, pair SMAPITokenPair) error

type Group

type Group struct {
	ID          string   `json:"id"`
	Coordinator Member   `json:"coordinator"`
	Members     []Member `json:"members"`
}

type Member

type Member struct {
	Name          string `json:"name"`
	IP            string `json:"ip"`
	UUID          string `json:"uuid"`
	Location      string `json:"location"`
	IsVisible     bool   `json:"isVisible"`
	IsCoordinator bool   `json:"isCoordinator"`
}

type MusicServiceAuthType

type MusicServiceAuthType string
const (
	MusicServiceAuthAnonymous  MusicServiceAuthType = "Anonymous"
	MusicServiceAuthUserID     MusicServiceAuthType = "UserId"
	MusicServiceAuthDeviceLink MusicServiceAuthType = "DeviceLink"
	MusicServiceAuthAppLink    MusicServiceAuthType = "AppLink"
)

type MusicServiceDescriptor

type MusicServiceDescriptor struct {
	ID                 string               `json:"id"`
	Name               string               `json:"name"`
	Version            string               `json:"version"`
	URI                string               `json:"uri"`
	SecureURI          string               `json:"secureUri"`
	Capabilities       string               `json:"capabilities"`
	ContainerType      string               `json:"containerType"`
	Auth               MusicServiceAuthType `json:"auth"`
	ServiceType        string               `json:"serviceType"`
	PresentationMapURI string               `json:"presentationMapUri,omitempty"`
	StringsURI         string               `json:"stringsUri,omitempty"`
	ManifestURI        string               `json:"manifestUri,omitempty"`
}

type PlayMode

type PlayMode string

PlayMode represents the playback mode (shuffle/repeat settings). Valid values: NORMAL, SHUFFLE, SHUFFLE_NOREPEAT, REPEAT_ALL, REPEAT_ONE

const (
	PlayModeNormal          PlayMode = "NORMAL"
	PlayModeShuffle         PlayMode = "SHUFFLE"
	PlayModeShuffleNoRepeat PlayMode = "SHUFFLE_NOREPEAT"
	PlayModeRepeatAll       PlayMode = "REPEAT_ALL"
	PlayModeRepeatOne       PlayMode = "REPEAT_ONE"
)

type PositionInfo

type PositionInfo struct {
	Track         string
	TrackURI      string
	TrackMeta     string
	TrackDuration string
	RelTime       string
}

type QueueItem

type QueueItem struct {
	Position int      `json:"position"` // 1-based
	Item     DIDLItem `json:"item"`
}

type QueuePage

type QueuePage struct {
	Items          []QueueItem `json:"items"`
	NumberReturned int         `json:"numberReturned"`
	TotalMatches   int         `json:"totalMatches"`
	UpdateID       int         `json:"updateID"`
}

type SMAPIBeginAuthResult

type SMAPIBeginAuthResult struct {
	RegURL       string `json:"regUrl"`
	LinkCode     string `json:"linkCode"`
	LinkDeviceID string `json:"linkDeviceId,omitempty"`
}

type SMAPIBrowseResult

type SMAPIBrowseResult struct {
	ID              string      `json:"id"`
	Index           int         `json:"index"`
	Count           int         `json:"count"`
	Total           int         `json:"total"`
	MediaMetadata   []SMAPIItem `json:"mediaMetadata,omitempty"`
	MediaCollection []SMAPIItem `json:"mediaCollection,omitempty"`
}

type SMAPIClient

type SMAPIClient struct {
	Service     MusicServiceDescriptor
	HouseholdID string
	DeviceID    string
	TokenStore  SMAPITokenStore
	// contains filtered or unexported fields
}

func NewSMAPIClient

func NewSMAPIClient(ctx context.Context, speaker *Client, svc MusicServiceDescriptor, store SMAPITokenStore) (*SMAPIClient, error)

func (*SMAPIClient) BeginAuthentication

func (c *SMAPIClient) BeginAuthentication(ctx context.Context) (SMAPIBeginAuthResult, error)

func (*SMAPIClient) CompleteAuthentication

func (c *SMAPIClient) CompleteAuthentication(ctx context.Context, linkCode, linkDeviceID string) (SMAPITokenPair, error)

func (*SMAPIClient) GetMetadata

func (c *SMAPIClient) GetMetadata(ctx context.Context, id string, index, count int, recursive bool) (SMAPIBrowseResult, error)

func (*SMAPIClient) Search

func (c *SMAPIClient) Search(ctx context.Context, category, term string, index, count int) (SMAPISearchResult, error)

func (*SMAPIClient) SearchCategories

func (c *SMAPIClient) SearchCategories(ctx context.Context) ([]string, error)

type SMAPIItem

type SMAPIItem struct {
	ID       string `json:"id"`
	ItemType string `json:"itemType"`
	Title    string `json:"title"`
	Summary  string `json:"summary,omitempty"`
	MimeType string `json:"mimeType,omitempty"`
}

type SMAPISearchResult

type SMAPISearchResult struct {
	Category        string      `json:"category"`
	Term            string      `json:"term"`
	Index           int         `json:"index"`
	Count           int         `json:"count"`
	Total           int         `json:"total"`
	MediaMetadata   []SMAPIItem `json:"mediaMetadata,omitempty"`
	MediaCollection []SMAPIItem `json:"mediaCollection,omitempty"`
}

type SMAPITokenPair

type SMAPITokenPair struct {
	AuthToken   string    `json:"authToken"`
	PrivateKey  string    `json:"privateKey"`
	UpdatedAt   time.Time `json:"updatedAt"`
	LinkCode    string    `json:"linkCode,omitempty"`    // optional, for debugging
	DeviceID    string    `json:"deviceId,omitempty"`    // optional, for debugging
	HouseholdID string    `json:"householdId,omitempty"` // optional, for debugging
}

type SMAPITokenStore

type SMAPITokenStore interface {
	Has(serviceID, householdID string) bool
	Load(serviceID, householdID string) (SMAPITokenPair, bool, error)
	Save(serviceID, householdID string, pair SMAPITokenPair) error
}

type SpotifyKind

type SpotifyKind string
const (
	SpotifyAlbum    SpotifyKind = "album"
	SpotifyEpisode  SpotifyKind = "episode"
	SpotifyPlaylist SpotifyKind = "playlist"
	SpotifyShow     SpotifyKind = "show"
	SpotifyTrack    SpotifyKind = "track"
)

type SpotifyRef

type SpotifyRef struct {
	Kind        SpotifyKind
	ID          string
	Canonical   string // spotify:<kind>:<id>
	EncodedID   string // spotify%3a<kind>%3a<id>
	ServiceNums []int  // possible Sonos service numbers
}

func ParseSpotifyRef

func ParseSpotifyRef(input string) (SpotifyRef, bool)

type Subscription

type Subscription struct {
	SID     string
	Timeout time.Duration
	URL     string
}

type Topology

type Topology struct {
	Groups []Group           `json:"groups"`
	ByName map[string]Member `json:"-"`
	ByIP   map[string]Member `json:"-"`
	// contains filtered or unexported fields
}

func (Topology) CoordinatorIPFor

func (t Topology) CoordinatorIPFor(ip string) (string, bool)

func (Topology) CoordinatorIPForName

func (t Topology) CoordinatorIPForName(name string) (string, bool)

func (Topology) CoordinatorUUIDForIP

func (t Topology) CoordinatorUUIDForIP(ip string) (string, bool)

func (Topology) CoordinatorUUIDForName

func (t Topology) CoordinatorUUIDForName(name string) (string, bool)

func (Topology) FindByIP

func (t Topology) FindByIP(ip string) (Member, bool)

func (Topology) FindByName

func (t Topology) FindByName(name string) (Member, bool)

func (Topology) GroupForIP

func (t Topology) GroupForIP(ip string) (Group, bool)

func (Topology) GroupForName

func (t Topology) GroupForName(name string) (Group, bool)

type TransportInfo

type TransportInfo struct {
	State  string
	Status string
	Speed  string
}

type TransportSettings

type TransportSettings struct {
	PlayMode       PlayMode
	RecQualityMode string
}

TransportSettings holds the current play mode and rec quality mode.

type UPnPError

type UPnPError struct {
	Code        string
	Description string
}

func (*UPnPError) Error

func (e *UPnPError) Error() string

Jump to

Keyboard shortcuts

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