add sonos handler to play file

This commit is contained in:
kaedwen
2023-07-16 09:50:19 +02:00
parent b7e7db4127
commit 783aa5fd79
44 changed files with 12187 additions and 14 deletions
+2 -1
View File
@@ -1 +1,2 @@
service*
service*
cert
+3 -1
View File
@@ -13,7 +13,9 @@
"env": {
"HTTP_STATIC": "${workspaceFolder}/static/dist",
"VIDEO_OUT_DEVICE": "/dev/video4",
"AUDIO_OUT_DEVICE": "plughw:0,1,0"
"AUDIO_OUT_DEVICE": "plughw:0,1,0",
"INPUT_DEVICE": "/dev/input/event5",
"JINGLE_PATH": "${workspaceFolder}/audio"
}
},
{
Binary file not shown.
+2
View File
@@ -5,8 +5,10 @@ go 1.20
require (
github.com/alexflint/go-arg v1.4.3
github.com/gin-gonic/gin v1.9.1
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2
github.com/pion/rtcp v1.2.10
github.com/pion/webrtc/v3 v3.2.10
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e
github.com/tinyzimmer/go-glib v0.0.25
github.com/tinyzimmer/go-gst v0.2.33
go.uber.org/zap v1.24.0
+4
View File
@@ -63,6 +63,8 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2 h1:bxudnRpvfq2PMYEYN7VGj03+MXG4EobVUmONigCx1yA=
github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2/go.mod h1:iHAf8OIncO2gcQ8XOjS7CMJ2aPbX2Bs0wl5pZyanEqk=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -160,6 +162,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e h1:beo21nzzdqCVGe6EdG3Lo3UbU7meQN4JjAAeyZccH94=
github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e/go.mod h1:F5m1XEgf251EShYE9r+2Rl45NPLGovXttfuAjBb93bY=
github.com/tinyzimmer/go-glib v0.0.25 h1:2GpumtkxA0wpXhCXP6D3ksb5pGMfo9WbhgLvEw8njK4=
github.com/tinyzimmer/go-glib v0.0.25/go.mod h1:ltV0gO6xNFzZhsIRbFXv8RTq9NGoNT2dmAER4YmZfaM=
github.com/tinyzimmer/go-gst v0.2.33 h1:wdwUYoN7dkWGUTrZIgB9Mp5LMRr/Sld5PVGRsE7/O9s=
+12 -1
View File
@@ -6,6 +6,7 @@ import (
"syscall"
"github.com/kaedwen/webrtc/pkg/common"
"github.com/kaedwen/webrtc/pkg/ring"
"github.com/kaedwen/webrtc/pkg/server"
"github.com/kaedwen/webrtc/pkg/webrtc"
"github.com/tinyzimmer/go-glib/glib"
@@ -26,7 +27,17 @@ func main() {
panic(err)
}
http := server.NewHttpServer(lg.With(zap.String("context", "server")), &cfg.Http)
http := server.NewHttpServer(lg.With(zap.String("context", "server")), &cfg)
rh, err := ring.NewRingHandler(lg.With(zap.String("context", "ring")), &cfg.Ring)
if err != nil {
panic(err)
}
err = rh.Watch(ctx)
if err != nil {
panic(err)
}
err = webrtc.NewWebrtcHandler(ctx, lg.With(zap.String("context", "webrtc")), cfg.Stream(), http.Hndl)
if err != nil {
+9
View File
@@ -12,6 +12,7 @@ type Config struct {
AudioOut ConfigAudioOutputStream `arg:"group:AudioOut"`
AudioIn ConfigAudioInputStream `arg:"group:AudioIn"`
Logging ConfigLogging `arg:"group:Logging"`
Ring ConfigRing `arg:"group:Ring"`
Http ConfigHTTP `arg:"group:Http"`
}
@@ -25,6 +26,14 @@ type ConfigLogging struct {
Level string `arg:"--log-level,env:LOG_LEVEL" default:"debug"`
}
type ConfigRing struct {
Device string `arg:"--input-device,env:INPUT_DEVICE" default:"/dev/input/by-path/platform-gpio-keys-user-event"`
Key string `arg:"--ring-key" default:"KEY_F1"`
JingleName string `arg:"--jingle-name,env:JINGLE_NAME" default:"ding-dong.wav"`
JinglePath *string `arg:"--jingle-path,env:JINGLE_PATH"`
SonosTarget string `arg:"--sonos-target,env:SONOS_TARGET" default:"Living Room"`
}
type ConfigHTTP struct {
Host string `arg:"--http-host,env:HTTP_HOST" default:"0.0.0.0"`
Port uint `arg:"--http-port,env:HTTP_PORT" default:"8080"`
+74
View File
@@ -0,0 +1,74 @@
package ring
import (
"context"
"fmt"
"net/url"
"github.com/holoplot/go-evdev"
"github.com/kaedwen/webrtc/pkg/common"
"github.com/kaedwen/webrtc/pkg/ring/sonos"
"go.uber.org/zap"
)
type Player interface {
Play(uri *url.URL) error
}
type RingHandler struct {
lg *zap.Logger
cfg *common.ConfigRing
players []Player
}
func NewRingHandler(lg *zap.Logger, cfg *common.ConfigRing) (*RingHandler, error) {
sp, err := sonos.NewSonosPlayer(lg.With(zap.String("context", "sonos")), cfg.SonosTarget)
if err != nil {
return nil, err
}
return &RingHandler{lg, cfg, []Player{sp}}, nil
}
func (h *RingHandler) Watch(ctx context.Context) error {
d, err := evdev.Open(h.cfg.Device)
if err != nil {
return err
}
vMajor, vMinor, vMicro := d.DriverVersion()
h.lg.Info("input driver running", zap.String("version", fmt.Sprintf("%d.%d.%d", vMajor, vMinor, vMicro)))
key := evdev.KEYFromString[h.cfg.Key]
bu := url.URL{
Scheme: "http",
Host: "192.168.60.141:9099",
}
go func() {
err := d.NonBlock()
if err != nil {
h.lg.Fatal("failed to set non block", zap.Error(err))
}
for {
e, err := d.ReadOne()
if err == nil && e.Code == key && e.Value == 0 {
tu := bu.JoinPath(h.cfg.JingleName)
for _, p := range h.players {
if err := p.Play(tu); err != nil {
h.lg.Error("failed to play", zap.Error(err))
}
}
}
}
}()
go func() {
<-ctx.Done()
_ = d.Close()
}()
return nil
}
+55
View File
@@ -0,0 +1,55 @@
package sonos
import (
"errors"
"net/url"
"time"
so "github.com/szatmary/sonos"
"go.uber.org/zap"
)
type SonosPlayer struct {
lg *zap.Logger
zp *so.ZonePlayer
}
func NewSonosPlayer(lg *zap.Logger, target string) (*SonosPlayer, error) {
zp, err := SearchTarget(lg, target)
if err != nil {
return nil, err
}
return &SonosPlayer{lg, zp}, nil
}
func (p *SonosPlayer) Play(uri *url.URL) error {
err := p.zp.SetAVTransportURI(uri.String())
if err != nil {
return err
}
return p.zp.Play()
}
func SearchTarget(lg *zap.Logger, target string) (*so.ZonePlayer, error) {
son, err := so.NewSonos()
if err != nil {
return nil, err
}
defer son.Close()
found, _ := son.Search()
to := time.After(10 * time.Second)
for {
select {
case <-to:
return nil, errors.New("timeout")
case zp := <-found:
lg.Info("found player", zap.String("name", zp.RoomName()))
if zp.RoomName() == target {
return zp, nil
}
}
}
}
+7 -7
View File
@@ -25,7 +25,7 @@ type SignalingHandle struct {
type HttpServer struct {
http.Server
lg *zap.Logger
cfg *common.ConfigHTTP
cfg *common.Config
Hndl chan *SignalingHandle
}
@@ -37,7 +37,7 @@ func NewSignalingHandle(id string) SignalingHandle {
}
}
func NewHttpServer(lg *zap.Logger, cfg *common.ConfigHTTP) *HttpServer {
func NewHttpServer(lg *zap.Logger, cfg *common.Config) *HttpServer {
h := HttpServer{
Hndl: make(chan *SignalingHandle, 10),
cfg: cfg,
@@ -57,12 +57,12 @@ func NewHttpServer(lg *zap.Logger, cfg *common.ConfigHTTP) *HttpServer {
}
func (h *HttpServer) ListenAndServe(ctx context.Context) error {
if h.cfg.Tls {
if h.cfg.Http.Tls {
// set the configured address
h.Addr = h.cfg.Address()
h.Addr = h.cfg.Http.Address()
if h.cfg.TlsCert != nil && h.cfg.TlsKey != nil {
cert, err := tls.LoadX509KeyPair(*h.cfg.TlsCert, *h.cfg.TlsKey)
if h.cfg.Http.TlsCert != nil && h.cfg.Http.TlsKey != nil {
cert, err := tls.LoadX509KeyPair(*h.cfg.Http.TlsCert, *h.cfg.Http.TlsKey)
if err != nil {
return err
}
@@ -94,7 +94,7 @@ func (h *HttpServer) ListenAndServe(ctx context.Context) error {
}()
} else {
// set the configured address
h.Addr = h.cfg.Address()
h.Addr = h.cfg.Http.Address()
go func() {
// and listen
+9 -3
View File
@@ -38,9 +38,15 @@ func (s staticDiskSource) Open(p string) (common.StaticSourceFile, error) {
return &staticSourceFile{t}, nil
}
func SetupHandler(e *gin.Engine, cfg *common.ConfigHTTP) {
if cfg.StaticPath != nil {
handler := common.NewStaticHandler(staticDiskSource{*cfg.StaticPath}, "index.html")
func SetupHandler(e *gin.Engine, cfg *common.Config) {
if cfg.Ring.JinglePath != nil {
e.GET(cfg.Ring.JingleName, func(c *gin.Context) {
c.File(path.Join(*cfg.Ring.JinglePath, cfg.Ring.JingleName))
})
}
if cfg.Http.StaticPath != nil {
handler := common.NewStaticHandler(staticDiskSource{*cfg.Http.StaticPath}, "index.html")
e.NoRoute(func(c *gin.Context) {
encoding := c.Request.Header.Get("Accept-Encoding")
+7 -1
View File
@@ -41,7 +41,13 @@ func (s staticSource) Open(p string) (common.StaticSourceFile, error) {
return &staticSourceFile{t}, nil
}
func SetupHandler(e *gin.Engine, _ *common.ConfigHTTP) {
func SetupHandler(e *gin.Engine, cfg *common.Config) {
if cfg.Ring.JinglePath != nil {
e.GET(cfg.Ring.JingleName, func(c *gin.Context) {
c.File(path.Join(*cfg.Ring.JinglePath, cfg.Ring.JingleName))
})
}
handler := common.NewStaticHandler(staticSource{"dist"}, "index.html")
e.NoRoute(func(c *gin.Context) {
encoding := c.Request.Header.Get("Accept-Encoding")
+2
View File
@@ -0,0 +1,2 @@
/evtest
/uinputtest
+23
View File
@@ -0,0 +1,23 @@
MIT License
Copyright (c) 2019 Holoplot GmbH
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+48
View File
@@ -0,0 +1,48 @@
# Go support for the Linux evdev interface
This is a pure Go package for the Linux evdev interface, without cgo dependencies.
The Linux evdev interface is the userspace interface to interact with input devices such as
keyboard, mice, joysticks, touchscreens, rotary encoders etc.
The implementation in this package has the following features:
* Query device information such as the name, the physical location, the unique ID,
the vendor/product/bus/version IDs
* Query supported event types, codes and device properties
* Query the current status of bit-field based input types (such as keyboard, switches etc)
as well as information on absolute types (`ABS_X`, ...) including their min/max values and
current state
* Grab/Ungrab/Revoke support for exclusive claiming of devices
* Auto-generated `const` definitions and maps for types and codes from the kernel include headers
# Install
```
go get github.com/holoplot/go-evdev
```
And then use it in your source code.
```
import "github.com/holoplot/go-evdev"
```
# Re-generating codes.go
To re-generate `codes.go` from the latest kernel headers, use the following command.
```
go run build/gen-codes/main.go
gofmt codes.go
```
You can optionally validate generated string mappings with `go run build/gen-codes-validate/main.go`
# Example
See the code in `cmd/evtest` for an example.
# MIT License
See file `LICENSE` for details.
+33
View File
@@ -0,0 +1,33 @@
package evdev
type bitmap struct {
bits []byte
}
func (bm *bitmap) bitIsSet(bit int) bool {
if bit > len(bm.bits)*8 {
return false
}
return bm.bits[bit/8]&(1<<(bit%8)) != 0
}
func (bm *bitmap) setBits() []int {
var a []int
for i, by := range bm.bits {
for bit := 0; bit < 8; bit++ {
if by&byte(1<<bit) != 0 {
a = append(a, (i*8)+bit)
}
}
}
return a
}
func newBitmap(bits []byte) *bitmap {
return &bitmap{
bits: bits,
}
}
+3751
View File
File diff suppressed because it is too large Load Diff
+261
View File
@@ -0,0 +1,261 @@
package evdev
import (
"encoding/binary"
"fmt"
"os"
"syscall"
)
// InputDevice represent a Linux kernel input device in userspace.
// It can be used to query and write device properties, read input events,
// or grab it for exclusive access.
type InputDevice struct {
file *os.File
driverVersion int32
}
// Open creates a new InputDevice from the given path. Returns an error if
// the device node could not be opened or its properties failed to read.
func Open(path string) (*InputDevice, error) {
d := &InputDevice{}
var err error
d.file, err = os.OpenFile(path, os.O_RDWR, 0)
if err != nil {
return nil, err
}
d.driverVersion, err = ioctlEVIOCGVERSION(d.file.Fd())
if err != nil {
return nil, fmt.Errorf("cannot get driver version: %v", err)
}
return d, nil
}
// OpenByName creates a new InputDevice from the device name as reported by the kernel.
// Returns an error if the name does not exist, or the device node could
// not be opened or its properties failed to read.
func OpenByName(name string) (*InputDevice, error) {
devices, err := ListDevicePaths()
if err != nil {
return nil, err
}
for _, d := range devices {
if d.Name == name {
return Open(d.Path)
}
}
return nil, fmt.Errorf("could not find input device with name %q", name)
}
// Close releases the resources held by an InputDevice. After calling this
// function, the InputDevice is no longer operational.
func (d *InputDevice) Close() error {
return d.file.Close()
}
// Path returns the device's node path it was opened under.
func (d *InputDevice) Path() string {
return d.file.Name()
}
// DriverVersion returns the version of the Linux Evdev driver.
// The three ints returned by this function describe the major, minor and
// micro parts of the version code.
func (d *InputDevice) DriverVersion() (int, int, int) {
return int(d.driverVersion >> 16),
int((d.driverVersion >> 8) & 0xff),
int((d.driverVersion >> 0) & 0xff)
}
// Name returns the device's name as reported by the kernel.
func (d *InputDevice) Name() (string, error) {
return ioctlEVIOCGNAME(d.file.Fd())
}
// PhysicalLocation returns the device's physical location as reported by the kernel.
func (d *InputDevice) PhysicalLocation() (string, error) {
return ioctlEVIOCGPHYS(d.file.Fd())
}
// UniqueID returns the device's unique identifier as reported by the kernel.
func (d *InputDevice) UniqueID() (string, error) {
return ioctlEVIOCGUNIQ(d.file.Fd())
}
// InputID returns the device's vendor/product/busType/version information as reported by the kernel.
func (d *InputDevice) InputID() (InputID, error) {
return ioctlEVIOCGID(d.file.Fd())
}
// CapableTypes returns a slice of EvType that are the device supports
func (d *InputDevice) CapableTypes() []EvType {
var types []EvType
evBits, err := ioctlEVIOCGBIT(d.file.Fd(), 0)
if err != nil {
return []EvType{}
}
evBitmap := newBitmap(evBits)
for _, t := range evBitmap.setBits() {
types = append(types, EvType(t))
}
return types
}
// CapableEvents returns a slice of EvCode that are the device supports for given EvType
func (d *InputDevice) CapableEvents(t EvType) []EvCode {
var codes []EvCode
evBits, err := ioctlEVIOCGBIT(d.file.Fd(), int(t))
if err != nil {
return []EvCode{}
}
evBitmap := newBitmap(evBits)
for _, t := range evBitmap.setBits() {
codes = append(codes, EvCode(t))
}
return codes
}
// Properties returns a slice of EvProp that are the device supports
func (d *InputDevice) Properties() []EvProp {
var props []EvProp
propBits, err := ioctlEVIOCGPROP(d.file.Fd())
if err != nil {
return []EvProp{}
}
propBitmap := newBitmap(propBits)
for _, p := range propBitmap.setBits() {
props = append(props, EvProp(p))
}
return props
}
// State return a StateMap for the given type. The map will be empty if the requested type
// is not supported by the device.
func (d *InputDevice) State(t EvType) (StateMap, error) {
fd := d.file.Fd()
evBits, err := ioctlEVIOCGBIT(fd, 0)
if err != nil {
return nil, fmt.Errorf("cannot get evBits: %v", err)
}
evBitmap := newBitmap(evBits)
if !evBitmap.bitIsSet(int(t)) {
return StateMap{}, nil
}
codeBits, err := ioctlEVIOCGBIT(fd, int(t))
if err != nil {
return nil, fmt.Errorf("cannot get evBits: %v", err)
}
codeBitmap := newBitmap(codeBits)
var stateBits []byte
switch t {
case EV_KEY:
stateBits, err = ioctlEVIOCGKEY(fd)
case EV_SW:
stateBits, err = ioctlEVIOCGSW(fd)
case EV_LED:
stateBits, err = ioctlEVIOCGLED(fd)
case EV_SND:
stateBits, err = ioctlEVIOCGSND(fd)
default:
err = fmt.Errorf("unsupported evType %d", t)
}
if err != nil {
return nil, err
}
stateBitmap := newBitmap(stateBits)
st := StateMap{}
for _, code := range codeBitmap.setBits() {
st[EvCode(code)] = stateBitmap.bitIsSet(code)
}
return st, nil
}
// AbsInfos returns the AbsInfo struct for all axis the device supports.
func (d *InputDevice) AbsInfos() (map[EvCode]AbsInfo, error) {
a := make(map[EvCode]AbsInfo)
absBits, err := ioctlEVIOCGBIT(d.file.Fd(), EV_ABS)
if err != nil {
return nil, fmt.Errorf("cannot get absBits: %v", err)
}
absBitmap := newBitmap(absBits)
for _, abs := range absBitmap.setBits() {
absInfo, err := ioctlEVIOCGABS(d.file.Fd(), abs)
if err == nil {
a[EvCode(abs)] = absInfo
}
}
return a, nil
}
// Grab grabs the device for exclusive access. No other process will receive
// input events until the device instance is active.
func (d *InputDevice) Grab() error {
return ioctlEVIOCGRAB(d.file.Fd(), 1)
}
// Ungrab releases a previously taken exclusive use with Grab().
func (d *InputDevice) Ungrab() error {
return ioctlEVIOCGRAB(d.file.Fd(), 0)
}
// Revoke revokes device access
func (d *InputDevice) Revoke() error {
return ioctlEVIOCREVOKE(d.file.Fd())
}
// NonBlock sets file descriptor into nonblocking mode.
// This way it is possible to interrupt ReadOne call by closing the device.
// Note: file.Fd() call will set file descriptor back to blocking mode so make sure your program
// is not using any other method than ReadOne after NonBlock call.
func (d *InputDevice) NonBlock() error {
return syscall.SetNonblock(int(d.file.Fd()), true)
}
// ReadOne reads one InputEvent from the device. It blocks until an event has
// been received or an error has occurred.
func (d *InputDevice) ReadOne() (*InputEvent, error) {
event := InputEvent{}
err := binary.Read(d.file, binary.LittleEndian, &event)
if err != nil {
return nil, err
}
return &event, nil
}
// WriteOne writes one InputEvent to the device.
// Useful for controlling LEDs of the device
func (d *InputDevice) WriteOne(event *InputEvent) error {
return binary.Write(d.file, binary.LittleEndian, event)
}
+274
View File
@@ -0,0 +1,274 @@
package evdev
import (
"errors"
"fmt"
"strings"
"syscall"
"unsafe"
)
const (
ioctlDirNone = 0x0
ioctlDirWrite = 0x1
ioctlDirRead = 0x2
)
func trimNull(s string) string {
return strings.Trim(s, "\x00")
}
func ioctlMakeCode(dir, typ, nr int, size uintptr) uint32 {
var code uint32
if dir > ioctlDirWrite|ioctlDirRead {
panic(fmt.Errorf("invalid ioctl dir value: %d", dir))
}
if size > 1<<14 {
panic(fmt.Errorf("invalid ioctl size value: %d", size))
}
code |= uint32(dir) << 30
code |= uint32(size) << 16
code |= uint32(typ) << 8
code |= uint32(nr)
return code
}
func doIoctl(fd uintptr, code uint32, ptr unsafe.Pointer) error {
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(code), uintptr(ptr))
if errno != 0 {
return errors.New(errno.Error())
}
return nil
}
func ioctlEVIOCGVERSION(fd uintptr) (int32, error) {
version := int32(0)
code := ioctlMakeCode(ioctlDirRead, 'E', 0x01, unsafe.Sizeof(version))
err := doIoctl(fd, code, unsafe.Pointer(&version))
return version, err
}
func ioctlEVIOCGID(fd uintptr) (InputID, error) {
id := InputID{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x02, unsafe.Sizeof(id))
err := doIoctl(fd, code, unsafe.Pointer(&id))
return id, err
}
func ioctlEVIOCGREP(fd uintptr) ([2]uint32, error) {
rep := [2]uint32{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x03, unsafe.Sizeof(rep))
err := doIoctl(fd, code, unsafe.Pointer(&rep))
return rep, err
}
func ioctlEVIOCSREP(fd uintptr, rep [2]uint32) error {
code := ioctlMakeCode(ioctlDirWrite, 'E', 0x03, unsafe.Sizeof(rep))
return doIoctl(fd, code, unsafe.Pointer(&rep))
}
func ioctlEVIOCGKEYCODE(fd uintptr) (InputKeymapEntry, error) {
entry := InputKeymapEntry{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x04, unsafe.Sizeof(entry))
err := doIoctl(fd, code, unsafe.Pointer(&entry))
return entry, err
}
func ioctlEVIOCSKEYCODE(fd uintptr, entry InputKeymapEntry) error {
code := ioctlMakeCode(ioctlDirWrite, 'E', 0x04, unsafe.Sizeof(entry))
return doIoctl(fd, code, unsafe.Pointer(&entry))
}
func ioctlEVIOCGNAME(fd uintptr) (string, error) {
str := [256]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x06, unsafe.Sizeof(str))
err := doIoctl(fd, code, unsafe.Pointer(&str))
return trimNull(string(str[:])), err
}
func ioctlEVIOCGPHYS(fd uintptr) (string, error) {
str := [256]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x07, unsafe.Sizeof(str))
err := doIoctl(fd, code, unsafe.Pointer(&str))
return trimNull(string(str[:])), err
}
func ioctlEVIOCGUNIQ(fd uintptr) (string, error) {
str := [256]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x08, unsafe.Sizeof(str))
err := doIoctl(fd, code, unsafe.Pointer(&str))
return trimNull(string(str[:])), err
}
func ioctlEVIOCGPROP(fd uintptr) ([]byte, error) {
bits := [256]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x09, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:], err
}
func ioctlEVIOCGKEY(fd uintptr) ([]byte, error) {
bits := [KEY_MAX]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x18, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:], err
}
func ioctlEVIOCGLED(fd uintptr) ([]byte, error) {
bits := [LED_MAX]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x19, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:], err
}
func ioctlEVIOCGSND(fd uintptr) ([]byte, error) {
bits := [SND_MAX]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x1a, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:], err
}
func ioctlEVIOCGSW(fd uintptr) ([]byte, error) {
bits := [SW_MAX]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x1b, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:], err
}
func ioctlEVIOCGBIT(fd uintptr, evtype int) ([]byte, error) {
var cnt int
switch evtype {
case 0:
// special case, indicating the list of all feature types supported should be returned,
// rather than the list of particular features for that type
cnt = EV_CNT
case EV_KEY:
cnt = KEY_CNT
case EV_REL:
cnt = REL_CNT
case EV_ABS:
cnt = ABS_CNT
case EV_MSC:
cnt = MSC_CNT
case EV_SW:
cnt = SW_CNT
case EV_LED:
cnt = LED_CNT
case EV_SND:
cnt = SND_CNT
case EV_REP:
cnt = REP_CNT
case EV_FF:
cnt = FF_CNT
default: // EV_PWR, EV_FF_STATUS ??
cnt = KEY_MAX
}
bytesNumber := (cnt + 7) / 8
bits := [KEY_MAX]byte{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x20+evtype, unsafe.Sizeof(bits))
err := doIoctl(fd, code, unsafe.Pointer(&bits))
return bits[:bytesNumber], err
}
func ioctlEVIOCGABS(fd uintptr, abs int) (AbsInfo, error) {
info := AbsInfo{}
code := ioctlMakeCode(ioctlDirRead, 'E', 0x40+abs, unsafe.Sizeof(info))
err := doIoctl(fd, code, unsafe.Pointer(&info))
return info, err
}
func ioctlEVIOCSABS(fd uintptr, abs int, info AbsInfo) error {
code := ioctlMakeCode(ioctlDirWrite, 'E', 0xc0+abs, unsafe.Sizeof(info))
return doIoctl(fd, code, unsafe.Pointer(&info))
}
func ioctlEVIOCGRAB(fd uintptr, p int32) error {
code := ioctlMakeCode(ioctlDirWrite, 'E', 0x90, unsafe.Sizeof(p))
if p != 0 {
return doIoctl(fd, code, unsafe.Pointer(&p))
}
return doIoctl(fd, code, nil)
}
func ioctlEVIOCREVOKE(fd uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'E', 0x91, unsafe.Sizeof(p))
return doIoctl(fd, code, nil)
}
func ioctlUISETEVBIT(fd uintptr, ev uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 100, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(ev))
}
func ioctlUISETKEYBIT(fd uintptr, key uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 101, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(key))
}
func ioctlUISETRELBIT(fd uintptr, rel uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 102, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(rel))
}
func ioctlUISETABSBIT(fd uintptr, abs uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 103, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(abs))
}
func ioctlUISETMSCBIT(fd uintptr, msc uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 104, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(msc))
}
func ioctlUISETLEDBIT(fd uintptr, led uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 105, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(led))
}
func ioctlUISETSNDBIT(fd uintptr, snd uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 106, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(snd))
}
func ioctlUISETFFBIT(fd uintptr, fe uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 107, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(fe))
}
func ioctlUISETSWBIT(fd uintptr, sw uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 109, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(sw))
}
func ioctlUISETPROPBIT(fd uintptr, prop uintptr) error {
var p int32
code := ioctlMakeCode(ioctlDirWrite, 'U', 110, unsafe.Sizeof(p))
return doIoctl(fd, code, unsafe.Pointer(prop))
}
func ioctlUIDEVCREATE(fd uintptr) error {
code := ioctlMakeCode(ioctlDirNone, 'U', 1, 0)
return doIoctl(fd, code, nil)
}
func ioctlUIDEVDESTROY(fd uintptr) error {
code := ioctlMakeCode(ioctlDirNone, 'U', 2, 0)
return doIoctl(fd, code, nil)
}
+39
View File
@@ -0,0 +1,39 @@
package evdev
import (
"fmt"
"io/ioutil"
)
// InputPath contains information about an InputDevice Name & Path
type InputPath struct {
Name string
Path string
}
// ListDevicePaths lists all available input devices, returning their
// filename path, and the name as reported by the kernel.
func ListDevicePaths() ([]InputPath, error) {
var list []InputPath
basePath := "/dev/input"
files, err := ioutil.ReadDir(basePath)
if err != nil {
return list, err
}
for _, fileName := range files {
if fileName.IsDir() {
continue
}
full := fmt.Sprintf("%s/%s", basePath, fileName.Name())
if d, err := Open(full); err == nil {
name, _ := d.Name()
list = append(list, InputPath{Name: name, Path: d.Path()})
d.Close()
}
}
return list, nil
}
+43
View File
@@ -0,0 +1,43 @@
package evdev
var EvCodeNameLookup = map[EvType]map[EvCode]string{
EV_SYN: SYNNames,
EV_KEY: KEYNames,
EV_REL: RELNames,
EV_ABS: ABSNames,
EV_MSC: MSCNames,
EV_SW: SWNames,
EV_LED: LEDNames,
EV_SND: SNDNames,
EV_REP: REPNames,
EV_FF: FFNames,
// EV_PWR:
// EV_FF_STATUS:
}
// TypeName returns the name of an EvType as string, or "UNKNOWN" if the type is not valid
func TypeName(t EvType) string {
name, ok := EVToString[t]
if ok {
return name
}
return "unknown"
}
// PropName returns the name of the given EvProp, or "UNKNOWN" if the property is not valid
func PropName(p EvProp) string {
name, ok := INPUTToString[p]
if ok {
return name
}
return "unknown"
}
// CodeName returns the name of an EvfCode in the given EvType, or "UNKNOWN" of the code is not valid.
func CodeName(t EvType, c EvCode) string {
name, ok := EvCodeNameLookup[t][c]
if !ok {
return "unknown"
}
return name
}
+86
View File
@@ -0,0 +1,86 @@
package evdev
import (
"fmt"
"syscall"
)
// EvType is EV_KEY, EV_SW, EV_LED, EV_SND, ...
type EvType uint16
// EvCode describes codes within a type (eg. KEY_A, KEY_B, ...)
type EvCode uint16
// EvProp describes device properties (eg. INPUT_PROP_ACCELEROMETER, INPUT_PROP_BUTTONPAD, ...)
type EvProp uint16
// StateMap describes the current state of codes within a type, as booleans.
type StateMap map[EvCode]bool
// InputEvent describes an event that is generated by an InputDevice
type InputEvent struct {
Time syscall.Timeval // time in seconds since epoch at which event occurred
Type EvType // event type - one of ecodes.EV_*
Code EvCode // event code related to the event type
Value int32 // event value related to the event type
}
func (e *InputEvent) TypeName() string {
return TypeName(e.Type)
}
func (e *InputEvent) CodeName() string {
return CodeName(e.Type, e.Code)
}
func (e *InputEvent) String() string {
return fmt.Sprintf(
"type: 0x%02x [%s], code: 0x%02x [%s], value: %d",
e.Type, e.TypeName(), e.Code, e.CodeName(), e.Value,
)
}
// InputID ...
type InputID struct {
BusType uint16
Vendor uint16
Product uint16
Version uint16
}
// AbsInfo describes details on ABS input types
type AbsInfo struct {
Value int32
Minimum int32
Maximum int32
Fuzz int32
Flat int32
Resolution int32
}
// InputKeymapEntry is used to retrieve and modify keymap data
type InputKeymapEntry struct {
Flags uint8
Len uint8
Index uint16
KeyCode uint32
ScanCode [32]uint8
}
// InputMask ...
type InputMask struct {
Type uint32
CodesSize uint32
CodesPtr uint64
}
// UinputUserDevice is used when creating or cloning a device
type UinputUserDevice struct {
Name [uinputMaxNameSize]byte
ID InputID
EffectsMax uint32
Absmax [absSize]int32
Absmin [absSize]int32
Absfuzz [absSize]int32
Absflat [absSize]int32
}
+160
View File
@@ -0,0 +1,160 @@
package evdev
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"syscall"
)
const (
uinputMaxNameSize = 80
absSize = 64
)
// CreateDevice creates a device from scratch with the provided capabilities and name
// If set up fails the device will be removed from the system,
// once set up it can be removed by calling dev.Close
func CreateDevice(name string, id InputID, capabilities map[EvType][]EvCode) (*InputDevice, error) {
deviceFile, err := os.OpenFile("/dev/uinput", syscall.O_WRONLY|syscall.O_NONBLOCK, 0660)
if err != nil {
return nil, err
}
newDev := &InputDevice{
file: deviceFile,
}
for ev, codes := range capabilities {
if err := ioctlUISETEVBIT(newDev.file.Fd(), uintptr(ev)); err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to set ev bit: %d - %w", ev, err)
}
if err := setEventCodes(newDev, ev, codes); err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to set ev code: %w", err)
}
}
if _, err = createInputDevice(newDev.file, UinputUserDevice{
Name: toUinputName([]byte(name)),
ID: id,
}); err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to create device: %w", err)
}
return newDev, nil
}
// CloneDevice creates a new device from an existing one
// all capabilites will be coppied over to the new virtual device
// If set up fails the device will be removed from the system,
// once set up it can be removed by calling dev.Close
func CloneDevice(name string, dev *InputDevice) (*InputDevice, error) {
deviceFile, err := os.OpenFile("/dev/uinput", syscall.O_WRONLY|syscall.O_NONBLOCK, 0660)
if err != nil {
return nil, err
}
newDev := &InputDevice{
file: deviceFile,
driverVersion: dev.driverVersion,
}
for _, ev := range dev.CapableTypes() {
if err := ioctlUISETEVBIT(newDev.file.Fd(), uintptr(ev)); err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to set ev bit: %d - %w", ev, err)
}
eventCodes := dev.CapableEvents(ev)
if err := setEventCodes(newDev, ev, eventCodes); err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to set ev code: %w", err)
}
}
id, err := dev.InputID()
if err != nil {
DestroyDevice(newDev)
return nil, fmt.Errorf("failed to get original device id: %w", err)
}
if _, err = createInputDevice(newDev.file, UinputUserDevice{
Name: toUinputName([]byte(name)),
ID: id,
}); err != nil {
return nil, fmt.Errorf("failed to create device: %w", err)
}
return newDev, nil
}
// Destroy destroys an input device, removing it from the system
// This is designed to be called on self created virtual devices and may fail if called
// on real devices attached to the system
func DestroyDevice(dev *InputDevice) error {
return ioctlUIDEVDESTROY(dev.file.Fd())
}
func setEventCodes(dev *InputDevice, ev EvType, codes []EvCode) error {
for _, code := range codes {
var err error
switch ev {
case EV_ABS:
err = ioctlUISETABSBIT(dev.file.Fd(), uintptr(code))
case EV_FF:
err = ioctlUISETFFBIT(dev.file.Fd(), uintptr(code))
case EV_KEY:
err = ioctlUISETKEYBIT(dev.file.Fd(), uintptr(code))
case EV_LED:
err = ioctlUISETLEDBIT(dev.file.Fd(), uintptr(code))
case EV_MSC:
err = ioctlUISETMSCBIT(dev.file.Fd(), uintptr(code))
case EV_REL:
err = ioctlUISETRELBIT(dev.file.Fd(), uintptr(code))
case EV_SND:
err = ioctlUISETSNDBIT(dev.file.Fd(), uintptr(code))
case EV_SW:
err = ioctlUISETSWBIT(dev.file.Fd(), uintptr(code))
}
if err != nil {
return err
}
}
return nil
}
func toUinputName(name []byte) (uinputName [uinputMaxNameSize]byte) {
var fixedSizeName [uinputMaxNameSize]byte
copy(fixedSizeName[:], name)
return fixedSizeName
}
func createInputDevice(file *os.File, dev UinputUserDevice) (fd *os.File, err error) {
buf := new(bytes.Buffer)
if err = binary.Write(buf, binary.LittleEndian, dev); err != nil {
file.Close()
return nil, fmt.Errorf("failed to write user device buffer: %w", err)
}
if _, err = file.Write(buf.Bytes()); err != nil {
file.Close()
return nil, fmt.Errorf("failed to write uidev struct to device file: %w", err)
}
if err = ioctlUIDEVCREATE(file.Fd()); err != nil {
file.Close()
return nil, fmt.Errorf("failed to create device: %w", err)
}
return file, nil
}
+12
View File
@@ -0,0 +1,12 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
File diff suppressed because it is too large Load Diff
+593
View File
@@ -0,0 +1,593 @@
package alarmclock
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:AlarmClock:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/AlarmClock/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/AlarmClock/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
SetFormat *SetFormatArgs `xml:"u:SetFormat,omitempty"`
GetFormat *GetFormatArgs `xml:"u:GetFormat,omitempty"`
SetTimeZone *SetTimeZoneArgs `xml:"u:SetTimeZone,omitempty"`
GetTimeZone *GetTimeZoneArgs `xml:"u:GetTimeZone,omitempty"`
GetTimeZoneAndRule *GetTimeZoneAndRuleArgs `xml:"u:GetTimeZoneAndRule,omitempty"`
GetTimeZoneRule *GetTimeZoneRuleArgs `xml:"u:GetTimeZoneRule,omitempty"`
SetTimeServer *SetTimeServerArgs `xml:"u:SetTimeServer,omitempty"`
GetTimeServer *GetTimeServerArgs `xml:"u:GetTimeServer,omitempty"`
SetTimeNow *SetTimeNowArgs `xml:"u:SetTimeNow,omitempty"`
GetHouseholdTimeAtStamp *GetHouseholdTimeAtStampArgs `xml:"u:GetHouseholdTimeAtStamp,omitempty"`
GetTimeNow *GetTimeNowArgs `xml:"u:GetTimeNow,omitempty"`
CreateAlarm *CreateAlarmArgs `xml:"u:CreateAlarm,omitempty"`
UpdateAlarm *UpdateAlarmArgs `xml:"u:UpdateAlarm,omitempty"`
DestroyAlarm *DestroyAlarmArgs `xml:"u:DestroyAlarm,omitempty"`
ListAlarms *ListAlarmsArgs `xml:"u:ListAlarms,omitempty"`
SetDailyIndexRefreshTime *SetDailyIndexRefreshTimeArgs `xml:"u:SetDailyIndexRefreshTime,omitempty"`
GetDailyIndexRefreshTime *GetDailyIndexRefreshTimeArgs `xml:"u:GetDailyIndexRefreshTime,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
SetFormat *SetFormatResponse `xml:"SetFormatResponse,omitempty"`
GetFormat *GetFormatResponse `xml:"GetFormatResponse,omitempty"`
SetTimeZone *SetTimeZoneResponse `xml:"SetTimeZoneResponse,omitempty"`
GetTimeZone *GetTimeZoneResponse `xml:"GetTimeZoneResponse,omitempty"`
GetTimeZoneAndRule *GetTimeZoneAndRuleResponse `xml:"GetTimeZoneAndRuleResponse,omitempty"`
GetTimeZoneRule *GetTimeZoneRuleResponse `xml:"GetTimeZoneRuleResponse,omitempty"`
SetTimeServer *SetTimeServerResponse `xml:"SetTimeServerResponse,omitempty"`
GetTimeServer *GetTimeServerResponse `xml:"GetTimeServerResponse,omitempty"`
SetTimeNow *SetTimeNowResponse `xml:"SetTimeNowResponse,omitempty"`
GetHouseholdTimeAtStamp *GetHouseholdTimeAtStampResponse `xml:"GetHouseholdTimeAtStampResponse,omitempty"`
GetTimeNow *GetTimeNowResponse `xml:"GetTimeNowResponse,omitempty"`
CreateAlarm *CreateAlarmResponse `xml:"CreateAlarmResponse,omitempty"`
UpdateAlarm *UpdateAlarmResponse `xml:"UpdateAlarmResponse,omitempty"`
DestroyAlarm *DestroyAlarmResponse `xml:"DestroyAlarmResponse,omitempty"`
ListAlarms *ListAlarmsResponse `xml:"ListAlarmsResponse,omitempty"`
SetDailyIndexRefreshTime *SetDailyIndexRefreshTimeResponse `xml:"SetDailyIndexRefreshTimeResponse,omitempty"`
GetDailyIndexRefreshTime *GetDailyIndexRefreshTimeResponse `xml:"GetDailyIndexRefreshTimeResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type SetFormatArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredTimeFormat string `xml:"DesiredTimeFormat"`
DesiredDateFormat string `xml:"DesiredDateFormat"`
}
type SetFormatResponse struct {
}
func (s *Service) SetFormat(httpClient *http.Client, args *SetFormatArgs) (*SetFormatResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetFormat`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetFormat: args},
})
if err != nil {
return nil, err
}
if r.Body.SetFormat == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.SetFormat()`)
}
return r.Body.SetFormat, nil
}
type GetFormatArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetFormatResponse struct {
CurrentTimeFormat string `xml:"CurrentTimeFormat"`
CurrentDateFormat string `xml:"CurrentDateFormat"`
}
func (s *Service) GetFormat(httpClient *http.Client, args *GetFormatArgs) (*GetFormatResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetFormat`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetFormat: args},
})
if err != nil {
return nil, err
}
if r.Body.GetFormat == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetFormat()`)
}
return r.Body.GetFormat, nil
}
type SetTimeZoneArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Index int32 `xml:"Index"`
AutoAdjustDst bool `xml:"AutoAdjustDst"`
}
type SetTimeZoneResponse struct {
}
func (s *Service) SetTimeZone(httpClient *http.Client, args *SetTimeZoneArgs) (*SetTimeZoneResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetTimeZone`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetTimeZone: args},
})
if err != nil {
return nil, err
}
if r.Body.SetTimeZone == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeZone()`)
}
return r.Body.SetTimeZone, nil
}
type GetTimeZoneArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetTimeZoneResponse struct {
Index int32 `xml:"Index"`
AutoAdjustDst bool `xml:"AutoAdjustDst"`
}
func (s *Service) GetTimeZone(httpClient *http.Client, args *GetTimeZoneArgs) (*GetTimeZoneResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTimeZone`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTimeZone: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTimeZone == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZone()`)
}
return r.Body.GetTimeZone, nil
}
type GetTimeZoneAndRuleArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetTimeZoneAndRuleResponse struct {
Index int32 `xml:"Index"`
AutoAdjustDst bool `xml:"AutoAdjustDst"`
CurrentTimeZone string `xml:"CurrentTimeZone"`
}
func (s *Service) GetTimeZoneAndRule(httpClient *http.Client, args *GetTimeZoneAndRuleArgs) (*GetTimeZoneAndRuleResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTimeZoneAndRule`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTimeZoneAndRule: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTimeZoneAndRule == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZoneAndRule()`)
}
return r.Body.GetTimeZoneAndRule, nil
}
type GetTimeZoneRuleArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Index int32 `xml:"Index"`
}
type GetTimeZoneRuleResponse struct {
TimeZone string `xml:"TimeZone"`
}
func (s *Service) GetTimeZoneRule(httpClient *http.Client, args *GetTimeZoneRuleArgs) (*GetTimeZoneRuleResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTimeZoneRule`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTimeZoneRule: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTimeZoneRule == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeZoneRule()`)
}
return r.Body.GetTimeZoneRule, nil
}
type SetTimeServerArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredTimeServer string `xml:"DesiredTimeServer"`
}
type SetTimeServerResponse struct {
}
func (s *Service) SetTimeServer(httpClient *http.Client, args *SetTimeServerArgs) (*SetTimeServerResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetTimeServer`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetTimeServer: args},
})
if err != nil {
return nil, err
}
if r.Body.SetTimeServer == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeServer()`)
}
return r.Body.SetTimeServer, nil
}
type GetTimeServerArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetTimeServerResponse struct {
CurrentTimeServer string `xml:"CurrentTimeServer"`
}
func (s *Service) GetTimeServer(httpClient *http.Client, args *GetTimeServerArgs) (*GetTimeServerResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTimeServer`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTimeServer: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTimeServer == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeServer()`)
}
return r.Body.GetTimeServer, nil
}
type SetTimeNowArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredTime string `xml:"DesiredTime"`
TimeZoneForDesiredTime string `xml:"TimeZoneForDesiredTime"`
}
type SetTimeNowResponse struct {
}
func (s *Service) SetTimeNow(httpClient *http.Client, args *SetTimeNowArgs) (*SetTimeNowResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetTimeNow`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetTimeNow: args},
})
if err != nil {
return nil, err
}
if r.Body.SetTimeNow == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.SetTimeNow()`)
}
return r.Body.SetTimeNow, nil
}
type GetHouseholdTimeAtStampArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
TimeStamp string `xml:"TimeStamp"`
}
type GetHouseholdTimeAtStampResponse struct {
HouseholdUTCTime string `xml:"HouseholdUTCTime"`
}
func (s *Service) GetHouseholdTimeAtStamp(httpClient *http.Client, args *GetHouseholdTimeAtStampArgs) (*GetHouseholdTimeAtStampResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetHouseholdTimeAtStamp`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetHouseholdTimeAtStamp: args},
})
if err != nil {
return nil, err
}
if r.Body.GetHouseholdTimeAtStamp == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetHouseholdTimeAtStamp()`)
}
return r.Body.GetHouseholdTimeAtStamp, nil
}
type GetTimeNowArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetTimeNowResponse struct {
CurrentUTCTime string `xml:"CurrentUTCTime"`
CurrentLocalTime string `xml:"CurrentLocalTime"`
CurrentTimeZone string `xml:"CurrentTimeZone"`
CurrentTimeGeneration uint32 `xml:"CurrentTimeGeneration"`
}
func (s *Service) GetTimeNow(httpClient *http.Client, args *GetTimeNowArgs) (*GetTimeNowResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTimeNow`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTimeNow: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTimeNow == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetTimeNow()`)
}
return r.Body.GetTimeNow, nil
}
type CreateAlarmArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
StartLocalTime string `xml:"StartLocalTime"`
Duration string `xml:"Duration"`
// Allowed Value: ONCE
// Allowed Value: WEEKDAYS
// Allowed Value: WEEKENDS
// Allowed Value: DAILY
Recurrence string `xml:"Recurrence"`
Enabled bool `xml:"Enabled"`
RoomUUID string `xml:"RoomUUID"`
ProgramURI string `xml:"ProgramURI"`
ProgramMetaData string `xml:"ProgramMetaData"`
// Allowed Value: NORMAL
// Allowed Value: REPEAT_ALL
// Allowed Value: SHUFFLE_NOREPEAT
// Allowed Value: SHUFFLE
PlayMode string `xml:"PlayMode"`
Volume uint16 `xml:"Volume"`
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
}
type CreateAlarmResponse struct {
AssignedID uint32 `xml:"AssignedID"`
}
func (s *Service) CreateAlarm(httpClient *http.Client, args *CreateAlarmArgs) (*CreateAlarmResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`CreateAlarm`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{CreateAlarm: args},
})
if err != nil {
return nil, err
}
if r.Body.CreateAlarm == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.CreateAlarm()`)
}
return r.Body.CreateAlarm, nil
}
type UpdateAlarmArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ID uint32 `xml:"ID"`
StartLocalTime string `xml:"StartLocalTime"`
Duration string `xml:"Duration"`
// Allowed Value: ONCE
// Allowed Value: WEEKDAYS
// Allowed Value: WEEKENDS
// Allowed Value: DAILY
Recurrence string `xml:"Recurrence"`
Enabled bool `xml:"Enabled"`
RoomUUID string `xml:"RoomUUID"`
ProgramURI string `xml:"ProgramURI"`
ProgramMetaData string `xml:"ProgramMetaData"`
// Allowed Value: NORMAL
// Allowed Value: REPEAT_ALL
// Allowed Value: SHUFFLE_NOREPEAT
// Allowed Value: SHUFFLE
PlayMode string `xml:"PlayMode"`
Volume uint16 `xml:"Volume"`
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
}
type UpdateAlarmResponse struct {
}
func (s *Service) UpdateAlarm(httpClient *http.Client, args *UpdateAlarmArgs) (*UpdateAlarmResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`UpdateAlarm`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{UpdateAlarm: args},
})
if err != nil {
return nil, err
}
if r.Body.UpdateAlarm == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.UpdateAlarm()`)
}
return r.Body.UpdateAlarm, nil
}
type DestroyAlarmArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ID uint32 `xml:"ID"`
}
type DestroyAlarmResponse struct {
}
func (s *Service) DestroyAlarm(httpClient *http.Client, args *DestroyAlarmArgs) (*DestroyAlarmResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`DestroyAlarm`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{DestroyAlarm: args},
})
if err != nil {
return nil, err
}
if r.Body.DestroyAlarm == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.DestroyAlarm()`)
}
return r.Body.DestroyAlarm, nil
}
type ListAlarmsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type ListAlarmsResponse struct {
CurrentAlarmList string `xml:"CurrentAlarmList"`
CurrentAlarmListVersion string `xml:"CurrentAlarmListVersion"`
}
func (s *Service) ListAlarms(httpClient *http.Client, args *ListAlarmsArgs) (*ListAlarmsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ListAlarms`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ListAlarms: args},
})
if err != nil {
return nil, err
}
if r.Body.ListAlarms == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.ListAlarms()`)
}
return r.Body.ListAlarms, nil
}
type SetDailyIndexRefreshTimeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredDailyIndexRefreshTime string `xml:"DesiredDailyIndexRefreshTime"`
}
type SetDailyIndexRefreshTimeResponse struct {
}
func (s *Service) SetDailyIndexRefreshTime(httpClient *http.Client, args *SetDailyIndexRefreshTimeArgs) (*SetDailyIndexRefreshTimeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetDailyIndexRefreshTime`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetDailyIndexRefreshTime: args},
})
if err != nil {
return nil, err
}
if r.Body.SetDailyIndexRefreshTime == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.SetDailyIndexRefreshTime()`)
}
return r.Body.SetDailyIndexRefreshTime, nil
}
type GetDailyIndexRefreshTimeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetDailyIndexRefreshTimeResponse struct {
CurrentDailyIndexRefreshTime string `xml:"CurrentDailyIndexRefreshTime"`
}
func (s *Service) GetDailyIndexRefreshTime(httpClient *http.Client, args *GetDailyIndexRefreshTimeArgs) (*GetDailyIndexRefreshTimeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetDailyIndexRefreshTime`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetDailyIndexRefreshTime: args},
})
if err != nil {
return nil, err
}
if r.Body.GetDailyIndexRefreshTime == nil {
return nil, errors.New(`unexpected respose from service calling alarmclock.GetDailyIndexRefreshTime()`)
}
return r.Body.GetDailyIndexRefreshTime, nil
}
+174
View File
@@ -0,0 +1,174 @@
package connectionmanager
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:ConnectionManager:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaServer/ConnectionManager/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaServer/ConnectionManager/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
GetProtocolInfo *GetProtocolInfoArgs `xml:"u:GetProtocolInfo,omitempty"`
GetCurrentConnectionIDs *GetCurrentConnectionIDsArgs `xml:"u:GetCurrentConnectionIDs,omitempty"`
GetCurrentConnectionInfo *GetCurrentConnectionInfoArgs `xml:"u:GetCurrentConnectionInfo,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
GetProtocolInfo *GetProtocolInfoResponse `xml:"GetProtocolInfoResponse,omitempty"`
GetCurrentConnectionIDs *GetCurrentConnectionIDsResponse `xml:"GetCurrentConnectionIDsResponse,omitempty"`
GetCurrentConnectionInfo *GetCurrentConnectionInfoResponse `xml:"GetCurrentConnectionInfoResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type GetProtocolInfoArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetProtocolInfoResponse struct {
Source string `xml:"Source"`
Sink string `xml:"Sink"`
}
func (s *Service) GetProtocolInfo(httpClient *http.Client, args *GetProtocolInfoArgs) (*GetProtocolInfoResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetProtocolInfo`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetProtocolInfo: args},
})
if err != nil {
return nil, err
}
if r.Body.GetProtocolInfo == nil {
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetProtocolInfo()`)
}
return r.Body.GetProtocolInfo, nil
}
type GetCurrentConnectionIDsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetCurrentConnectionIDsResponse struct {
ConnectionIDs string `xml:"ConnectionIDs"`
}
func (s *Service) GetCurrentConnectionIDs(httpClient *http.Client, args *GetCurrentConnectionIDsArgs) (*GetCurrentConnectionIDsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetCurrentConnectionIDs`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetCurrentConnectionIDs: args},
})
if err != nil {
return nil, err
}
if r.Body.GetCurrentConnectionIDs == nil {
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetCurrentConnectionIDs()`)
}
return r.Body.GetCurrentConnectionIDs, nil
}
type GetCurrentConnectionInfoArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ConnectionID int32 `xml:"ConnectionID"`
}
type GetCurrentConnectionInfoResponse struct {
RcsID int32 `xml:"RcsID"`
AVTransportID int32 `xml:"AVTransportID"`
ProtocolInfo string `xml:"ProtocolInfo"`
PeerConnectionManager string `xml:"PeerConnectionManager"`
PeerConnectionID int32 `xml:"PeerConnectionID"`
Direction string `xml:"Direction"`
Status string `xml:"Status"`
}
func (s *Service) GetCurrentConnectionInfo(httpClient *http.Client, args *GetCurrentConnectionInfoArgs) (*GetCurrentConnectionInfoResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetCurrentConnectionInfo`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetCurrentConnectionInfo: args},
})
if err != nil {
return nil, err
}
if r.Body.GetCurrentConnectionInfo == nil {
return nil, errors.New(`unexpected respose from service calling connectionmanager.GetCurrentConnectionInfo()`)
}
return r.Body.GetCurrentConnectionInfo, nil
}
+539
View File
@@ -0,0 +1,539 @@
package contentdirectory
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:ContentDirectory:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaServer/ContentDirectory/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaServer/ContentDirectory/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
GetSearchCapabilities *GetSearchCapabilitiesArgs `xml:"u:GetSearchCapabilities,omitempty"`
GetSortCapabilities *GetSortCapabilitiesArgs `xml:"u:GetSortCapabilities,omitempty"`
GetSystemUpdateID *GetSystemUpdateIDArgs `xml:"u:GetSystemUpdateID,omitempty"`
GetAlbumArtistDisplayOption *GetAlbumArtistDisplayOptionArgs `xml:"u:GetAlbumArtistDisplayOption,omitempty"`
GetLastIndexChange *GetLastIndexChangeArgs `xml:"u:GetLastIndexChange,omitempty"`
Browse *BrowseArgs `xml:"u:Browse,omitempty"`
FindPrefix *FindPrefixArgs `xml:"u:FindPrefix,omitempty"`
GetAllPrefixLocations *GetAllPrefixLocationsArgs `xml:"u:GetAllPrefixLocations,omitempty"`
CreateObject *CreateObjectArgs `xml:"u:CreateObject,omitempty"`
UpdateObject *UpdateObjectArgs `xml:"u:UpdateObject,omitempty"`
DestroyObject *DestroyObjectArgs `xml:"u:DestroyObject,omitempty"`
RefreshShareIndex *RefreshShareIndexArgs `xml:"u:RefreshShareIndex,omitempty"`
RequestResort *RequestResortArgs `xml:"u:RequestResort,omitempty"`
GetShareIndexInProgress *GetShareIndexInProgressArgs `xml:"u:GetShareIndexInProgress,omitempty"`
GetBrowseable *GetBrowseableArgs `xml:"u:GetBrowseable,omitempty"`
SetBrowseable *SetBrowseableArgs `xml:"u:SetBrowseable,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
GetSearchCapabilities *GetSearchCapabilitiesResponse `xml:"GetSearchCapabilitiesResponse,omitempty"`
GetSortCapabilities *GetSortCapabilitiesResponse `xml:"GetSortCapabilitiesResponse,omitempty"`
GetSystemUpdateID *GetSystemUpdateIDResponse `xml:"GetSystemUpdateIDResponse,omitempty"`
GetAlbumArtistDisplayOption *GetAlbumArtistDisplayOptionResponse `xml:"GetAlbumArtistDisplayOptionResponse,omitempty"`
GetLastIndexChange *GetLastIndexChangeResponse `xml:"GetLastIndexChangeResponse,omitempty"`
Browse *BrowseResponse `xml:"BrowseResponse,omitempty"`
FindPrefix *FindPrefixResponse `xml:"FindPrefixResponse,omitempty"`
GetAllPrefixLocations *GetAllPrefixLocationsResponse `xml:"GetAllPrefixLocationsResponse,omitempty"`
CreateObject *CreateObjectResponse `xml:"CreateObjectResponse,omitempty"`
UpdateObject *UpdateObjectResponse `xml:"UpdateObjectResponse,omitempty"`
DestroyObject *DestroyObjectResponse `xml:"DestroyObjectResponse,omitempty"`
RefreshShareIndex *RefreshShareIndexResponse `xml:"RefreshShareIndexResponse,omitempty"`
RequestResort *RequestResortResponse `xml:"RequestResortResponse,omitempty"`
GetShareIndexInProgress *GetShareIndexInProgressResponse `xml:"GetShareIndexInProgressResponse,omitempty"`
GetBrowseable *GetBrowseableResponse `xml:"GetBrowseableResponse,omitempty"`
SetBrowseable *SetBrowseableResponse `xml:"SetBrowseableResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type GetSearchCapabilitiesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetSearchCapabilitiesResponse struct {
SearchCaps string `xml:"SearchCaps"`
}
func (s *Service) GetSearchCapabilities(httpClient *http.Client, args *GetSearchCapabilitiesArgs) (*GetSearchCapabilitiesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetSearchCapabilities`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetSearchCapabilities: args},
})
if err != nil {
return nil, err
}
if r.Body.GetSearchCapabilities == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSearchCapabilities()`)
}
return r.Body.GetSearchCapabilities, nil
}
type GetSortCapabilitiesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetSortCapabilitiesResponse struct {
SortCaps string `xml:"SortCaps"`
}
func (s *Service) GetSortCapabilities(httpClient *http.Client, args *GetSortCapabilitiesArgs) (*GetSortCapabilitiesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetSortCapabilities`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetSortCapabilities: args},
})
if err != nil {
return nil, err
}
if r.Body.GetSortCapabilities == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSortCapabilities()`)
}
return r.Body.GetSortCapabilities, nil
}
type GetSystemUpdateIDArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetSystemUpdateIDResponse struct {
Id uint32 `xml:"Id"`
}
func (s *Service) GetSystemUpdateID(httpClient *http.Client, args *GetSystemUpdateIDArgs) (*GetSystemUpdateIDResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetSystemUpdateID`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetSystemUpdateID: args},
})
if err != nil {
return nil, err
}
if r.Body.GetSystemUpdateID == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetSystemUpdateID()`)
}
return r.Body.GetSystemUpdateID, nil
}
type GetAlbumArtistDisplayOptionArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetAlbumArtistDisplayOptionResponse struct {
AlbumArtistDisplayOption string `xml:"AlbumArtistDisplayOption"`
}
func (s *Service) GetAlbumArtistDisplayOption(httpClient *http.Client, args *GetAlbumArtistDisplayOptionArgs) (*GetAlbumArtistDisplayOptionResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetAlbumArtistDisplayOption`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetAlbumArtistDisplayOption: args},
})
if err != nil {
return nil, err
}
if r.Body.GetAlbumArtistDisplayOption == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetAlbumArtistDisplayOption()`)
}
return r.Body.GetAlbumArtistDisplayOption, nil
}
type GetLastIndexChangeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetLastIndexChangeResponse struct {
LastIndexChange string `xml:"LastIndexChange"`
}
func (s *Service) GetLastIndexChange(httpClient *http.Client, args *GetLastIndexChangeArgs) (*GetLastIndexChangeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetLastIndexChange`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetLastIndexChange: args},
})
if err != nil {
return nil, err
}
if r.Body.GetLastIndexChange == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetLastIndexChange()`)
}
return r.Body.GetLastIndexChange, nil
}
type BrowseArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ObjectID string `xml:"ObjectID"`
// Allowed Value: BrowseMetadata
// Allowed Value: BrowseDirectChildren
BrowseFlag string `xml:"BrowseFlag"`
Filter string `xml:"Filter"`
StartingIndex uint32 `xml:"StartingIndex"`
RequestedCount uint32 `xml:"RequestedCount"`
SortCriteria string `xml:"SortCriteria"`
}
type BrowseResponse struct {
Result string `xml:"Result"`
NumberReturned uint32 `xml:"NumberReturned"`
TotalMatches uint32 `xml:"TotalMatches"`
UpdateID uint32 `xml:"UpdateID"`
}
func (s *Service) Browse(httpClient *http.Client, args *BrowseArgs) (*BrowseResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Browse`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Browse: args},
})
if err != nil {
return nil, err
}
if r.Body.Browse == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.Browse()`)
}
return r.Body.Browse, nil
}
type FindPrefixArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ObjectID string `xml:"ObjectID"`
Prefix string `xml:"Prefix"`
}
type FindPrefixResponse struct {
StartingIndex uint32 `xml:"StartingIndex"`
UpdateID uint32 `xml:"UpdateID"`
}
func (s *Service) FindPrefix(httpClient *http.Client, args *FindPrefixArgs) (*FindPrefixResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`FindPrefix`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{FindPrefix: args},
})
if err != nil {
return nil, err
}
if r.Body.FindPrefix == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.FindPrefix()`)
}
return r.Body.FindPrefix, nil
}
type GetAllPrefixLocationsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ObjectID string `xml:"ObjectID"`
}
type GetAllPrefixLocationsResponse struct {
TotalPrefixes uint32 `xml:"TotalPrefixes"`
PrefixAndIndexCSV string `xml:"PrefixAndIndexCSV"`
UpdateID uint32 `xml:"UpdateID"`
}
func (s *Service) GetAllPrefixLocations(httpClient *http.Client, args *GetAllPrefixLocationsArgs) (*GetAllPrefixLocationsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetAllPrefixLocations`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetAllPrefixLocations: args},
})
if err != nil {
return nil, err
}
if r.Body.GetAllPrefixLocations == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetAllPrefixLocations()`)
}
return r.Body.GetAllPrefixLocations, nil
}
type CreateObjectArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ContainerID string `xml:"ContainerID"`
Elements string `xml:"Elements"`
}
type CreateObjectResponse struct {
ObjectID string `xml:"ObjectID"`
Result string `xml:"Result"`
}
func (s *Service) CreateObject(httpClient *http.Client, args *CreateObjectArgs) (*CreateObjectResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`CreateObject`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{CreateObject: args},
})
if err != nil {
return nil, err
}
if r.Body.CreateObject == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.CreateObject()`)
}
return r.Body.CreateObject, nil
}
type UpdateObjectArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ObjectID string `xml:"ObjectID"`
CurrentTagValue string `xml:"CurrentTagValue"`
NewTagValue string `xml:"NewTagValue"`
}
type UpdateObjectResponse struct {
}
func (s *Service) UpdateObject(httpClient *http.Client, args *UpdateObjectArgs) (*UpdateObjectResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`UpdateObject`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{UpdateObject: args},
})
if err != nil {
return nil, err
}
if r.Body.UpdateObject == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.UpdateObject()`)
}
return r.Body.UpdateObject, nil
}
type DestroyObjectArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ObjectID string `xml:"ObjectID"`
}
type DestroyObjectResponse struct {
}
func (s *Service) DestroyObject(httpClient *http.Client, args *DestroyObjectArgs) (*DestroyObjectResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`DestroyObject`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{DestroyObject: args},
})
if err != nil {
return nil, err
}
if r.Body.DestroyObject == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.DestroyObject()`)
}
return r.Body.DestroyObject, nil
}
type RefreshShareIndexArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AlbumArtistDisplayOption string `xml:"AlbumArtistDisplayOption"`
}
type RefreshShareIndexResponse struct {
}
func (s *Service) RefreshShareIndex(httpClient *http.Client, args *RefreshShareIndexArgs) (*RefreshShareIndexResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RefreshShareIndex`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RefreshShareIndex: args},
})
if err != nil {
return nil, err
}
if r.Body.RefreshShareIndex == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.RefreshShareIndex()`)
}
return r.Body.RefreshShareIndex, nil
}
type RequestResortArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
SortOrder string `xml:"SortOrder"`
}
type RequestResortResponse struct {
}
func (s *Service) RequestResort(httpClient *http.Client, args *RequestResortArgs) (*RequestResortResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RequestResort`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RequestResort: args},
})
if err != nil {
return nil, err
}
if r.Body.RequestResort == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.RequestResort()`)
}
return r.Body.RequestResort, nil
}
type GetShareIndexInProgressArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetShareIndexInProgressResponse struct {
IsIndexing bool `xml:"IsIndexing"`
}
func (s *Service) GetShareIndexInProgress(httpClient *http.Client, args *GetShareIndexInProgressArgs) (*GetShareIndexInProgressResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetShareIndexInProgress`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetShareIndexInProgress: args},
})
if err != nil {
return nil, err
}
if r.Body.GetShareIndexInProgress == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetShareIndexInProgress()`)
}
return r.Body.GetShareIndexInProgress, nil
}
type GetBrowseableArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetBrowseableResponse struct {
IsBrowseable bool `xml:"IsBrowseable"`
}
func (s *Service) GetBrowseable(httpClient *http.Client, args *GetBrowseableArgs) (*GetBrowseableResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetBrowseable`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetBrowseable: args},
})
if err != nil {
return nil, err
}
if r.Body.GetBrowseable == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.GetBrowseable()`)
}
return r.Body.GetBrowseable, nil
}
type SetBrowseableArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Browseable bool `xml:"Browseable"`
}
type SetBrowseableResponse struct {
}
func (s *Service) SetBrowseable(httpClient *http.Client, args *SetBrowseableArgs) (*SetBrowseableResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetBrowseable`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetBrowseable: args},
})
if err != nil {
return nil, err
}
if r.Body.SetBrowseable == nil {
return nil, errors.New(`unexpected respose from service calling contentdirectory.SetBrowseable()`)
}
return r.Body.SetBrowseable, nil
}
+789
View File
@@ -0,0 +1,789 @@
package deviceproperties
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:DeviceProperties:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/DeviceProperties/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/DeviceProperties/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
SetLEDState *SetLEDStateArgs `xml:"u:SetLEDState,omitempty"`
GetLEDState *GetLEDStateArgs `xml:"u:GetLEDState,omitempty"`
AddBondedZones *AddBondedZonesArgs `xml:"u:AddBondedZones,omitempty"`
RemoveBondedZones *RemoveBondedZonesArgs `xml:"u:RemoveBondedZones,omitempty"`
CreateStereoPair *CreateStereoPairArgs `xml:"u:CreateStereoPair,omitempty"`
SeparateStereoPair *SeparateStereoPairArgs `xml:"u:SeparateStereoPair,omitempty"`
SetZoneAttributes *SetZoneAttributesArgs `xml:"u:SetZoneAttributes,omitempty"`
GetZoneAttributes *GetZoneAttributesArgs `xml:"u:GetZoneAttributes,omitempty"`
GetHouseholdID *GetHouseholdIDArgs `xml:"u:GetHouseholdID,omitempty"`
GetZoneInfo *GetZoneInfoArgs `xml:"u:GetZoneInfo,omitempty"`
SetAutoplayLinkedZones *SetAutoplayLinkedZonesArgs `xml:"u:SetAutoplayLinkedZones,omitempty"`
GetAutoplayLinkedZones *GetAutoplayLinkedZonesArgs `xml:"u:GetAutoplayLinkedZones,omitempty"`
SetAutoplayRoomUUID *SetAutoplayRoomUUIDArgs `xml:"u:SetAutoplayRoomUUID,omitempty"`
GetAutoplayRoomUUID *GetAutoplayRoomUUIDArgs `xml:"u:GetAutoplayRoomUUID,omitempty"`
SetAutoplayVolume *SetAutoplayVolumeArgs `xml:"u:SetAutoplayVolume,omitempty"`
GetAutoplayVolume *GetAutoplayVolumeArgs `xml:"u:GetAutoplayVolume,omitempty"`
SetUseAutoplayVolume *SetUseAutoplayVolumeArgs `xml:"u:SetUseAutoplayVolume,omitempty"`
GetUseAutoplayVolume *GetUseAutoplayVolumeArgs `xml:"u:GetUseAutoplayVolume,omitempty"`
AddHTSatellite *AddHTSatelliteArgs `xml:"u:AddHTSatellite,omitempty"`
RemoveHTSatellite *RemoveHTSatelliteArgs `xml:"u:RemoveHTSatellite,omitempty"`
EnterConfigMode *EnterConfigModeArgs `xml:"u:EnterConfigMode,omitempty"`
ExitConfigMode *ExitConfigModeArgs `xml:"u:ExitConfigMode,omitempty"`
GetButtonState *GetButtonStateArgs `xml:"u:GetButtonState,omitempty"`
SetButtonLockState *SetButtonLockStateArgs `xml:"u:SetButtonLockState,omitempty"`
GetButtonLockState *GetButtonLockStateArgs `xml:"u:GetButtonLockState,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
SetLEDState *SetLEDStateResponse `xml:"SetLEDStateResponse,omitempty"`
GetLEDState *GetLEDStateResponse `xml:"GetLEDStateResponse,omitempty"`
AddBondedZones *AddBondedZonesResponse `xml:"AddBondedZonesResponse,omitempty"`
RemoveBondedZones *RemoveBondedZonesResponse `xml:"RemoveBondedZonesResponse,omitempty"`
CreateStereoPair *CreateStereoPairResponse `xml:"CreateStereoPairResponse,omitempty"`
SeparateStereoPair *SeparateStereoPairResponse `xml:"SeparateStereoPairResponse,omitempty"`
SetZoneAttributes *SetZoneAttributesResponse `xml:"SetZoneAttributesResponse,omitempty"`
GetZoneAttributes *GetZoneAttributesResponse `xml:"GetZoneAttributesResponse,omitempty"`
GetHouseholdID *GetHouseholdIDResponse `xml:"GetHouseholdIDResponse,omitempty"`
GetZoneInfo *GetZoneInfoResponse `xml:"GetZoneInfoResponse,omitempty"`
SetAutoplayLinkedZones *SetAutoplayLinkedZonesResponse `xml:"SetAutoplayLinkedZonesResponse,omitempty"`
GetAutoplayLinkedZones *GetAutoplayLinkedZonesResponse `xml:"GetAutoplayLinkedZonesResponse,omitempty"`
SetAutoplayRoomUUID *SetAutoplayRoomUUIDResponse `xml:"SetAutoplayRoomUUIDResponse,omitempty"`
GetAutoplayRoomUUID *GetAutoplayRoomUUIDResponse `xml:"GetAutoplayRoomUUIDResponse,omitempty"`
SetAutoplayVolume *SetAutoplayVolumeResponse `xml:"SetAutoplayVolumeResponse,omitempty"`
GetAutoplayVolume *GetAutoplayVolumeResponse `xml:"GetAutoplayVolumeResponse,omitempty"`
SetUseAutoplayVolume *SetUseAutoplayVolumeResponse `xml:"SetUseAutoplayVolumeResponse,omitempty"`
GetUseAutoplayVolume *GetUseAutoplayVolumeResponse `xml:"GetUseAutoplayVolumeResponse,omitempty"`
AddHTSatellite *AddHTSatelliteResponse `xml:"AddHTSatelliteResponse,omitempty"`
RemoveHTSatellite *RemoveHTSatelliteResponse `xml:"RemoveHTSatelliteResponse,omitempty"`
EnterConfigMode *EnterConfigModeResponse `xml:"EnterConfigModeResponse,omitempty"`
ExitConfigMode *ExitConfigModeResponse `xml:"ExitConfigModeResponse,omitempty"`
GetButtonState *GetButtonStateResponse `xml:"GetButtonStateResponse,omitempty"`
SetButtonLockState *SetButtonLockStateResponse `xml:"SetButtonLockStateResponse,omitempty"`
GetButtonLockState *GetButtonLockStateResponse `xml:"GetButtonLockStateResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type SetLEDStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
// Allowed Value: On
// Allowed Value: Off
DesiredLEDState string `xml:"DesiredLEDState"`
}
type SetLEDStateResponse struct {
}
func (s *Service) SetLEDState(httpClient *http.Client, args *SetLEDStateArgs) (*SetLEDStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetLEDState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetLEDState: args},
})
if err != nil {
return nil, err
}
if r.Body.SetLEDState == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetLEDState()`)
}
return r.Body.SetLEDState, nil
}
type GetLEDStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetLEDStateResponse struct {
CurrentLEDState string `xml:"CurrentLEDState"`
}
func (s *Service) GetLEDState(httpClient *http.Client, args *GetLEDStateArgs) (*GetLEDStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetLEDState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetLEDState: args},
})
if err != nil {
return nil, err
}
if r.Body.GetLEDState == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetLEDState()`)
}
return r.Body.GetLEDState, nil
}
type AddBondedZonesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ChannelMapSet string `xml:"ChannelMapSet"`
}
type AddBondedZonesResponse struct {
}
func (s *Service) AddBondedZones(httpClient *http.Client, args *AddBondedZonesArgs) (*AddBondedZonesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddBondedZones`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddBondedZones: args},
})
if err != nil {
return nil, err
}
if r.Body.AddBondedZones == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.AddBondedZones()`)
}
return r.Body.AddBondedZones, nil
}
type RemoveBondedZonesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ChannelMapSet string `xml:"ChannelMapSet"`
KeepGrouped bool `xml:"KeepGrouped"`
}
type RemoveBondedZonesResponse struct {
}
func (s *Service) RemoveBondedZones(httpClient *http.Client, args *RemoveBondedZonesArgs) (*RemoveBondedZonesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveBondedZones`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveBondedZones: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveBondedZones == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.RemoveBondedZones()`)
}
return r.Body.RemoveBondedZones, nil
}
type CreateStereoPairArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ChannelMapSet string `xml:"ChannelMapSet"`
}
type CreateStereoPairResponse struct {
}
func (s *Service) CreateStereoPair(httpClient *http.Client, args *CreateStereoPairArgs) (*CreateStereoPairResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`CreateStereoPair`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{CreateStereoPair: args},
})
if err != nil {
return nil, err
}
if r.Body.CreateStereoPair == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.CreateStereoPair()`)
}
return r.Body.CreateStereoPair, nil
}
type SeparateStereoPairArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ChannelMapSet string `xml:"ChannelMapSet"`
}
type SeparateStereoPairResponse struct {
}
func (s *Service) SeparateStereoPair(httpClient *http.Client, args *SeparateStereoPairArgs) (*SeparateStereoPairResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SeparateStereoPair`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SeparateStereoPair: args},
})
if err != nil {
return nil, err
}
if r.Body.SeparateStereoPair == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SeparateStereoPair()`)
}
return r.Body.SeparateStereoPair, nil
}
type SetZoneAttributesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredZoneName string `xml:"DesiredZoneName"`
DesiredIcon string `xml:"DesiredIcon"`
DesiredConfiguration string `xml:"DesiredConfiguration"`
}
type SetZoneAttributesResponse struct {
}
func (s *Service) SetZoneAttributes(httpClient *http.Client, args *SetZoneAttributesArgs) (*SetZoneAttributesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetZoneAttributes`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetZoneAttributes: args},
})
if err != nil {
return nil, err
}
if r.Body.SetZoneAttributes == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetZoneAttributes()`)
}
return r.Body.SetZoneAttributes, nil
}
type GetZoneAttributesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetZoneAttributesResponse struct {
CurrentZoneName string `xml:"CurrentZoneName"`
CurrentIcon string `xml:"CurrentIcon"`
CurrentConfiguration string `xml:"CurrentConfiguration"`
}
func (s *Service) GetZoneAttributes(httpClient *http.Client, args *GetZoneAttributesArgs) (*GetZoneAttributesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetZoneAttributes`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetZoneAttributes: args},
})
if err != nil {
return nil, err
}
if r.Body.GetZoneAttributes == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetZoneAttributes()`)
}
return r.Body.GetZoneAttributes, nil
}
type GetHouseholdIDArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetHouseholdIDResponse struct {
CurrentHouseholdID string `xml:"CurrentHouseholdID"`
}
func (s *Service) GetHouseholdID(httpClient *http.Client, args *GetHouseholdIDArgs) (*GetHouseholdIDResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetHouseholdID`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetHouseholdID: args},
})
if err != nil {
return nil, err
}
if r.Body.GetHouseholdID == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetHouseholdID()`)
}
return r.Body.GetHouseholdID, nil
}
type GetZoneInfoArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetZoneInfoResponse struct {
SerialNumber string `xml:"SerialNumber"`
SoftwareVersion string `xml:"SoftwareVersion"`
DisplaySoftwareVersion string `xml:"DisplaySoftwareVersion"`
HardwareVersion string `xml:"HardwareVersion"`
IPAddress string `xml:"IPAddress"`
MACAddress string `xml:"MACAddress"`
CopyrightInfo string `xml:"CopyrightInfo"`
ExtraInfo string `xml:"ExtraInfo"`
HTAudioIn uint32 `xml:"HTAudioIn"`
Flags uint32 `xml:"Flags"`
}
func (s *Service) GetZoneInfo(httpClient *http.Client, args *GetZoneInfoArgs) (*GetZoneInfoResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetZoneInfo`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetZoneInfo: args},
})
if err != nil {
return nil, err
}
if r.Body.GetZoneInfo == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetZoneInfo()`)
}
return r.Body.GetZoneInfo, nil
}
type SetAutoplayLinkedZonesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
Source string `xml:"Source"`
}
type SetAutoplayLinkedZonesResponse struct {
}
func (s *Service) SetAutoplayLinkedZones(httpClient *http.Client, args *SetAutoplayLinkedZonesArgs) (*SetAutoplayLinkedZonesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetAutoplayLinkedZones`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetAutoplayLinkedZones: args},
})
if err != nil {
return nil, err
}
if r.Body.SetAutoplayLinkedZones == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayLinkedZones()`)
}
return r.Body.SetAutoplayLinkedZones, nil
}
type GetAutoplayLinkedZonesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Source string `xml:"Source"`
}
type GetAutoplayLinkedZonesResponse struct {
IncludeLinkedZones bool `xml:"IncludeLinkedZones"`
}
func (s *Service) GetAutoplayLinkedZones(httpClient *http.Client, args *GetAutoplayLinkedZonesArgs) (*GetAutoplayLinkedZonesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetAutoplayLinkedZones`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetAutoplayLinkedZones: args},
})
if err != nil {
return nil, err
}
if r.Body.GetAutoplayLinkedZones == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayLinkedZones()`)
}
return r.Body.GetAutoplayLinkedZones, nil
}
type SetAutoplayRoomUUIDArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
RoomUUID string `xml:"RoomUUID"`
Source string `xml:"Source"`
}
type SetAutoplayRoomUUIDResponse struct {
}
func (s *Service) SetAutoplayRoomUUID(httpClient *http.Client, args *SetAutoplayRoomUUIDArgs) (*SetAutoplayRoomUUIDResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetAutoplayRoomUUID`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetAutoplayRoomUUID: args},
})
if err != nil {
return nil, err
}
if r.Body.SetAutoplayRoomUUID == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayRoomUUID()`)
}
return r.Body.SetAutoplayRoomUUID, nil
}
type GetAutoplayRoomUUIDArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Source string `xml:"Source"`
}
type GetAutoplayRoomUUIDResponse struct {
RoomUUID string `xml:"RoomUUID"`
}
func (s *Service) GetAutoplayRoomUUID(httpClient *http.Client, args *GetAutoplayRoomUUIDArgs) (*GetAutoplayRoomUUIDResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetAutoplayRoomUUID`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetAutoplayRoomUUID: args},
})
if err != nil {
return nil, err
}
if r.Body.GetAutoplayRoomUUID == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayRoomUUID()`)
}
return r.Body.GetAutoplayRoomUUID, nil
}
type SetAutoplayVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
// Allowed Range: 0 -> 100 step: 1
Volume uint16 `xml:"Volume"`
Source string `xml:"Source"`
}
type SetAutoplayVolumeResponse struct {
}
func (s *Service) SetAutoplayVolume(httpClient *http.Client, args *SetAutoplayVolumeArgs) (*SetAutoplayVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetAutoplayVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetAutoplayVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetAutoplayVolume == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetAutoplayVolume()`)
}
return r.Body.SetAutoplayVolume, nil
}
type GetAutoplayVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Source string `xml:"Source"`
}
type GetAutoplayVolumeResponse struct {
CurrentVolume uint16 `xml:"CurrentVolume"`
}
func (s *Service) GetAutoplayVolume(httpClient *http.Client, args *GetAutoplayVolumeArgs) (*GetAutoplayVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetAutoplayVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetAutoplayVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.GetAutoplayVolume == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetAutoplayVolume()`)
}
return r.Body.GetAutoplayVolume, nil
}
type SetUseAutoplayVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
UseVolume bool `xml:"UseVolume"`
Source string `xml:"Source"`
}
type SetUseAutoplayVolumeResponse struct {
}
func (s *Service) SetUseAutoplayVolume(httpClient *http.Client, args *SetUseAutoplayVolumeArgs) (*SetUseAutoplayVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetUseAutoplayVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetUseAutoplayVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetUseAutoplayVolume == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetUseAutoplayVolume()`)
}
return r.Body.SetUseAutoplayVolume, nil
}
type GetUseAutoplayVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Source string `xml:"Source"`
}
type GetUseAutoplayVolumeResponse struct {
UseVolume bool `xml:"UseVolume"`
}
func (s *Service) GetUseAutoplayVolume(httpClient *http.Client, args *GetUseAutoplayVolumeArgs) (*GetUseAutoplayVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetUseAutoplayVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetUseAutoplayVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.GetUseAutoplayVolume == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetUseAutoplayVolume()`)
}
return r.Body.GetUseAutoplayVolume, nil
}
type AddHTSatelliteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
HTSatChanMapSet string `xml:"HTSatChanMapSet"`
}
type AddHTSatelliteResponse struct {
}
func (s *Service) AddHTSatellite(httpClient *http.Client, args *AddHTSatelliteArgs) (*AddHTSatelliteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddHTSatellite`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddHTSatellite: args},
})
if err != nil {
return nil, err
}
if r.Body.AddHTSatellite == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.AddHTSatellite()`)
}
return r.Body.AddHTSatellite, nil
}
type RemoveHTSatelliteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
SatRoomUUID string `xml:"SatRoomUUID"`
}
type RemoveHTSatelliteResponse struct {
}
func (s *Service) RemoveHTSatellite(httpClient *http.Client, args *RemoveHTSatelliteArgs) (*RemoveHTSatelliteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveHTSatellite`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveHTSatellite: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveHTSatellite == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.RemoveHTSatellite()`)
}
return r.Body.RemoveHTSatellite, nil
}
type EnterConfigModeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Mode string `xml:"Mode"`
Options string `xml:"Options"`
}
type EnterConfigModeResponse struct {
State string `xml:"State"`
}
func (s *Service) EnterConfigMode(httpClient *http.Client, args *EnterConfigModeArgs) (*EnterConfigModeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`EnterConfigMode`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{EnterConfigMode: args},
})
if err != nil {
return nil, err
}
if r.Body.EnterConfigMode == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.EnterConfigMode()`)
}
return r.Body.EnterConfigMode, nil
}
type ExitConfigModeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Options string `xml:"Options"`
}
type ExitConfigModeResponse struct {
}
func (s *Service) ExitConfigMode(httpClient *http.Client, args *ExitConfigModeArgs) (*ExitConfigModeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ExitConfigMode`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ExitConfigMode: args},
})
if err != nil {
return nil, err
}
if r.Body.ExitConfigMode == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.ExitConfigMode()`)
}
return r.Body.ExitConfigMode, nil
}
type GetButtonStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetButtonStateResponse struct {
State string `xml:"State"`
}
func (s *Service) GetButtonState(httpClient *http.Client, args *GetButtonStateArgs) (*GetButtonStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetButtonState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetButtonState: args},
})
if err != nil {
return nil, err
}
if r.Body.GetButtonState == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetButtonState()`)
}
return r.Body.GetButtonState, nil
}
type SetButtonLockStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
// Allowed Value: On
// Allowed Value: Off
DesiredButtonLockState string `xml:"DesiredButtonLockState"`
}
type SetButtonLockStateResponse struct {
}
func (s *Service) SetButtonLockState(httpClient *http.Client, args *SetButtonLockStateArgs) (*SetButtonLockStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetButtonLockState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetButtonLockState: args},
})
if err != nil {
return nil, err
}
if r.Body.SetButtonLockState == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.SetButtonLockState()`)
}
return r.Body.SetButtonLockState, nil
}
type GetButtonLockStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetButtonLockStateResponse struct {
CurrentButtonLockState string `xml:"CurrentButtonLockState"`
}
func (s *Service) GetButtonLockState(httpClient *http.Client, args *GetButtonLockStateArgs) (*GetButtonLockStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetButtonLockState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetButtonLockState: args},
})
if err != nil {
return nil, err
}
if r.Body.GetButtonLockState == nil {
return nil, errors.New(`unexpected respose from service calling deviceproperties.GetButtonLockState()`)
}
return r.Body.GetButtonLockState, nil
}
+200
View File
@@ -0,0 +1,200 @@
package groupmanagement
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:GroupManagement:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/GroupManagement/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/GroupManagement/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
AddMember *AddMemberArgs `xml:"u:AddMember,omitempty"`
RemoveMember *RemoveMemberArgs `xml:"u:RemoveMember,omitempty"`
ReportTrackBufferingResult *ReportTrackBufferingResultArgs `xml:"u:ReportTrackBufferingResult,omitempty"`
SetSourceAreaIds *SetSourceAreaIdsArgs `xml:"u:SetSourceAreaIds,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
AddMember *AddMemberResponse `xml:"AddMemberResponse,omitempty"`
RemoveMember *RemoveMemberResponse `xml:"RemoveMemberResponse,omitempty"`
ReportTrackBufferingResult *ReportTrackBufferingResultResponse `xml:"ReportTrackBufferingResultResponse,omitempty"`
SetSourceAreaIds *SetSourceAreaIdsResponse `xml:"SetSourceAreaIdsResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type AddMemberArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
MemberID string `xml:"MemberID"`
BootSeq uint32 `xml:"BootSeq"`
}
type AddMemberResponse struct {
CurrentTransportSettings string `xml:"CurrentTransportSettings"`
CurrentURI string `xml:"CurrentURI"`
GroupUUIDJoined string `xml:"GroupUUIDJoined"`
ResetVolumeAfter bool `xml:"ResetVolumeAfter"`
VolumeAVTransportURI string `xml:"VolumeAVTransportURI"`
}
func (s *Service) AddMember(httpClient *http.Client, args *AddMemberArgs) (*AddMemberResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddMember`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddMember: args},
})
if err != nil {
return nil, err
}
if r.Body.AddMember == nil {
return nil, errors.New(`unexpected respose from service calling groupmanagement.AddMember()`)
}
return r.Body.AddMember, nil
}
type RemoveMemberArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
MemberID string `xml:"MemberID"`
}
type RemoveMemberResponse struct {
}
func (s *Service) RemoveMember(httpClient *http.Client, args *RemoveMemberArgs) (*RemoveMemberResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveMember`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveMember: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveMember == nil {
return nil, errors.New(`unexpected respose from service calling groupmanagement.RemoveMember()`)
}
return r.Body.RemoveMember, nil
}
type ReportTrackBufferingResultArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
MemberID string `xml:"MemberID"`
ResultCode int32 `xml:"ResultCode"`
}
type ReportTrackBufferingResultResponse struct {
}
func (s *Service) ReportTrackBufferingResult(httpClient *http.Client, args *ReportTrackBufferingResultArgs) (*ReportTrackBufferingResultResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReportTrackBufferingResult`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReportTrackBufferingResult: args},
})
if err != nil {
return nil, err
}
if r.Body.ReportTrackBufferingResult == nil {
return nil, errors.New(`unexpected respose from service calling groupmanagement.ReportTrackBufferingResult()`)
}
return r.Body.ReportTrackBufferingResult, nil
}
type SetSourceAreaIdsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DesiredSourceAreaIds string `xml:"DesiredSourceAreaIds"`
}
type SetSourceAreaIdsResponse struct {
}
func (s *Service) SetSourceAreaIds(httpClient *http.Client, args *SetSourceAreaIdsArgs) (*SetSourceAreaIdsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetSourceAreaIds`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetSourceAreaIds: args},
})
if err != nil {
return nil, err
}
if r.Body.SetSourceAreaIds == nil {
return nil, errors.New(`unexpected respose from service calling groupmanagement.SetSourceAreaIds()`)
}
return r.Body.SetSourceAreaIds, nil
}
@@ -0,0 +1,254 @@
package grouprenderingcontrol
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:GroupRenderingControl:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaRenderer/GroupRenderingControl/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaRenderer/GroupRenderingControl/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
GetGroupMute *GetGroupMuteArgs `xml:"u:GetGroupMute,omitempty"`
SetGroupMute *SetGroupMuteArgs `xml:"u:SetGroupMute,omitempty"`
GetGroupVolume *GetGroupVolumeArgs `xml:"u:GetGroupVolume,omitempty"`
SetGroupVolume *SetGroupVolumeArgs `xml:"u:SetGroupVolume,omitempty"`
SetRelativeGroupVolume *SetRelativeGroupVolumeArgs `xml:"u:SetRelativeGroupVolume,omitempty"`
SnapshotGroupVolume *SnapshotGroupVolumeArgs `xml:"u:SnapshotGroupVolume,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
GetGroupMute *GetGroupMuteResponse `xml:"GetGroupMuteResponse,omitempty"`
SetGroupMute *SetGroupMuteResponse `xml:"SetGroupMuteResponse,omitempty"`
GetGroupVolume *GetGroupVolumeResponse `xml:"GetGroupVolumeResponse,omitempty"`
SetGroupVolume *SetGroupVolumeResponse `xml:"SetGroupVolumeResponse,omitempty"`
SetRelativeGroupVolume *SetRelativeGroupVolumeResponse `xml:"SetRelativeGroupVolumeResponse,omitempty"`
SnapshotGroupVolume *SnapshotGroupVolumeResponse `xml:"SnapshotGroupVolumeResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type GetGroupMuteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetGroupMuteResponse struct {
CurrentMute bool `xml:"CurrentMute"`
}
func (s *Service) GetGroupMute(httpClient *http.Client, args *GetGroupMuteArgs) (*GetGroupMuteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetGroupMute`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetGroupMute: args},
})
if err != nil {
return nil, err
}
if r.Body.GetGroupMute == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.GetGroupMute()`)
}
return r.Body.GetGroupMute, nil
}
type SetGroupMuteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
DesiredMute bool `xml:"DesiredMute"`
}
type SetGroupMuteResponse struct {
}
func (s *Service) SetGroupMute(httpClient *http.Client, args *SetGroupMuteArgs) (*SetGroupMuteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetGroupMute`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetGroupMute: args},
})
if err != nil {
return nil, err
}
if r.Body.SetGroupMute == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetGroupMute()`)
}
return r.Body.SetGroupMute, nil
}
type GetGroupVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetGroupVolumeResponse struct {
CurrentVolume uint16 `xml:"CurrentVolume"`
}
func (s *Service) GetGroupVolume(httpClient *http.Client, args *GetGroupVolumeArgs) (*GetGroupVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetGroupVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetGroupVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.GetGroupVolume == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.GetGroupVolume()`)
}
return r.Body.GetGroupVolume, nil
}
type SetGroupVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Range: 0 -> 100 step: 1
DesiredVolume uint16 `xml:"DesiredVolume"`
}
type SetGroupVolumeResponse struct {
}
func (s *Service) SetGroupVolume(httpClient *http.Client, args *SetGroupVolumeArgs) (*SetGroupVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetGroupVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetGroupVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetGroupVolume == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetGroupVolume()`)
}
return r.Body.SetGroupVolume, nil
}
type SetRelativeGroupVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
Adjustment int32 `xml:"Adjustment"`
}
type SetRelativeGroupVolumeResponse struct {
NewVolume uint16 `xml:"NewVolume"`
}
func (s *Service) SetRelativeGroupVolume(httpClient *http.Client, args *SetRelativeGroupVolumeArgs) (*SetRelativeGroupVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetRelativeGroupVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetRelativeGroupVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetRelativeGroupVolume == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SetRelativeGroupVolume()`)
}
return r.Body.SetRelativeGroupVolume, nil
}
type SnapshotGroupVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type SnapshotGroupVolumeResponse struct {
}
func (s *Service) SnapshotGroupVolume(httpClient *http.Client, args *SnapshotGroupVolumeArgs) (*SnapshotGroupVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SnapshotGroupVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SnapshotGroupVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SnapshotGroupVolume == nil {
return nil, errors.New(`unexpected respose from service calling grouprenderingcontrol.SnapshotGroupVolume()`)
}
return r.Body.SnapshotGroupVolume, nil
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Matthew Szatmary
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+169
View File
@@ -0,0 +1,169 @@
package musicservices
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:MusicServices:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MusicServices/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MusicServices/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
GetSessionId *GetSessionIdArgs `xml:"u:GetSessionId,omitempty"`
ListAvailableServices *ListAvailableServicesArgs `xml:"u:ListAvailableServices,omitempty"`
UpdateAvailableServices *UpdateAvailableServicesArgs `xml:"u:UpdateAvailableServices,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
GetSessionId *GetSessionIdResponse `xml:"GetSessionIdResponse,omitempty"`
ListAvailableServices *ListAvailableServicesResponse `xml:"ListAvailableServicesResponse,omitempty"`
UpdateAvailableServices *UpdateAvailableServicesResponse `xml:"UpdateAvailableServicesResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type GetSessionIdArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
ServiceId uint32 `xml:"ServiceId"`
Username string `xml:"Username"`
}
type GetSessionIdResponse struct {
SessionId string `xml:"SessionId"`
}
func (s *Service) GetSessionId(httpClient *http.Client, args *GetSessionIdArgs) (*GetSessionIdResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetSessionId`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetSessionId: args},
})
if err != nil {
return nil, err
}
if r.Body.GetSessionId == nil {
return nil, errors.New(`unexpected respose from service calling musicservices.GetSessionId()`)
}
return r.Body.GetSessionId, nil
}
type ListAvailableServicesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type ListAvailableServicesResponse struct {
AvailableServiceDescriptorList string `xml:"AvailableServiceDescriptorList"`
AvailableServiceTypeList string `xml:"AvailableServiceTypeList"`
AvailableServiceListVersion string `xml:"AvailableServiceListVersion"`
}
func (s *Service) ListAvailableServices(httpClient *http.Client, args *ListAvailableServicesArgs) (*ListAvailableServicesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ListAvailableServices`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ListAvailableServices: args},
})
if err != nil {
return nil, err
}
if r.Body.ListAvailableServices == nil {
return nil, errors.New(`unexpected respose from service calling musicservices.ListAvailableServices()`)
}
return r.Body.ListAvailableServices, nil
}
type UpdateAvailableServicesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type UpdateAvailableServicesResponse struct {
}
func (s *Service) UpdateAvailableServices(httpClient *http.Client, args *UpdateAvailableServicesArgs) (*UpdateAvailableServicesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`UpdateAvailableServices`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{UpdateAvailableServices: args},
})
if err != nil {
return nil, err
}
if r.Body.UpdateAvailableServices == nil {
return nil, errors.New(`unexpected respose from service calling musicservices.UpdateAvailableServices()`)
}
return r.Body.UpdateAvailableServices, nil
}
+115
View File
@@ -0,0 +1,115 @@
package qplay
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:QPlay:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/QPlay/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/QPlay/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
QPlayAuth *QPlayAuthArgs `xml:"u:QPlayAuth,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
QPlayAuth *QPlayAuthResponse `xml:"QPlayAuthResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type QPlayAuthArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
Seed string `xml:"Seed"`
}
type QPlayAuthResponse struct {
Code string `xml:"Code"`
MID string `xml:"MID"`
DID string `xml:"DID"`
}
func (s *Service) QPlayAuth(httpClient *http.Client, args *QPlayAuthArgs) (*QPlayAuthResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`QPlayAuth`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{QPlayAuth: args},
})
if err != nil {
return nil, err
}
if r.Body.QPlayAuth == nil {
return nil, errors.New(`unexpected respose from service calling qplay.QPlayAuth()`)
}
return r.Body.QPlayAuth, nil
}
+435
View File
@@ -0,0 +1,435 @@
package queue
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:Queue:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaRenderer/Queue/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaRenderer/Queue/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
AddURI *AddURIArgs `xml:"u:AddURI,omitempty"`
AddMultipleURIs *AddMultipleURIsArgs `xml:"u:AddMultipleURIs,omitempty"`
AttachQueue *AttachQueueArgs `xml:"u:AttachQueue,omitempty"`
Backup *BackupArgs `xml:"u:Backup,omitempty"`
Browse *BrowseArgs `xml:"u:Browse,omitempty"`
CreateQueue *CreateQueueArgs `xml:"u:CreateQueue,omitempty"`
RemoveAllTracks *RemoveAllTracksArgs `xml:"u:RemoveAllTracks,omitempty"`
RemoveTrackRange *RemoveTrackRangeArgs `xml:"u:RemoveTrackRange,omitempty"`
ReorderTracks *ReorderTracksArgs `xml:"u:ReorderTracks,omitempty"`
ReplaceAllTracks *ReplaceAllTracksArgs `xml:"u:ReplaceAllTracks,omitempty"`
SaveAsSonosPlaylist *SaveAsSonosPlaylistArgs `xml:"u:SaveAsSonosPlaylist,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
AddURI *AddURIResponse `xml:"AddURIResponse,omitempty"`
AddMultipleURIs *AddMultipleURIsResponse `xml:"AddMultipleURIsResponse,omitempty"`
AttachQueue *AttachQueueResponse `xml:"AttachQueueResponse,omitempty"`
Backup *BackupResponse `xml:"BackupResponse,omitempty"`
Browse *BrowseResponse `xml:"BrowseResponse,omitempty"`
CreateQueue *CreateQueueResponse `xml:"CreateQueueResponse,omitempty"`
RemoveAllTracks *RemoveAllTracksResponse `xml:"RemoveAllTracksResponse,omitempty"`
RemoveTrackRange *RemoveTrackRangeResponse `xml:"RemoveTrackRangeResponse,omitempty"`
ReorderTracks *ReorderTracksResponse `xml:"ReorderTracksResponse,omitempty"`
ReplaceAllTracks *ReplaceAllTracksResponse `xml:"ReplaceAllTracksResponse,omitempty"`
SaveAsSonosPlaylist *SaveAsSonosPlaylistResponse `xml:"SaveAsSonosPlaylistResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type AddURIArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
UpdateID uint32 `xml:"UpdateID"`
EnqueuedURI string `xml:"EnqueuedURI"`
EnqueuedURIMetaData string `xml:"EnqueuedURIMetaData"`
DesiredFirstTrackNumberEnqueued uint32 `xml:"DesiredFirstTrackNumberEnqueued"`
EnqueueAsNext bool `xml:"EnqueueAsNext"`
}
type AddURIResponse struct {
FirstTrackNumberEnqueued uint32 `xml:"FirstTrackNumberEnqueued"`
NumTracksAdded uint32 `xml:"NumTracksAdded"`
NewQueueLength uint32 `xml:"NewQueueLength"`
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) AddURI(httpClient *http.Client, args *AddURIArgs) (*AddURIResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddURI`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddURI: args},
})
if err != nil {
return nil, err
}
if r.Body.AddURI == nil {
return nil, errors.New(`unexpected respose from service calling queue.AddURI()`)
}
return r.Body.AddURI, nil
}
type AddMultipleURIsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
UpdateID uint32 `xml:"UpdateID"`
ContainerURI string `xml:"ContainerURI"`
ContainerMetaData string `xml:"ContainerMetaData"`
DesiredFirstTrackNumberEnqueued uint32 `xml:"DesiredFirstTrackNumberEnqueued"`
EnqueueAsNext bool `xml:"EnqueueAsNext"`
NumberOfURIs uint32 `xml:"NumberOfURIs"`
EnqueuedURIsAndMetaData string `xml:"EnqueuedURIsAndMetaData"`
}
type AddMultipleURIsResponse struct {
FirstTrackNumberEnqueued uint32 `xml:"FirstTrackNumberEnqueued"`
NumTracksAdded uint32 `xml:"NumTracksAdded"`
NewQueueLength uint32 `xml:"NewQueueLength"`
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) AddMultipleURIs(httpClient *http.Client, args *AddMultipleURIsArgs) (*AddMultipleURIsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddMultipleURIs`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddMultipleURIs: args},
})
if err != nil {
return nil, err
}
if r.Body.AddMultipleURIs == nil {
return nil, errors.New(`unexpected respose from service calling queue.AddMultipleURIs()`)
}
return r.Body.AddMultipleURIs, nil
}
type AttachQueueArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueOwnerID string `xml:"QueueOwnerID"`
}
type AttachQueueResponse struct {
QueueID uint32 `xml:"QueueID"`
QueueOwnerContext string `xml:"QueueOwnerContext"`
}
func (s *Service) AttachQueue(httpClient *http.Client, args *AttachQueueArgs) (*AttachQueueResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AttachQueue`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AttachQueue: args},
})
if err != nil {
return nil, err
}
if r.Body.AttachQueue == nil {
return nil, errors.New(`unexpected respose from service calling queue.AttachQueue()`)
}
return r.Body.AttachQueue, nil
}
type BackupArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type BackupResponse struct {
}
func (s *Service) Backup(httpClient *http.Client, args *BackupArgs) (*BackupResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Backup`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Backup: args},
})
if err != nil {
return nil, err
}
if r.Body.Backup == nil {
return nil, errors.New(`unexpected respose from service calling queue.Backup()`)
}
return r.Body.Backup, nil
}
type BrowseArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
StartingIndex uint32 `xml:"StartingIndex"`
RequestedCount uint32 `xml:"RequestedCount"`
}
type BrowseResponse struct {
Result string `xml:"Result"`
NumberReturned uint32 `xml:"NumberReturned"`
TotalMatches uint32 `xml:"TotalMatches"`
UpdateID uint32 `xml:"UpdateID"`
}
func (s *Service) Browse(httpClient *http.Client, args *BrowseArgs) (*BrowseResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Browse`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Browse: args},
})
if err != nil {
return nil, err
}
if r.Body.Browse == nil {
return nil, errors.New(`unexpected respose from service calling queue.Browse()`)
}
return r.Body.Browse, nil
}
type CreateQueueArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueOwnerID string `xml:"QueueOwnerID"`
QueueOwnerContext string `xml:"QueueOwnerContext"`
QueuePolicy string `xml:"QueuePolicy"`
}
type CreateQueueResponse struct {
QueueID uint32 `xml:"QueueID"`
}
func (s *Service) CreateQueue(httpClient *http.Client, args *CreateQueueArgs) (*CreateQueueResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`CreateQueue`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{CreateQueue: args},
})
if err != nil {
return nil, err
}
if r.Body.CreateQueue == nil {
return nil, errors.New(`unexpected respose from service calling queue.CreateQueue()`)
}
return r.Body.CreateQueue, nil
}
type RemoveAllTracksArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
UpdateID uint32 `xml:"UpdateID"`
}
type RemoveAllTracksResponse struct {
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) RemoveAllTracks(httpClient *http.Client, args *RemoveAllTracksArgs) (*RemoveAllTracksResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveAllTracks`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveAllTracks: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveAllTracks == nil {
return nil, errors.New(`unexpected respose from service calling queue.RemoveAllTracks()`)
}
return r.Body.RemoveAllTracks, nil
}
type RemoveTrackRangeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
UpdateID uint32 `xml:"UpdateID"`
StartingIndex uint32 `xml:"StartingIndex"`
NumberOfTracks uint32 `xml:"NumberOfTracks"`
}
type RemoveTrackRangeResponse struct {
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) RemoveTrackRange(httpClient *http.Client, args *RemoveTrackRangeArgs) (*RemoveTrackRangeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveTrackRange`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveTrackRange: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveTrackRange == nil {
return nil, errors.New(`unexpected respose from service calling queue.RemoveTrackRange()`)
}
return r.Body.RemoveTrackRange, nil
}
type ReorderTracksArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
StartingIndex uint32 `xml:"StartingIndex"`
NumberOfTracks uint32 `xml:"NumberOfTracks"`
InsertBefore uint32 `xml:"InsertBefore"`
UpdateID uint32 `xml:"UpdateID"`
}
type ReorderTracksResponse struct {
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) ReorderTracks(httpClient *http.Client, args *ReorderTracksArgs) (*ReorderTracksResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReorderTracks`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReorderTracks: args},
})
if err != nil {
return nil, err
}
if r.Body.ReorderTracks == nil {
return nil, errors.New(`unexpected respose from service calling queue.ReorderTracks()`)
}
return r.Body.ReorderTracks, nil
}
type ReplaceAllTracksArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
UpdateID uint32 `xml:"UpdateID"`
ContainerURI string `xml:"ContainerURI"`
ContainerMetaData string `xml:"ContainerMetaData"`
CurrentTrackIndex uint32 `xml:"CurrentTrackIndex"`
NewCurrentTrackIndices string `xml:"NewCurrentTrackIndices"`
NumberOfURIs uint32 `xml:"NumberOfURIs"`
EnqueuedURIsAndMetaData string `xml:"EnqueuedURIsAndMetaData"`
}
type ReplaceAllTracksResponse struct {
NewQueueLength uint32 `xml:"NewQueueLength"`
NewUpdateID uint32 `xml:"NewUpdateID"`
}
func (s *Service) ReplaceAllTracks(httpClient *http.Client, args *ReplaceAllTracksArgs) (*ReplaceAllTracksResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReplaceAllTracks`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReplaceAllTracks: args},
})
if err != nil {
return nil, err
}
if r.Body.ReplaceAllTracks == nil {
return nil, errors.New(`unexpected respose from service calling queue.ReplaceAllTracks()`)
}
return r.Body.ReplaceAllTracks, nil
}
type SaveAsSonosPlaylistArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
QueueID uint32 `xml:"QueueID"`
Title string `xml:"Title"`
ObjectID string `xml:"ObjectID"`
}
type SaveAsSonosPlaylistResponse struct {
AssignedObjectID string `xml:"AssignedObjectID"`
}
func (s *Service) SaveAsSonosPlaylist(httpClient *http.Client, args *SaveAsSonosPlaylistArgs) (*SaveAsSonosPlaylistResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SaveAsSonosPlaylist`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SaveAsSonosPlaylist: args},
})
if err != nil {
return nil, err
}
if r.Body.SaveAsSonosPlaylist == nil {
return nil, errors.New(`unexpected respose from service calling queue.SaveAsSonosPlaylist()`)
}
return r.Body.SaveAsSonosPlaylist, nil
}
View File
+940
View File
@@ -0,0 +1,940 @@
package renderingcontrol
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:RenderingControl:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaRenderer/RenderingControl/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaRenderer/RenderingControl/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
GetMute *GetMuteArgs `xml:"u:GetMute,omitempty"`
SetMute *SetMuteArgs `xml:"u:SetMute,omitempty"`
ResetBasicEQ *ResetBasicEQArgs `xml:"u:ResetBasicEQ,omitempty"`
ResetExtEQ *ResetExtEQArgs `xml:"u:ResetExtEQ,omitempty"`
GetVolume *GetVolumeArgs `xml:"u:GetVolume,omitempty"`
SetVolume *SetVolumeArgs `xml:"u:SetVolume,omitempty"`
SetRelativeVolume *SetRelativeVolumeArgs `xml:"u:SetRelativeVolume,omitempty"`
GetVolumeDB *GetVolumeDBArgs `xml:"u:GetVolumeDB,omitempty"`
SetVolumeDB *SetVolumeDBArgs `xml:"u:SetVolumeDB,omitempty"`
GetVolumeDBRange *GetVolumeDBRangeArgs `xml:"u:GetVolumeDBRange,omitempty"`
GetBass *GetBassArgs `xml:"u:GetBass,omitempty"`
SetBass *SetBassArgs `xml:"u:SetBass,omitempty"`
GetTreble *GetTrebleArgs `xml:"u:GetTreble,omitempty"`
SetTreble *SetTrebleArgs `xml:"u:SetTreble,omitempty"`
GetEQ *GetEQArgs `xml:"u:GetEQ,omitempty"`
SetEQ *SetEQArgs `xml:"u:SetEQ,omitempty"`
GetLoudness *GetLoudnessArgs `xml:"u:GetLoudness,omitempty"`
SetLoudness *SetLoudnessArgs `xml:"u:SetLoudness,omitempty"`
GetSupportsOutputFixed *GetSupportsOutputFixedArgs `xml:"u:GetSupportsOutputFixed,omitempty"`
GetOutputFixed *GetOutputFixedArgs `xml:"u:GetOutputFixed,omitempty"`
SetOutputFixed *SetOutputFixedArgs `xml:"u:SetOutputFixed,omitempty"`
GetHeadphoneConnected *GetHeadphoneConnectedArgs `xml:"u:GetHeadphoneConnected,omitempty"`
RampToVolume *RampToVolumeArgs `xml:"u:RampToVolume,omitempty"`
RestoreVolumePriorToRamp *RestoreVolumePriorToRampArgs `xml:"u:RestoreVolumePriorToRamp,omitempty"`
SetChannelMap *SetChannelMapArgs `xml:"u:SetChannelMap,omitempty"`
SetRoomCalibrationX *SetRoomCalibrationXArgs `xml:"u:SetRoomCalibrationX,omitempty"`
GetRoomCalibrationStatus *GetRoomCalibrationStatusArgs `xml:"u:GetRoomCalibrationStatus,omitempty"`
SetRoomCalibrationStatus *SetRoomCalibrationStatusArgs `xml:"u:SetRoomCalibrationStatus,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
GetMute *GetMuteResponse `xml:"GetMuteResponse,omitempty"`
SetMute *SetMuteResponse `xml:"SetMuteResponse,omitempty"`
ResetBasicEQ *ResetBasicEQResponse `xml:"ResetBasicEQResponse,omitempty"`
ResetExtEQ *ResetExtEQResponse `xml:"ResetExtEQResponse,omitempty"`
GetVolume *GetVolumeResponse `xml:"GetVolumeResponse,omitempty"`
SetVolume *SetVolumeResponse `xml:"SetVolumeResponse,omitempty"`
SetRelativeVolume *SetRelativeVolumeResponse `xml:"SetRelativeVolumeResponse,omitempty"`
GetVolumeDB *GetVolumeDBResponse `xml:"GetVolumeDBResponse,omitempty"`
SetVolumeDB *SetVolumeDBResponse `xml:"SetVolumeDBResponse,omitempty"`
GetVolumeDBRange *GetVolumeDBRangeResponse `xml:"GetVolumeDBRangeResponse,omitempty"`
GetBass *GetBassResponse `xml:"GetBassResponse,omitempty"`
SetBass *SetBassResponse `xml:"SetBassResponse,omitempty"`
GetTreble *GetTrebleResponse `xml:"GetTrebleResponse,omitempty"`
SetTreble *SetTrebleResponse `xml:"SetTrebleResponse,omitempty"`
GetEQ *GetEQResponse `xml:"GetEQResponse,omitempty"`
SetEQ *SetEQResponse `xml:"SetEQResponse,omitempty"`
GetLoudness *GetLoudnessResponse `xml:"GetLoudnessResponse,omitempty"`
SetLoudness *SetLoudnessResponse `xml:"SetLoudnessResponse,omitempty"`
GetSupportsOutputFixed *GetSupportsOutputFixedResponse `xml:"GetSupportsOutputFixedResponse,omitempty"`
GetOutputFixed *GetOutputFixedResponse `xml:"GetOutputFixedResponse,omitempty"`
SetOutputFixed *SetOutputFixedResponse `xml:"SetOutputFixedResponse,omitempty"`
GetHeadphoneConnected *GetHeadphoneConnectedResponse `xml:"GetHeadphoneConnectedResponse,omitempty"`
RampToVolume *RampToVolumeResponse `xml:"RampToVolumeResponse,omitempty"`
RestoreVolumePriorToRamp *RestoreVolumePriorToRampResponse `xml:"RestoreVolumePriorToRampResponse,omitempty"`
SetChannelMap *SetChannelMapResponse `xml:"SetChannelMapResponse,omitempty"`
SetRoomCalibrationX *SetRoomCalibrationXResponse `xml:"SetRoomCalibrationXResponse,omitempty"`
GetRoomCalibrationStatus *GetRoomCalibrationStatusResponse `xml:"GetRoomCalibrationStatusResponse,omitempty"`
SetRoomCalibrationStatus *SetRoomCalibrationStatusResponse `xml:"SetRoomCalibrationStatusResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type GetMuteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
// Allowed Value: SpeakerOnly
Channel string `xml:"Channel"`
}
type GetMuteResponse struct {
CurrentMute bool `xml:"CurrentMute"`
}
func (s *Service) GetMute(httpClient *http.Client, args *GetMuteArgs) (*GetMuteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetMute`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetMute: args},
})
if err != nil {
return nil, err
}
if r.Body.GetMute == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetMute()`)
}
return r.Body.GetMute, nil
}
type SetMuteArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
// Allowed Value: SpeakerOnly
Channel string `xml:"Channel"`
DesiredMute bool `xml:"DesiredMute"`
}
type SetMuteResponse struct {
}
func (s *Service) SetMute(httpClient *http.Client, args *SetMuteArgs) (*SetMuteResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetMute`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetMute: args},
})
if err != nil {
return nil, err
}
if r.Body.SetMute == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetMute()`)
}
return r.Body.SetMute, nil
}
type ResetBasicEQArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type ResetBasicEQResponse struct {
Bass int16 `xml:"Bass"`
Treble int16 `xml:"Treble"`
Loudness bool `xml:"Loudness"`
LeftVolume uint16 `xml:"LeftVolume"`
RightVolume uint16 `xml:"RightVolume"`
}
func (s *Service) ResetBasicEQ(httpClient *http.Client, args *ResetBasicEQArgs) (*ResetBasicEQResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ResetBasicEQ`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ResetBasicEQ: args},
})
if err != nil {
return nil, err
}
if r.Body.ResetBasicEQ == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.ResetBasicEQ()`)
}
return r.Body.ResetBasicEQ, nil
}
type ResetExtEQArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
EQType string `xml:"EQType"`
}
type ResetExtEQResponse struct {
}
func (s *Service) ResetExtEQ(httpClient *http.Client, args *ResetExtEQArgs) (*ResetExtEQResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ResetExtEQ`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ResetExtEQ: args},
})
if err != nil {
return nil, err
}
if r.Body.ResetExtEQ == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.ResetExtEQ()`)
}
return r.Body.ResetExtEQ, nil
}
type GetVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
}
type GetVolumeResponse struct {
CurrentVolume uint16 `xml:"CurrentVolume"`
}
func (s *Service) GetVolume(httpClient *http.Client, args *GetVolumeArgs) (*GetVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.GetVolume == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolume()`)
}
return r.Body.GetVolume, nil
}
type SetVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
// Allowed Range: 0 -> 100 step: 1
DesiredVolume uint16 `xml:"DesiredVolume"`
}
type SetVolumeResponse struct {
}
func (s *Service) SetVolume(httpClient *http.Client, args *SetVolumeArgs) (*SetVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetVolume == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetVolume()`)
}
return r.Body.SetVolume, nil
}
type SetRelativeVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
Adjustment int32 `xml:"Adjustment"`
}
type SetRelativeVolumeResponse struct {
NewVolume uint16 `xml:"NewVolume"`
}
func (s *Service) SetRelativeVolume(httpClient *http.Client, args *SetRelativeVolumeArgs) (*SetRelativeVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetRelativeVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetRelativeVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetRelativeVolume == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRelativeVolume()`)
}
return r.Body.SetRelativeVolume, nil
}
type GetVolumeDBArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
}
type GetVolumeDBResponse struct {
CurrentVolume int16 `xml:"CurrentVolume"`
}
func (s *Service) GetVolumeDB(httpClient *http.Client, args *GetVolumeDBArgs) (*GetVolumeDBResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetVolumeDB`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetVolumeDB: args},
})
if err != nil {
return nil, err
}
if r.Body.GetVolumeDB == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolumeDB()`)
}
return r.Body.GetVolumeDB, nil
}
type SetVolumeDBArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
DesiredVolume int16 `xml:"DesiredVolume"`
}
type SetVolumeDBResponse struct {
}
func (s *Service) SetVolumeDB(httpClient *http.Client, args *SetVolumeDBArgs) (*SetVolumeDBResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetVolumeDB`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetVolumeDB: args},
})
if err != nil {
return nil, err
}
if r.Body.SetVolumeDB == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetVolumeDB()`)
}
return r.Body.SetVolumeDB, nil
}
type GetVolumeDBRangeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
}
type GetVolumeDBRangeResponse struct {
MinValue int16 `xml:"MinValue"`
MaxValue int16 `xml:"MaxValue"`
}
func (s *Service) GetVolumeDBRange(httpClient *http.Client, args *GetVolumeDBRangeArgs) (*GetVolumeDBRangeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetVolumeDBRange`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetVolumeDBRange: args},
})
if err != nil {
return nil, err
}
if r.Body.GetVolumeDBRange == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetVolumeDBRange()`)
}
return r.Body.GetVolumeDBRange, nil
}
type GetBassArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetBassResponse struct {
CurrentBass int16 `xml:"CurrentBass"`
}
func (s *Service) GetBass(httpClient *http.Client, args *GetBassArgs) (*GetBassResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetBass`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetBass: args},
})
if err != nil {
return nil, err
}
if r.Body.GetBass == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetBass()`)
}
return r.Body.GetBass, nil
}
type SetBassArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Range: -10 -> 10 step: 1
DesiredBass int16 `xml:"DesiredBass"`
}
type SetBassResponse struct {
}
func (s *Service) SetBass(httpClient *http.Client, args *SetBassArgs) (*SetBassResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetBass`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetBass: args},
})
if err != nil {
return nil, err
}
if r.Body.SetBass == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetBass()`)
}
return r.Body.SetBass, nil
}
type GetTrebleArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetTrebleResponse struct {
CurrentTreble int16 `xml:"CurrentTreble"`
}
func (s *Service) GetTreble(httpClient *http.Client, args *GetTrebleArgs) (*GetTrebleResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetTreble`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetTreble: args},
})
if err != nil {
return nil, err
}
if r.Body.GetTreble == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetTreble()`)
}
return r.Body.GetTreble, nil
}
type SetTrebleArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Range: -10 -> 10 step: 1
DesiredTreble int16 `xml:"DesiredTreble"`
}
type SetTrebleResponse struct {
}
func (s *Service) SetTreble(httpClient *http.Client, args *SetTrebleArgs) (*SetTrebleResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetTreble`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetTreble: args},
})
if err != nil {
return nil, err
}
if r.Body.SetTreble == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetTreble()`)
}
return r.Body.SetTreble, nil
}
type GetEQArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
EQType string `xml:"EQType"`
}
type GetEQResponse struct {
CurrentValue int16 `xml:"CurrentValue"`
}
func (s *Service) GetEQ(httpClient *http.Client, args *GetEQArgs) (*GetEQResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetEQ`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetEQ: args},
})
if err != nil {
return nil, err
}
if r.Body.GetEQ == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetEQ()`)
}
return r.Body.GetEQ, nil
}
type SetEQArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
EQType string `xml:"EQType"`
DesiredValue int16 `xml:"DesiredValue"`
}
type SetEQResponse struct {
}
func (s *Service) SetEQ(httpClient *http.Client, args *SetEQArgs) (*SetEQResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetEQ`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetEQ: args},
})
if err != nil {
return nil, err
}
if r.Body.SetEQ == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetEQ()`)
}
return r.Body.SetEQ, nil
}
type GetLoudnessArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
}
type GetLoudnessResponse struct {
CurrentLoudness bool `xml:"CurrentLoudness"`
}
func (s *Service) GetLoudness(httpClient *http.Client, args *GetLoudnessArgs) (*GetLoudnessResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetLoudness`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetLoudness: args},
})
if err != nil {
return nil, err
}
if r.Body.GetLoudness == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetLoudness()`)
}
return r.Body.GetLoudness, nil
}
type SetLoudnessArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
DesiredLoudness bool `xml:"DesiredLoudness"`
}
type SetLoudnessResponse struct {
}
func (s *Service) SetLoudness(httpClient *http.Client, args *SetLoudnessArgs) (*SetLoudnessResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetLoudness`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetLoudness: args},
})
if err != nil {
return nil, err
}
if r.Body.SetLoudness == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetLoudness()`)
}
return r.Body.SetLoudness, nil
}
type GetSupportsOutputFixedArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetSupportsOutputFixedResponse struct {
CurrentSupportsFixed bool `xml:"CurrentSupportsFixed"`
}
func (s *Service) GetSupportsOutputFixed(httpClient *http.Client, args *GetSupportsOutputFixedArgs) (*GetSupportsOutputFixedResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetSupportsOutputFixed`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetSupportsOutputFixed: args},
})
if err != nil {
return nil, err
}
if r.Body.GetSupportsOutputFixed == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetSupportsOutputFixed()`)
}
return r.Body.GetSupportsOutputFixed, nil
}
type GetOutputFixedArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetOutputFixedResponse struct {
CurrentFixed bool `xml:"CurrentFixed"`
}
func (s *Service) GetOutputFixed(httpClient *http.Client, args *GetOutputFixedArgs) (*GetOutputFixedResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetOutputFixed`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetOutputFixed: args},
})
if err != nil {
return nil, err
}
if r.Body.GetOutputFixed == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetOutputFixed()`)
}
return r.Body.GetOutputFixed, nil
}
type SetOutputFixedArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
DesiredFixed bool `xml:"DesiredFixed"`
}
type SetOutputFixedResponse struct {
}
func (s *Service) SetOutputFixed(httpClient *http.Client, args *SetOutputFixedArgs) (*SetOutputFixedResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetOutputFixed`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetOutputFixed: args},
})
if err != nil {
return nil, err
}
if r.Body.SetOutputFixed == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetOutputFixed()`)
}
return r.Body.SetOutputFixed, nil
}
type GetHeadphoneConnectedArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetHeadphoneConnectedResponse struct {
CurrentHeadphoneConnected bool `xml:"CurrentHeadphoneConnected"`
}
func (s *Service) GetHeadphoneConnected(httpClient *http.Client, args *GetHeadphoneConnectedArgs) (*GetHeadphoneConnectedResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetHeadphoneConnected`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetHeadphoneConnected: args},
})
if err != nil {
return nil, err
}
if r.Body.GetHeadphoneConnected == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetHeadphoneConnected()`)
}
return r.Body.GetHeadphoneConnected, nil
}
type RampToVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
// Allowed Value: SLEEP_TIMER_RAMP_TYPE
// Allowed Value: ALARM_RAMP_TYPE
// Allowed Value: AUTOPLAY_RAMP_TYPE
RampType string `xml:"RampType"`
// Allowed Range: 0 -> 100 step: 1
DesiredVolume uint16 `xml:"DesiredVolume"`
ResetVolumeAfter bool `xml:"ResetVolumeAfter"`
ProgramURI string `xml:"ProgramURI"`
}
type RampToVolumeResponse struct {
RampTime uint32 `xml:"RampTime"`
}
func (s *Service) RampToVolume(httpClient *http.Client, args *RampToVolumeArgs) (*RampToVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RampToVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RampToVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.RampToVolume == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.RampToVolume()`)
}
return r.Body.RampToVolume, nil
}
type RestoreVolumePriorToRampArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
// Allowed Value: Master
// Allowed Value: LF
// Allowed Value: RF
Channel string `xml:"Channel"`
}
type RestoreVolumePriorToRampResponse struct {
}
func (s *Service) RestoreVolumePriorToRamp(httpClient *http.Client, args *RestoreVolumePriorToRampArgs) (*RestoreVolumePriorToRampResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RestoreVolumePriorToRamp`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RestoreVolumePriorToRamp: args},
})
if err != nil {
return nil, err
}
if r.Body.RestoreVolumePriorToRamp == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.RestoreVolumePriorToRamp()`)
}
return r.Body.RestoreVolumePriorToRamp, nil
}
type SetChannelMapArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
ChannelMap string `xml:"ChannelMap"`
}
type SetChannelMapResponse struct {
}
func (s *Service) SetChannelMap(httpClient *http.Client, args *SetChannelMapArgs) (*SetChannelMapResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetChannelMap`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetChannelMap: args},
})
if err != nil {
return nil, err
}
if r.Body.SetChannelMap == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetChannelMap()`)
}
return r.Body.SetChannelMap, nil
}
type SetRoomCalibrationXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
CalibrationID string `xml:"CalibrationID"`
Coefficients string `xml:"Coefficients"`
CalibrationMode string `xml:"CalibrationMode"`
}
type SetRoomCalibrationXResponse struct {
}
func (s *Service) SetRoomCalibrationX(httpClient *http.Client, args *SetRoomCalibrationXArgs) (*SetRoomCalibrationXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetRoomCalibrationX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetRoomCalibrationX: args},
})
if err != nil {
return nil, err
}
if r.Body.SetRoomCalibrationX == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRoomCalibrationX()`)
}
return r.Body.SetRoomCalibrationX, nil
}
type GetRoomCalibrationStatusArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type GetRoomCalibrationStatusResponse struct {
RoomCalibrationEnabled bool `xml:"RoomCalibrationEnabled"`
RoomCalibrationAvailable bool `xml:"RoomCalibrationAvailable"`
}
func (s *Service) GetRoomCalibrationStatus(httpClient *http.Client, args *GetRoomCalibrationStatusArgs) (*GetRoomCalibrationStatusResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetRoomCalibrationStatus`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetRoomCalibrationStatus: args},
})
if err != nil {
return nil, err
}
if r.Body.GetRoomCalibrationStatus == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.GetRoomCalibrationStatus()`)
}
return r.Body.GetRoomCalibrationStatus, nil
}
type SetRoomCalibrationStatusArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
RoomCalibrationEnabled bool `xml:"RoomCalibrationEnabled"`
}
type SetRoomCalibrationStatusResponse struct {
}
func (s *Service) SetRoomCalibrationStatus(httpClient *http.Client, args *SetRoomCalibrationStatusArgs) (*SetRoomCalibrationStatusResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetRoomCalibrationStatus`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetRoomCalibrationStatus: args},
})
if err != nil {
return nil, err
}
if r.Body.SetRoomCalibrationStatus == nil {
return nil, errors.New(`unexpected respose from service calling renderingcontrol.SetRoomCalibrationStatus()`)
}
return r.Body.SetRoomCalibrationStatus, nil
}
+576
View File
@@ -0,0 +1,576 @@
package systemproperties
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:SystemProperties:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/SystemProperties/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/SystemProperties/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
SetString *SetStringArgs `xml:"u:SetString,omitempty"`
GetString *GetStringArgs `xml:"u:GetString,omitempty"`
Remove *RemoveArgs `xml:"u:Remove,omitempty"`
GetWebCode *GetWebCodeArgs `xml:"u:GetWebCode,omitempty"`
ProvisionCredentialedTrialAccountX *ProvisionCredentialedTrialAccountXArgs `xml:"u:ProvisionCredentialedTrialAccountX,omitempty"`
AddAccountX *AddAccountXArgs `xml:"u:AddAccountX,omitempty"`
AddOAuthAccountX *AddOAuthAccountXArgs `xml:"u:AddOAuthAccountX,omitempty"`
RemoveAccount *RemoveAccountArgs `xml:"u:RemoveAccount,omitempty"`
EditAccountPasswordX *EditAccountPasswordXArgs `xml:"u:EditAccountPasswordX,omitempty"`
SetAccountNicknameX *SetAccountNicknameXArgs `xml:"u:SetAccountNicknameX,omitempty"`
RefreshAccountCredentialsX *RefreshAccountCredentialsXArgs `xml:"u:RefreshAccountCredentialsX,omitempty"`
EditAccountMd *EditAccountMdArgs `xml:"u:EditAccountMd,omitempty"`
DoPostUpdateTasks *DoPostUpdateTasksArgs `xml:"u:DoPostUpdateTasks,omitempty"`
ResetThirdPartyCredentials *ResetThirdPartyCredentialsArgs `xml:"u:ResetThirdPartyCredentials,omitempty"`
EnableRDM *EnableRDMArgs `xml:"u:EnableRDM,omitempty"`
GetRDM *GetRDMArgs `xml:"u:GetRDM,omitempty"`
ReplaceAccountX *ReplaceAccountXArgs `xml:"u:ReplaceAccountX,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
SetString *SetStringResponse `xml:"SetStringResponse,omitempty"`
GetString *GetStringResponse `xml:"GetStringResponse,omitempty"`
Remove *RemoveResponse `xml:"RemoveResponse,omitempty"`
GetWebCode *GetWebCodeResponse `xml:"GetWebCodeResponse,omitempty"`
ProvisionCredentialedTrialAccountX *ProvisionCredentialedTrialAccountXResponse `xml:"ProvisionCredentialedTrialAccountXResponse,omitempty"`
AddAccountX *AddAccountXResponse `xml:"AddAccountXResponse,omitempty"`
AddOAuthAccountX *AddOAuthAccountXResponse `xml:"AddOAuthAccountXResponse,omitempty"`
RemoveAccount *RemoveAccountResponse `xml:"RemoveAccountResponse,omitempty"`
EditAccountPasswordX *EditAccountPasswordXResponse `xml:"EditAccountPasswordXResponse,omitempty"`
SetAccountNicknameX *SetAccountNicknameXResponse `xml:"SetAccountNicknameXResponse,omitempty"`
RefreshAccountCredentialsX *RefreshAccountCredentialsXResponse `xml:"RefreshAccountCredentialsXResponse,omitempty"`
EditAccountMd *EditAccountMdResponse `xml:"EditAccountMdResponse,omitempty"`
DoPostUpdateTasks *DoPostUpdateTasksResponse `xml:"DoPostUpdateTasksResponse,omitempty"`
ResetThirdPartyCredentials *ResetThirdPartyCredentialsResponse `xml:"ResetThirdPartyCredentialsResponse,omitempty"`
EnableRDM *EnableRDMResponse `xml:"EnableRDMResponse,omitempty"`
GetRDM *GetRDMResponse `xml:"GetRDMResponse,omitempty"`
ReplaceAccountX *ReplaceAccountXResponse `xml:"ReplaceAccountXResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type SetStringArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
VariableName string `xml:"VariableName"`
StringValue string `xml:"StringValue"`
}
type SetStringResponse struct {
}
func (s *Service) SetString(httpClient *http.Client, args *SetStringArgs) (*SetStringResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetString`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetString: args},
})
if err != nil {
return nil, err
}
if r.Body.SetString == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.SetString()`)
}
return r.Body.SetString, nil
}
type GetStringArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
VariableName string `xml:"VariableName"`
}
type GetStringResponse struct {
StringValue string `xml:"StringValue"`
}
func (s *Service) GetString(httpClient *http.Client, args *GetStringArgs) (*GetStringResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetString`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetString: args},
})
if err != nil {
return nil, err
}
if r.Body.GetString == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.GetString()`)
}
return r.Body.GetString, nil
}
type RemoveArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
VariableName string `xml:"VariableName"`
}
type RemoveResponse struct {
}
func (s *Service) Remove(httpClient *http.Client, args *RemoveArgs) (*RemoveResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Remove`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Remove: args},
})
if err != nil {
return nil, err
}
if r.Body.Remove == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.Remove()`)
}
return r.Body.Remove, nil
}
type GetWebCodeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
}
type GetWebCodeResponse struct {
WebCode string `xml:"WebCode"`
}
func (s *Service) GetWebCode(httpClient *http.Client, args *GetWebCodeArgs) (*GetWebCodeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetWebCode`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetWebCode: args},
})
if err != nil {
return nil, err
}
if r.Body.GetWebCode == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.GetWebCode()`)
}
return r.Body.GetWebCode, nil
}
type ProvisionCredentialedTrialAccountXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountID string `xml:"AccountID"`
AccountPassword string `xml:"AccountPassword"`
}
type ProvisionCredentialedTrialAccountXResponse struct {
IsExpired bool `xml:"IsExpired"`
AccountUDN string `xml:"AccountUDN"`
}
func (s *Service) ProvisionCredentialedTrialAccountX(httpClient *http.Client, args *ProvisionCredentialedTrialAccountXArgs) (*ProvisionCredentialedTrialAccountXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ProvisionCredentialedTrialAccountX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ProvisionCredentialedTrialAccountX: args},
})
if err != nil {
return nil, err
}
if r.Body.ProvisionCredentialedTrialAccountX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.ProvisionCredentialedTrialAccountX()`)
}
return r.Body.ProvisionCredentialedTrialAccountX, nil
}
type AddAccountXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountID string `xml:"AccountID"`
AccountPassword string `xml:"AccountPassword"`
}
type AddAccountXResponse struct {
AccountUDN string `xml:"AccountUDN"`
}
func (s *Service) AddAccountX(httpClient *http.Client, args *AddAccountXArgs) (*AddAccountXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddAccountX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddAccountX: args},
})
if err != nil {
return nil, err
}
if r.Body.AddAccountX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.AddAccountX()`)
}
return r.Body.AddAccountX, nil
}
type AddOAuthAccountXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountToken string `xml:"AccountToken"`
AccountKey string `xml:"AccountKey"`
OAuthDeviceID string `xml:"OAuthDeviceID"`
AuthorizationCode string `xml:"AuthorizationCode"`
RedirectURI string `xml:"RedirectURI"`
UserIdHashCode string `xml:"UserIdHashCode"`
AccountTier uint32 `xml:"AccountTier"`
}
type AddOAuthAccountXResponse struct {
AccountUDN string `xml:"AccountUDN"`
AccountNickname string `xml:"AccountNickname"`
}
func (s *Service) AddOAuthAccountX(httpClient *http.Client, args *AddOAuthAccountXArgs) (*AddOAuthAccountXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`AddOAuthAccountX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{AddOAuthAccountX: args},
})
if err != nil {
return nil, err
}
if r.Body.AddOAuthAccountX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.AddOAuthAccountX()`)
}
return r.Body.AddOAuthAccountX, nil
}
type RemoveAccountArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountID string `xml:"AccountID"`
}
type RemoveAccountResponse struct {
}
func (s *Service) RemoveAccount(httpClient *http.Client, args *RemoveAccountArgs) (*RemoveAccountResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RemoveAccount`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RemoveAccount: args},
})
if err != nil {
return nil, err
}
if r.Body.RemoveAccount == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.RemoveAccount()`)
}
return r.Body.RemoveAccount, nil
}
type EditAccountPasswordXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountID string `xml:"AccountID"`
NewAccountPassword string `xml:"NewAccountPassword"`
}
type EditAccountPasswordXResponse struct {
}
func (s *Service) EditAccountPasswordX(httpClient *http.Client, args *EditAccountPasswordXArgs) (*EditAccountPasswordXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`EditAccountPasswordX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{EditAccountPasswordX: args},
})
if err != nil {
return nil, err
}
if r.Body.EditAccountPasswordX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.EditAccountPasswordX()`)
}
return r.Body.EditAccountPasswordX, nil
}
type SetAccountNicknameXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountUDN string `xml:"AccountUDN"`
AccountNickname string `xml:"AccountNickname"`
}
type SetAccountNicknameXResponse struct {
}
func (s *Service) SetAccountNicknameX(httpClient *http.Client, args *SetAccountNicknameXArgs) (*SetAccountNicknameXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetAccountNicknameX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetAccountNicknameX: args},
})
if err != nil {
return nil, err
}
if r.Body.SetAccountNicknameX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.SetAccountNicknameX()`)
}
return r.Body.SetAccountNicknameX, nil
}
type RefreshAccountCredentialsXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountUID uint32 `xml:"AccountUID"`
AccountToken string `xml:"AccountToken"`
AccountKey string `xml:"AccountKey"`
}
type RefreshAccountCredentialsXResponse struct {
}
func (s *Service) RefreshAccountCredentialsX(httpClient *http.Client, args *RefreshAccountCredentialsXArgs) (*RefreshAccountCredentialsXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RefreshAccountCredentialsX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RefreshAccountCredentialsX: args},
})
if err != nil {
return nil, err
}
if r.Body.RefreshAccountCredentialsX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.RefreshAccountCredentialsX()`)
}
return r.Body.RefreshAccountCredentialsX, nil
}
type EditAccountMdArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountType uint32 `xml:"AccountType"`
AccountID string `xml:"AccountID"`
NewAccountMd string `xml:"NewAccountMd"`
}
type EditAccountMdResponse struct {
}
func (s *Service) EditAccountMd(httpClient *http.Client, args *EditAccountMdArgs) (*EditAccountMdResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`EditAccountMd`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{EditAccountMd: args},
})
if err != nil {
return nil, err
}
if r.Body.EditAccountMd == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.EditAccountMd()`)
}
return r.Body.EditAccountMd, nil
}
type DoPostUpdateTasksArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type DoPostUpdateTasksResponse struct {
}
func (s *Service) DoPostUpdateTasks(httpClient *http.Client, args *DoPostUpdateTasksArgs) (*DoPostUpdateTasksResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`DoPostUpdateTasks`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{DoPostUpdateTasks: args},
})
if err != nil {
return nil, err
}
if r.Body.DoPostUpdateTasks == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.DoPostUpdateTasks()`)
}
return r.Body.DoPostUpdateTasks, nil
}
type ResetThirdPartyCredentialsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type ResetThirdPartyCredentialsResponse struct {
}
func (s *Service) ResetThirdPartyCredentials(httpClient *http.Client, args *ResetThirdPartyCredentialsArgs) (*ResetThirdPartyCredentialsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ResetThirdPartyCredentials`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ResetThirdPartyCredentials: args},
})
if err != nil {
return nil, err
}
if r.Body.ResetThirdPartyCredentials == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.ResetThirdPartyCredentials()`)
}
return r.Body.ResetThirdPartyCredentials, nil
}
type EnableRDMArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
RDMValue bool `xml:"RDMValue"`
}
type EnableRDMResponse struct {
}
func (s *Service) EnableRDM(httpClient *http.Client, args *EnableRDMArgs) (*EnableRDMResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`EnableRDM`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{EnableRDM: args},
})
if err != nil {
return nil, err
}
if r.Body.EnableRDM == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.EnableRDM()`)
}
return r.Body.EnableRDM, nil
}
type GetRDMArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetRDMResponse struct {
RDMValue bool `xml:"RDMValue"`
}
func (s *Service) GetRDM(httpClient *http.Client, args *GetRDMArgs) (*GetRDMResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetRDM`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetRDM: args},
})
if err != nil {
return nil, err
}
if r.Body.GetRDM == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.GetRDM()`)
}
return r.Body.GetRDM, nil
}
type ReplaceAccountXArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
AccountUDN string `xml:"AccountUDN"`
NewAccountID string `xml:"NewAccountID"`
NewAccountPassword string `xml:"NewAccountPassword"`
AccountToken string `xml:"AccountToken"`
AccountKey string `xml:"AccountKey"`
OAuthDeviceID string `xml:"OAuthDeviceID"`
}
type ReplaceAccountXResponse struct {
NewAccountUDN string `xml:"NewAccountUDN"`
}
func (s *Service) ReplaceAccountX(httpClient *http.Client, args *ReplaceAccountXArgs) (*ReplaceAccountXResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReplaceAccountX`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReplaceAccountX: args},
})
if err != nil {
return nil, err
}
if r.Body.ReplaceAccountX == nil {
return nil, errors.New(`unexpected respose from service calling systemproperties.ReplaceAccountX()`)
}
return r.Body.ReplaceAccountX, nil
}
+306
View File
@@ -0,0 +1,306 @@
package virtuallinein
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:VirtualLineIn:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/MediaRenderer/VirtualLineIn/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/MediaRenderer/VirtualLineIn/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
StartTransmission *StartTransmissionArgs `xml:"u:StartTransmission,omitempty"`
StopTransmission *StopTransmissionArgs `xml:"u:StopTransmission,omitempty"`
Play *PlayArgs `xml:"u:Play,omitempty"`
Pause *PauseArgs `xml:"u:Pause,omitempty"`
Next *NextArgs `xml:"u:Next,omitempty"`
Previous *PreviousArgs `xml:"u:Previous,omitempty"`
Stop *StopArgs `xml:"u:Stop,omitempty"`
SetVolume *SetVolumeArgs `xml:"u:SetVolume,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
StartTransmission *StartTransmissionResponse `xml:"StartTransmissionResponse,omitempty"`
StopTransmission *StopTransmissionResponse `xml:"StopTransmissionResponse,omitempty"`
Play *PlayResponse `xml:"PlayResponse,omitempty"`
Pause *PauseResponse `xml:"PauseResponse,omitempty"`
Next *NextResponse `xml:"NextResponse,omitempty"`
Previous *PreviousResponse `xml:"PreviousResponse,omitempty"`
Stop *StopResponse `xml:"StopResponse,omitempty"`
SetVolume *SetVolumeResponse `xml:"SetVolumeResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type StartTransmissionArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
CoordinatorID string `xml:"CoordinatorID"`
}
type StartTransmissionResponse struct {
CurrentTransportSettings string `xml:"CurrentTransportSettings"`
}
func (s *Service) StartTransmission(httpClient *http.Client, args *StartTransmissionArgs) (*StartTransmissionResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`StartTransmission`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{StartTransmission: args},
})
if err != nil {
return nil, err
}
if r.Body.StartTransmission == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.StartTransmission()`)
}
return r.Body.StartTransmission, nil
}
type StopTransmissionArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
CoordinatorID string `xml:"CoordinatorID"`
}
type StopTransmissionResponse struct {
}
func (s *Service) StopTransmission(httpClient *http.Client, args *StopTransmissionArgs) (*StopTransmissionResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`StopTransmission`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{StopTransmission: args},
})
if err != nil {
return nil, err
}
if r.Body.StopTransmission == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.StopTransmission()`)
}
return r.Body.StopTransmission, nil
}
type PlayArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
Speed string `xml:"Speed"`
}
type PlayResponse struct {
}
func (s *Service) Play(httpClient *http.Client, args *PlayArgs) (*PlayResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Play`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Play: args},
})
if err != nil {
return nil, err
}
if r.Body.Play == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.Play()`)
}
return r.Body.Play, nil
}
type PauseArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type PauseResponse struct {
}
func (s *Service) Pause(httpClient *http.Client, args *PauseArgs) (*PauseResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Pause`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Pause: args},
})
if err != nil {
return nil, err
}
if r.Body.Pause == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.Pause()`)
}
return r.Body.Pause, nil
}
type NextArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type NextResponse struct {
}
func (s *Service) Next(httpClient *http.Client, args *NextArgs) (*NextResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Next`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Next: args},
})
if err != nil {
return nil, err
}
if r.Body.Next == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.Next()`)
}
return r.Body.Next, nil
}
type PreviousArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type PreviousResponse struct {
}
func (s *Service) Previous(httpClient *http.Client, args *PreviousArgs) (*PreviousResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Previous`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Previous: args},
})
if err != nil {
return nil, err
}
if r.Body.Previous == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.Previous()`)
}
return r.Body.Previous, nil
}
type StopArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
}
type StopResponse struct {
}
func (s *Service) Stop(httpClient *http.Client, args *StopArgs) (*StopResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`Stop`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{Stop: args},
})
if err != nil {
return nil, err
}
if r.Body.Stop == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.Stop()`)
}
return r.Body.Stop, nil
}
type SetVolumeArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
InstanceID uint32 `xml:"InstanceID"`
DesiredVolume uint16 `xml:"DesiredVolume"`
}
type SetVolumeResponse struct {
}
func (s *Service) SetVolume(httpClient *http.Client, args *SetVolumeArgs) (*SetVolumeResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SetVolume`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SetVolume: args},
})
if err != nil {
return nil, err
}
if r.Body.SetVolume == nil {
return nil, errors.New(`unexpected respose from service calling virtuallinein.SetVolume()`)
}
return r.Body.SetVolume, nil
}
+318
View File
@@ -0,0 +1,318 @@
package zonegrouptopology
import (
"bytes"
"encoding/xml"
"errors"
"io/ioutil"
"net/http"
"net/url"
)
const (
_ServiceURN = "urn:schemas-upnp-org:service:ZoneGroupTopology:1"
_EncodingSchema = "http://schemas.xmlsoap.org/soap/encoding/"
_EnvelopeSchema = "http://schemas.xmlsoap.org/soap/envelope/"
)
type Service struct {
ControlEndpoint *url.URL
EventEndpoint *url.URL
}
func NewService(deviceUrl *url.URL) *Service {
c, err := url.Parse(`/ZoneGroupTopology/Control`)
if nil != err {
panic(err)
}
e, err := url.Parse(`/ZoneGroupTopology/Event`)
if nil != err {
panic(err)
}
return &Service{
ControlEndpoint: deviceUrl.ResolveReference(c),
EventEndpoint: deviceUrl.ResolveReference(e),
}
}
type Envelope struct {
XMLName xml.Name `xml:"s:Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"s:encodingStyle,attr"`
Body Body `xml:"s:Body"`
}
type Body struct {
XMLName xml.Name `xml:"s:Body"`
CheckForUpdate *CheckForUpdateArgs `xml:"u:CheckForUpdate,omitempty"`
BeginSoftwareUpdate *BeginSoftwareUpdateArgs `xml:"u:BeginSoftwareUpdate,omitempty"`
ReportUnresponsiveDevice *ReportUnresponsiveDeviceArgs `xml:"u:ReportUnresponsiveDevice,omitempty"`
ReportAlarmStartedRunning *ReportAlarmStartedRunningArgs `xml:"u:ReportAlarmStartedRunning,omitempty"`
SubmitDiagnostics *SubmitDiagnosticsArgs `xml:"u:SubmitDiagnostics,omitempty"`
RegisterMobileDevice *RegisterMobileDeviceArgs `xml:"u:RegisterMobileDevice,omitempty"`
GetZoneGroupAttributes *GetZoneGroupAttributesArgs `xml:"u:GetZoneGroupAttributes,omitempty"`
GetZoneGroupState *GetZoneGroupStateArgs `xml:"u:GetZoneGroupState,omitempty"`
}
type EnvelopeResponse struct {
XMLName xml.Name `xml:"Envelope"`
Xmlns string `xml:"xmlns:s,attr"`
EncodingStyle string `xml:"encodingStyle,attr"`
Body BodyResponse `xml:"Body"`
}
type BodyResponse struct {
XMLName xml.Name `xml:"Body"`
CheckForUpdate *CheckForUpdateResponse `xml:"CheckForUpdateResponse,omitempty"`
BeginSoftwareUpdate *BeginSoftwareUpdateResponse `xml:"BeginSoftwareUpdateResponse,omitempty"`
ReportUnresponsiveDevice *ReportUnresponsiveDeviceResponse `xml:"ReportUnresponsiveDeviceResponse,omitempty"`
ReportAlarmStartedRunning *ReportAlarmStartedRunningResponse `xml:"ReportAlarmStartedRunningResponse,omitempty"`
SubmitDiagnostics *SubmitDiagnosticsResponse `xml:"SubmitDiagnosticsResponse,omitempty"`
RegisterMobileDevice *RegisterMobileDeviceResponse `xml:"RegisterMobileDeviceResponse,omitempty"`
GetZoneGroupAttributes *GetZoneGroupAttributesResponse `xml:"GetZoneGroupAttributesResponse,omitempty"`
GetZoneGroupState *GetZoneGroupStateResponse `xml:"GetZoneGroupStateResponse,omitempty"`
}
func (s *Service) exec(actionName string, httpClient *http.Client, envelope *Envelope) (*EnvelopeResponse, error) {
marshaled, err := xml.Marshal(envelope)
if err != nil {
return nil, err
}
postBody := []byte(`<?xml version="1.0"?>`)
postBody = append(postBody, marshaled...)
req, err := http.NewRequest(`POST`, s.ControlEndpoint.String(), bytes.NewBuffer(postBody))
if err != nil {
return nil, err
}
req.Header.Set(`Content-Type`, `text/xml; charset="utf-8"`)
req.Header.Set(`SOAPAction`, _ServiceURN+`#`+actionName)
res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
responseBody, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var envelopeResponse EnvelopeResponse
err = xml.Unmarshal(responseBody, &envelopeResponse)
if err != nil {
return nil, err
}
return &envelopeResponse, nil
}
type CheckForUpdateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
// Allowed Value: All
// Allowed Value: Software
UpdateType string `xml:"UpdateType"`
CachedOnly bool `xml:"CachedOnly"`
Version string `xml:"Version"`
}
type CheckForUpdateResponse struct {
UpdateItem string `xml:"UpdateItem"`
}
func (s *Service) CheckForUpdate(httpClient *http.Client, args *CheckForUpdateArgs) (*CheckForUpdateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`CheckForUpdate`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{CheckForUpdate: args},
})
if err != nil {
return nil, err
}
if r.Body.CheckForUpdate == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.CheckForUpdate()`)
}
return r.Body.CheckForUpdate, nil
}
type BeginSoftwareUpdateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
UpdateURL string `xml:"UpdateURL"`
Flags uint32 `xml:"Flags"`
ExtraOptions string `xml:"ExtraOptions"`
}
type BeginSoftwareUpdateResponse struct {
}
func (s *Service) BeginSoftwareUpdate(httpClient *http.Client, args *BeginSoftwareUpdateArgs) (*BeginSoftwareUpdateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`BeginSoftwareUpdate`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{BeginSoftwareUpdate: args},
})
if err != nil {
return nil, err
}
if r.Body.BeginSoftwareUpdate == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.BeginSoftwareUpdate()`)
}
return r.Body.BeginSoftwareUpdate, nil
}
type ReportUnresponsiveDeviceArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
DeviceUUID string `xml:"DeviceUUID"`
// Allowed Value: Remove
// Allowed Value: TopologyMonitorProbe
// Allowed Value: VerifyThenRemoveSystemwide
DesiredAction string `xml:"DesiredAction"`
}
type ReportUnresponsiveDeviceResponse struct {
}
func (s *Service) ReportUnresponsiveDevice(httpClient *http.Client, args *ReportUnresponsiveDeviceArgs) (*ReportUnresponsiveDeviceResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReportUnresponsiveDevice`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReportUnresponsiveDevice: args},
})
if err != nil {
return nil, err
}
if r.Body.ReportUnresponsiveDevice == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.ReportUnresponsiveDevice()`)
}
return r.Body.ReportUnresponsiveDevice, nil
}
type ReportAlarmStartedRunningArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type ReportAlarmStartedRunningResponse struct {
}
func (s *Service) ReportAlarmStartedRunning(httpClient *http.Client, args *ReportAlarmStartedRunningArgs) (*ReportAlarmStartedRunningResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`ReportAlarmStartedRunning`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{ReportAlarmStartedRunning: args},
})
if err != nil {
return nil, err
}
if r.Body.ReportAlarmStartedRunning == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.ReportAlarmStartedRunning()`)
}
return r.Body.ReportAlarmStartedRunning, nil
}
type SubmitDiagnosticsArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
IncludeControllers bool `xml:"IncludeControllers"`
Type string `xml:"Type"`
}
type SubmitDiagnosticsResponse struct {
DiagnosticID uint32 `xml:"DiagnosticID"`
}
func (s *Service) SubmitDiagnostics(httpClient *http.Client, args *SubmitDiagnosticsArgs) (*SubmitDiagnosticsResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`SubmitDiagnostics`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{SubmitDiagnostics: args},
})
if err != nil {
return nil, err
}
if r.Body.SubmitDiagnostics == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.SubmitDiagnostics()`)
}
return r.Body.SubmitDiagnostics, nil
}
type RegisterMobileDeviceArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
MobileDeviceName string `xml:"MobileDeviceName"`
MobileDeviceUDN string `xml:"MobileDeviceUDN"`
MobileIPAndPort string `xml:"MobileIPAndPort"`
}
type RegisterMobileDeviceResponse struct {
}
func (s *Service) RegisterMobileDevice(httpClient *http.Client, args *RegisterMobileDeviceArgs) (*RegisterMobileDeviceResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`RegisterMobileDevice`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{RegisterMobileDevice: args},
})
if err != nil {
return nil, err
}
if r.Body.RegisterMobileDevice == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.RegisterMobileDevice()`)
}
return r.Body.RegisterMobileDevice, nil
}
type GetZoneGroupAttributesArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetZoneGroupAttributesResponse struct {
CurrentZoneGroupName string `xml:"CurrentZoneGroupName"`
CurrentZoneGroupID string `xml:"CurrentZoneGroupID"`
CurrentZonePlayerUUIDsInGroup string `xml:"CurrentZonePlayerUUIDsInGroup"`
CurrentMuseHouseholdId string `xml:"CurrentMuseHouseholdId"`
}
func (s *Service) GetZoneGroupAttributes(httpClient *http.Client, args *GetZoneGroupAttributesArgs) (*GetZoneGroupAttributesResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetZoneGroupAttributes`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetZoneGroupAttributes: args},
})
if err != nil {
return nil, err
}
if r.Body.GetZoneGroupAttributes == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.GetZoneGroupAttributes()`)
}
return r.Body.GetZoneGroupAttributes, nil
}
type GetZoneGroupStateArgs struct {
Xmlns string `xml:"xmlns:u,attr"`
}
type GetZoneGroupStateResponse struct {
ZoneGroupState string `xml:"ZoneGroupState"`
}
func (s *Service) GetZoneGroupState(httpClient *http.Client, args *GetZoneGroupStateArgs) (*GetZoneGroupStateResponse, error) {
args.Xmlns = _ServiceURN
r, err := s.exec(`GetZoneGroupState`, httpClient,
&Envelope{
EncodingStyle: _EncodingSchema,
Xmlns: _EnvelopeSchema,
Body: Body{GetZoneGroupState: args},
})
if err != nil {
return nil, err
}
if r.Body.GetZoneGroupState == nil {
return nil, errors.New(`unexpected respose from service calling zonegrouptopology.GetZoneGroupState()`)
}
return r.Body.GetZoneGroupState, nil
}
+100
View File
@@ -0,0 +1,100 @@
package sonos
import (
"bufio"
"errors"
"fmt"
"net"
"net/http"
"net/url"
"time"
)
const (
mx = 5
st = "urn:schemas-upnp-org:device:ZonePlayer:1"
bcastaddr = "239.255.255.250:1900"
)
type Sonos struct {
// Context Context
listenSocket *net.UDPConn
udpReader *bufio.Reader
found chan *ZonePlayer
}
func NewSonos() (*Sonos, error) {
conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: []byte{0, 0, 0, 0}, Port: 0, Zone: ""})
if err != nil {
return nil, err
}
s := Sonos{
listenSocket: conn,
udpReader: bufio.NewReader(conn),
found: make(chan *ZonePlayer),
}
return &s, nil
}
func (s *Sonos) Close() {
s.listenSocket.Close()
}
func (s *Sonos) Search() (chan *ZonePlayer, error) {
go func() {
for {
response, err := http.ReadResponse(s.udpReader, nil)
if err != nil {
continue
}
location, err := url.Parse(response.Header.Get("Location"))
if err != nil {
continue
}
zp, err := NewZonePlayer(location)
if err != nil {
continue
}
if zp.IsCoordinator() {
s.found <- zp
}
}
}()
// MX should be set to use timeout value in integer seconds
pkt := []byte(fmt.Sprintf("M-SEARCH * HTTP/1.1\r\nHOST: %s\r\nMAN: \"ssdp:discover\"\r\nMX: %d\r\nST: %s\r\n\r\n", bcastaddr, mx, st))
bcast, err := net.ResolveUDPAddr("udp", bcastaddr)
if err != nil {
return nil, err
}
_, err = s.listenSocket.WriteTo(pkt, bcast)
if err != nil {
return nil, err
}
return s.found, nil
}
func FindRoom(room string, timeout time.Duration) (*ZonePlayer, error) {
son, err := NewSonos()
if err != nil {
return nil, err
}
defer son.Close()
found, _ := son.Search()
to := time.After(timeout)
for {
select {
case <-to:
return nil, errors.New("timeout")
case zp := <-found:
if zp.RoomName() == room {
return zp, nil
}
}
}
}
+107
View File
@@ -0,0 +1,107 @@
package sonos
import "encoding/xml"
type VanishedDevice struct {
XMLName xml.Name `xml:"VanishedDevice"`
UUID string `xml:"UUID"`
Location string `xml:"Location"`
ZoneName string `xml:"ZoneName"`
Icon string `xml:"Icon"`
Configuration string `xml:"Configuration"`
SoftwareVersion string `xml:"SoftwareVersion"`
SWGen string `xml:"SWGen"`
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
BootSeq string `xml:"BootSeq"`
TVConfigurationError string `xml:"TVConfigurationError"`
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
WirelessMode string `xml:"WirelessMode"`
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
ChannelFreq string `xml:"ChannelFreq"`
BehindWifiExtender string `xml:"BehindWifiExtender"`
WifiEnabled string `xml:"WifiEnabled"`
Orientation string `xml:"Orientation"`
RoomCalibrationState string `xml:"RoomCalibrationState"`
SecureRegState string `xml:"SecureRegState"`
VoiceConfigState string `xml:"VoiceConfigState"`
MicEnabled string `xml:"MicEnabled"`
AirPlayEnabled string `xml:"AirPlayEnabled"`
IdleState string `xml:"IdleState"`
MoreInfo string `xml:"MoreInfo"`
}
type Satellite struct {
XMLName xml.Name `xml:"Satellite"`
UUID string `xml:"UUID"`
Location string `xml:"Location"`
ZoneName string `xml:"ZoneName"`
Icon string `xml:"Icon"`
Configuration string `xml:"Configuration"`
SoftwareVersion string `xml:"SoftwareVersion"`
SWGen string `xml:"SWGen"`
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
BootSeq string `xml:"BootSeq"`
TVConfigurationError string `xml:"TVConfigurationError"`
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
WirelessMode string `xml:"WirelessMode"`
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
ChannelFreq string `xml:"ChannelFreq"`
BehindWifiExtender string `xml:"BehindWifiExtender"`
WifiEnabled string `xml:"WifiEnabled"`
Orientation string `xml:"Orientation"`
RoomCalibrationState string `xml:"RoomCalibrationState"`
SecureRegState string `xml:"SecureRegState"`
VoiceConfigState string `xml:"VoiceConfigState"`
MicEnabled string `xml:"MicEnabled"`
AirPlayEnabled string `xml:"AirPlayEnabled"`
IdleState string `xml:"IdleState"`
MoreInfo string `xml:"MoreInfo"`
}
type ZoneGroupMember struct {
XMLName xml.Name `xml:"ZoneGroupMember"`
UUID string `xml:"UUID"`
Location string `xml:"Location"`
ZoneName string `xml:"ZoneName"`
Icon string `xml:"Icon"`
Configuration string `xml:"Configuration"`
SoftwareVersion string `xml:"SoftwareVersion"`
SWGen string `xml:"SWGen"`
MinCompatibleVersion string `xml:"MinCompatibleVersion"`
LegacyCompatibleVersion string `xml:"LegacyCompatibleVersion"`
BootSeq string `xml:"BootSeq"`
TVConfigurationError string `xml:"TVConfigurationError"`
HdmiCecAvailable string `xml:"HdmiCecAvailable"`
WirelessMode string `xml:"WirelessMode"`
WirelessLeafOnly string `xml:"WirelessLeafOnly"`
HasConfiguredSSID string `xml:"HasConfiguredSSID"`
ChannelFreq string `xml:"ChannelFreq"`
BehindWifiExtender string `xml:"BehindWifiExtender"`
WifiEnabled string `xml:"WifiEnabled"`
Orientation string `xml:"Orientation"`
RoomCalibrationState string `xml:"RoomCalibrationState"`
SecureRegState string `xml:"SecureRegState"`
VoiceConfigState string `xml:"VoiceConfigState"`
MicEnabled string `xml:"MicEnabled"`
AirPlayEnabled string `xml:"AirPlayEnabled"`
IdleState string `xml:"IdleState"`
MoreInfo string `xml:"MoreInfo"`
Satellite []Satellite `xml:"Satellite>Satellite"`
VanishedDevice []VanishedDevice `xml:"VanishedDevices>VanishedDevice"`
}
type ZoneGroup struct {
XMLName xml.Name `xml:"ZoneGroup"`
Coordinator string `xml:"Coordinator,attr"`
ID string `xml:"ID,attr"`
ZoneGroupMember []ZoneGroupMember `xml:"ZoneGroupMember"`
}
type ZoneGroupState struct {
XMLName xml.Name `xml:"ZoneGroupState"`
ZoneGroups []ZoneGroup `xml:"ZoneGroups>ZoneGroup"`
}
+236
View File
@@ -0,0 +1,236 @@
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
}
+20
View File
@@ -73,6 +73,9 @@ github.com/goccy/go-json/internal/runtime
# github.com/google/uuid v1.3.0
## explicit
github.com/google/uuid
# github.com/holoplot/go-evdev v0.0.0-20230626094006-70c9462cc0f2
## explicit; go 1.18
github.com/holoplot/go-evdev
# github.com/json-iterator/go v1.1.12
## explicit; go 1.12
github.com/json-iterator/go
@@ -205,6 +208,23 @@ github.com/pmezard/go-difflib/difflib
## explicit; go 1.20
github.com/stretchr/testify/assert
github.com/stretchr/testify/require
# github.com/szatmary/sonos v0.0.0-20191204204454-000c9219ff0e
## explicit
github.com/szatmary/sonos
github.com/szatmary/sonos/AVTransport
github.com/szatmary/sonos/AlarmClock
github.com/szatmary/sonos/ConnectionManager
github.com/szatmary/sonos/ContentDirectory
github.com/szatmary/sonos/DeviceProperties
github.com/szatmary/sonos/GroupManagement
github.com/szatmary/sonos/GroupRenderingControl
github.com/szatmary/sonos/MusicServices
github.com/szatmary/sonos/QPlay
github.com/szatmary/sonos/Queue
github.com/szatmary/sonos/RenderingControl
github.com/szatmary/sonos/SystemProperties
github.com/szatmary/sonos/VirtualLineIn
github.com/szatmary/sonos/ZoneGroupTopology
# github.com/tinyzimmer/go-glib v0.0.25
## explicit; go 1.16
github.com/tinyzimmer/go-glib/glib