Skip to content

Commit

Permalink
Support info (device name and other meta-information) in the status. (#…
Browse files Browse the repository at this point in the history
…202)

* Support info (device name and other meta-information) in the status.

Examplar result:
```
% curl "http://0.0.0.0:8011/status?uuid=edfaf976-0411-41c4-9e5a-724c8781f0bc" | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   610  100   610    0     0    288      0  0:00:02  0:00:02 --:--:--   288
{
  "info": {
    "name": "Sisters Room speaker",
    "ip_address": "192.168.0.161",
    "locale": "pl",
    "mac_address": "54:60:09:D0:10:A4",
    "ssid": "Szum",
    "timezone": "Europe/Warsaw",
    "uptime": 45394.987882
  },
  "app_id": "",
  "display_name": "",
  "is_idle_screen": false,
  "status_text": "",
  "player_state": "",
  "current_time": 0,
  "idle_reason": "",
  "current_item_id": 0,
  "loading_item_id": 0,
  "content_id": "",
  "content_type": "",
  "stream_type": "",
  "duration": 0,
  "artist": "",
  "title": "",
  "subtitle": "",
  "volume_level": 0.89,
  "volume_muted": false,
  "media_volume_level": 0,
  "media_volume_muted": false,
  "session_id": "",
  "transport_id": "",
  "media_session_id": 0,
  "player_state_id": 0
}
```

* Regenerate mocks.

* Fixed error support.

* Support for cast groups.

* Delete info.

* Cache info.

* Cleanup.
  • Loading branch information
ptabor authored Dec 1, 2024
1 parent 92f518d commit 2ac6d1b
Show file tree
Hide file tree
Showing 14 changed files with 412 additions and 63 deletions.
35 changes: 34 additions & 1 deletion application/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (

"github.com/buger/jsonparser"
"github.com/pkg/errors"

"github.com/vishen/go-chromecast/cast"
pb "github.com/vishen/go-chromecast/cast/proto"
"github.com/vishen/go-chromecast/playlists"
Expand Down Expand Up @@ -66,6 +65,7 @@ type App interface {
Close(stopMedia bool) error
LoadApp(appID, contentID string) error
Status() (*cast.Application, *cast.Media, *cast.Volume)
Info() (*cast.DeviceInfo, error)
Update() error
Pause() error
Unpause() error
Expand Down Expand Up @@ -93,6 +93,9 @@ type Application struct {
conn cast.Conn
debug bool

// Device name override (originating e.g. from mdns lookup).
deviceNameOverride string

// Internal mapping of request id to result channel
resultChanMap map[int]chan *pb.CastMessage

Expand All @@ -107,6 +110,7 @@ type Application struct {
// Current values from the chromecast.
application *cast.Application // It is possible that there is no current application, can happen for google home.
media *cast.Media
info *cast.DeviceInfo
// There seems to be two different volumes returned from the chromecast,
// one for the receiver and one for the playing media. It looks we update
// the receiver volume from go-chromecast, so we should use that one. But
Expand Down Expand Up @@ -187,6 +191,12 @@ func WithSkipadRetries(retries int) ApplicationOption {
}
}

func WithDeviceNameOverride(deviceName string) ApplicationOption {
return func(a *Application) {
a.SetDeviceNameOverride(deviceName)
}
}

func NewApplication(opts ...ApplicationOption) *Application {
a := &Application{
conn: cast.NewConnection(),
Expand Down Expand Up @@ -223,6 +233,10 @@ func (a *Application) SetIface(iface *net.Interface) { a.iface = iface }
func (a *Application) SetSkipadSleep(sleep time.Duration) { a.skipadSleep = sleep }
func (a *Application) SetSkipadRetries(retries int) { a.skipadRetries = retries }

func (a *Application) SetDeviceNameOverride(deviceName string) {
a.deviceNameOverride = deviceName
}

func (a *Application) App() *cast.Application { return a.application }
func (a *Application) Media() *cast.Media { return a.media }
func (a *Application) Volume() *cast.Volume { return a.volumeReceiver }
Expand Down Expand Up @@ -437,6 +451,25 @@ func (a *Application) Status() (*cast.Application, *cast.Media, *cast.Volume) {
return a.application, a.media, a.volumeReceiver
}

func (a *Application) Info() (*cast.DeviceInfo, error) {
if a.info != nil {
return a.info, nil
}
addr, err := a.conn.RemoteAddr()
if err != nil {
return nil, err
}
info, err := GetInfo(addr)
if err != nil {
return nil, err
}
if len(a.deviceNameOverride) > 0 {
info.Name = a.deviceNameOverride
}
a.info = info
return info, err
}

func (a *Application) Pause() error {
if a.media == nil {
return ErrNoMediaPause
Expand Down
35 changes: 35 additions & 0 deletions application/info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package application

import (
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/vishen/go-chromecast/cast"
)

// getInfo uses the http://<ip>:8008/setup/eureka_endpoint to obtain more
// information about the cast-device.
// OBS: The 8008 seems to be pure http, whereas 8009 is typically the port
// to use for protobuf-communication,

func GetInfo(ip string) (info *cast.DeviceInfo, err error) {
// Note: Services exposed not on 8009 port are "Google Cast Group"s
// The only way to find the true device (group) name, is using mDNS outside of this function.
url := fmt.Sprintf("http://%v:8008/setup/eureka_info", ip)
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
info = new(cast.DeviceInfo)
if err := json.Unmarshal(data, info); err != nil {
return nil, err
}
return info, nil
}
Loading

0 comments on commit 2ac6d1b

Please sign in to comment.