Files
webrtc/vendor/github.com/szatmary/sonos/zoneplayer.go
T

237 lines
7.5 KiB
Go

package sonos
import (
"encoding/xml"
"io/ioutil"
"net/http"
"net/url"
avt "github.com/szatmary/sonos/AVTransport"
clk "github.com/szatmary/sonos/AlarmClock"
con "github.com/szatmary/sonos/ConnectionManager"
dir "github.com/szatmary/sonos/ContentDirectory"
dev "github.com/szatmary/sonos/DeviceProperties"
gmn "github.com/szatmary/sonos/GroupManagement"
rcg "github.com/szatmary/sonos/GroupRenderingControl"
mus "github.com/szatmary/sonos/MusicServices"
ply "github.com/szatmary/sonos/QPlay"
que "github.com/szatmary/sonos/Queue"
ren "github.com/szatmary/sonos/RenderingControl"
sys "github.com/szatmary/sonos/SystemProperties"
vli "github.com/szatmary/sonos/VirtualLineIn"
zgt "github.com/szatmary/sonos/ZoneGroupTopology"
)
type SpecVersion struct {
XMLName xml.Name `xml:"specVersion"`
Major int `xml:"major"`
Minor int `xml:"minor"`
}
type Service struct {
XMLName xml.Name `xml:"service"`
ServiceType string `xml:"serviceType"`
ServiceId string `xml:"serviceId"`
ControlURL string `xml:"controlURL"`
EventSubURL string `xml:"eventSubURL"`
SCPDURL string `xml:"SCPDURL"`
}
type Icon struct {
XMLName xml.Name `xml:"icon"`
Id string `xml:"id"`
Mimetype string `xml:"mimetype"`
Width int `xml:"width"`
Height int `xml:"height"`
Depth int `xml:"depth"`
Url url.URL `xml:"url"`
}
type Device struct {
XMLName xml.Name `xml:"device"`
DeviceType string `xml:"deviceType"`
FriendlyName string `xml:"friendlyName"`
Manufacturer string `xml:"manufacturer"`
ManufacturerURL string `xml:"manufacturerURL"`
ModelNumber string `xml:"modelNumber"`
ModelDescription string `xml:"modelDescription"`
ModelName string `xml:"modelName"`
ModelURL string `xml:"modelURL"`
SoftwareVersion string `xml:"softwareVersion"`
SwGen string `xml:"swGen"`
HardwareVersion string `xml:"hardwareVersion"`
SerialNum string `xml:"serialNum"`
MACAddress string `xml:"MACAddress"`
UDN string `xml:"UDN"`
Icons []Icon `xml:"iconList>icon"`
MinCompatibleVersion string `xml:"minCompatibleVersion"`
LegacyCompatibleVersion string `xml:"legacyCompatibleVersion"`
ApiVersion string `xml:"apiVersion"`
MinApiVersion string `xml:"minApiVersion"`
DisplayVersion string `xml:"displayVersion"`
ExtraVersion string `xml:"extraVersion"`
RoomName string `xml:"roomName"`
DisplayName string `xml:"displayName"`
ZoneType int `xml:"zoneType"`
Feature1 string `xml:"feature1"`
Feature2 string `xml:"feature2"`
Feature3 string `xml:"feature3"`
Seriesid string `xml:"seriesid"`
Variant int `xml:"variant"`
InternalSpeakerSize float32 `xml:"internalSpeakerSize"`
BassExtension float32 `xml:"bassExtension"`
SatGainOffset float32 `xml:"satGainOffset"`
Memory int `xml:"memory"`
Flash int `xml:"flash"`
FlashRepartitioned int `xml:"flashRepartitioned"`
AmpOnTime int `xml:"ampOnTime"`
RetailMode int `xml:"retailMode"`
Services []Service `xml:"serviceList>service"`
Devices []Device `xml:"deviceList>device"`
}
type Root struct {
XMLName xml.Name `xml:"root"`
Xmlns string `xml:"xmlns,attr"`
SpecVersion SpecVersion `xml:"specVersion"`
Device Device `xml:"device"`
}
type ZonePlayer struct {
Root *Root
HttpClient *http.Client
DeviceDescriptionURL *url.URL
// services
AlarmClock *clk.Service
AVTransport *avt.Service
ConnectionManager *con.Service
ContentDirectory *dir.Service
DeviceProperties *dev.Service
GroupManagement *gmn.Service
GroupRenderingControl *rcg.Service
MusicServices *mus.Service
QPlay *ply.Service
Queue *que.Service
RenderingControl *ren.Service
SystemProperties *sys.Service
VirtualLineIn *vli.Service
ZoneGroupTopology *zgt.Service
}
func NewZonePlayer(deviceDescriptionURL *url.URL) (*ZonePlayer, error) {
zp := ZonePlayer{
Root: &Root{},
HttpClient: &http.Client{},
DeviceDescriptionURL: deviceDescriptionURL,
AlarmClock: clk.NewService(deviceDescriptionURL),
AVTransport: avt.NewService(deviceDescriptionURL),
ConnectionManager: con.NewService(deviceDescriptionURL),
ContentDirectory: dir.NewService(deviceDescriptionURL),
DeviceProperties: dev.NewService(deviceDescriptionURL),
GroupManagement: gmn.NewService(deviceDescriptionURL),
GroupRenderingControl: rcg.NewService(deviceDescriptionURL),
MusicServices: mus.NewService(deviceDescriptionURL),
QPlay: ply.NewService(deviceDescriptionURL),
Queue: que.NewService(deviceDescriptionURL),
RenderingControl: ren.NewService(deviceDescriptionURL),
SystemProperties: sys.NewService(deviceDescriptionURL),
VirtualLineIn: vli.NewService(deviceDescriptionURL),
ZoneGroupTopology: zgt.NewService(deviceDescriptionURL),
}
resp, err := zp.HttpClient.Get(zp.DeviceDescriptionURL.String())
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
defer resp.Body.Close()
err = xml.Unmarshal(body, zp.Root)
if err != nil {
return nil, err
}
return &zp, nil
}
func (z *ZonePlayer) RoomName() string {
return z.Root.Device.RoomName
}
func (z *ZonePlayer) ModelName() string {
return z.Root.Device.ModelName
}
func (z *ZonePlayer) HardwareVersion() string {
return z.Root.Device.HardwareVersion
}
func (z *ZonePlayer) SerialNum() string {
return z.Root.Device.SerialNum
}
func (z *ZonePlayer) IsCoordinator() bool {
zoneGroupState, err := z.GetZoneGroupState()
if err != nil {
return false
}
for _, group := range zoneGroupState.ZoneGroups {
if "uuid:"+group.Coordinator == z.Root.Device.UDN {
return true
}
}
return false
}
// Convience functions
func (z *ZonePlayer) GetZoneGroupState() (*ZoneGroupState, error) {
zoneGroupStateResponse, err := z.ZoneGroupTopology.GetZoneGroupState(z.HttpClient, &zgt.GetZoneGroupStateArgs{})
if err != nil {
return nil, err
}
var zoneGroupState ZoneGroupState
err = xml.Unmarshal([]byte(zoneGroupStateResponse.ZoneGroupState), &zoneGroupState)
if err != nil {
return nil, err
}
return &zoneGroupState, nil
}
func (z *ZonePlayer) GetVolume() (int, error) {
res, err := z.RenderingControl.GetVolume(z.HttpClient, &ren.GetVolumeArgs{Channel: "Master"})
if err != nil {
return 0, err
}
return int(res.CurrentVolume), err
}
func (z *ZonePlayer) SetVolume(desiredVolume int) error {
_, err := z.RenderingControl.SetVolume(z.HttpClient, &ren.SetVolumeArgs{
Channel: "Master",
DesiredVolume: uint16(desiredVolume),
})
return err
}
func (z *ZonePlayer) Play() error {
_, err := z.AVTransport.Play(z.HttpClient, &avt.PlayArgs{
Speed: "1",
})
return err
}
func (z *ZonePlayer) SetAVTransportURI(url string) error {
_, err := z.AVTransport.SetAVTransportURI(z.HttpClient, &avt.SetAVTransportURIArgs{
CurrentURI: url,
})
return err
}