+35
-11
@@ -378,20 +378,38 @@ class Controller:
|
||||
reply = self.heos.command("player/get_play_state", pid=self.playback_pid(key))
|
||||
return parse_message(reply["heos"]["message"]).get("state", "stop")
|
||||
|
||||
def on_spotify(self, key: str) -> bool:
|
||||
"""Whether a room's now-playing is a Spotify stream, playing or
|
||||
paused -- the only thing its play/pause and next buttons make sense
|
||||
for. An idle player can refuse the query outright, which is "not
|
||||
Spotify" too."""
|
||||
def now_playing_media(self, key: str) -> dict:
|
||||
"""HEOS's get_now_playing_media payload for a room. An idle player
|
||||
can refuse the query outright, which is the same as nothing loaded."""
|
||||
with self._lock:
|
||||
self._fresh()
|
||||
try:
|
||||
reply = self.heos.command("player/get_now_playing_media", pid=self.playback_pid(key))
|
||||
except HeosError:
|
||||
return False
|
||||
payload = reply.get("payload") or {}
|
||||
return (str(payload.get("sid")) == self.SPOTIFY_SID
|
||||
or str(payload.get("mid", "")).startswith("spotify:"))
|
||||
return {}
|
||||
return reply.get("payload") or {}
|
||||
|
||||
@classmethod
|
||||
def _is_spotify(cls, media: dict) -> bool:
|
||||
return (str(media.get("sid")) == cls.SPOTIFY_SID
|
||||
or str(media.get("mid", "")).startswith("spotify:"))
|
||||
|
||||
@staticmethod
|
||||
def _track(media: dict):
|
||||
"""{"song", "artist", "image"} for a room's card, or None when there
|
||||
is no song to show. An AVR input is not one: HEOS fills in its
|
||||
"song" with the input's own name, which the input picker already
|
||||
shows. Artist and cover are None when HEOS has nothing for them."""
|
||||
song = media.get("song")
|
||||
if not song or str(media.get("mid", "")).startswith("inputs/"):
|
||||
return None
|
||||
return {"song": song, "artist": media.get("artist") or None, "image": media.get("image_url") or None}
|
||||
|
||||
def on_spotify(self, key: str) -> bool:
|
||||
"""Whether a room's now-playing is a Spotify stream, playing or
|
||||
paused -- the only thing its play/pause and next buttons make sense
|
||||
for."""
|
||||
return self._is_spotify(self.now_playing_media(key))
|
||||
|
||||
def toggle_play(self, key: str, state: str = None) -> str:
|
||||
"""Start or stop a room. With no state, flips whatever it is doing
|
||||
@@ -506,13 +524,19 @@ class Controller:
|
||||
"volume": None,
|
||||
"play_state": None,
|
||||
"spotify": False,
|
||||
"now_playing": None,
|
||||
"error": None,
|
||||
}
|
||||
try:
|
||||
scope, obj_id = self._volume_handles(key)[0]
|
||||
room["volume"] = self._read_volume(scope, obj_id)
|
||||
room["play_state"] = self.get_play_state(key)
|
||||
room["spotify"] = self.on_spotify(key)
|
||||
media = self.now_playing_media(key)
|
||||
room["spotify"] = self._is_spotify(media)
|
||||
# Kept while paused, so the card does not jump about
|
||||
# under the thumb that just pressed pause.
|
||||
if room["play_state"] != "stop":
|
||||
room["now_playing"] = self._track(media)
|
||||
except (TargetError, HeosError, KeyError) as exc:
|
||||
room["available"] = False
|
||||
room["error"] = str(exc)
|
||||
@@ -523,7 +547,7 @@ class Controller:
|
||||
snapshot["rooms"] = [
|
||||
{"key": key, "label": self.cfg.TARGETS[key]["label"], "available": False,
|
||||
"grouped": False, "volume": None, "play_state": None, "spotify": False,
|
||||
"error": str(exc)}
|
||||
"now_playing": None, "error": str(exc)}
|
||||
for key in self.cfg.ROOM_KEYS
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user