Add volume management to AVR
Deploy HEOS panel / deploy (push) Successful in 26s

This commit is contained in:
franzz committed 2026-09-20 18:18:28 +02:00
1 parent db00e57ef7
commit 9a3d0b8a72
6 files changed
+42 -19

No files matched your search

+23 -8
View File
@@ -138,10 +138,18 @@ class Controller:
def _id_param(scope: str) -> str:
return "pid" if scope == "player" else "gid"
def _read_volume(self, scope, obj_id) -> int:
reply = self.heos.command(f"{scope}/get_volume", **{self._id_param(scope): obj_id})
@staticmethod
def _level_in(reply) -> int:
"""The level a get_volume reply carries, or None when there is no
answer to read -- a player that was never asked, or one whose reply
came back a HeosError."""
if reply is None or isinstance(reply, HeosError):
return None
return int(parse_message(reply["heos"]["message"]).get("level", -1))
def _read_volume(self, scope, obj_id) -> int:
return self._level_in(self.heos.command(f"{scope}/get_volume", **{self._id_param(scope): obj_id}))
def volume(self, key: str) -> int:
with self._lock:
self._fresh()
@@ -470,13 +478,13 @@ class Controller:
snapshot = {
"host": {"key": self.cfg.HOST_KEY, "label": self.cfg.TARGETS[self.cfg.HOST_KEY]["label"]},
"rooms": [],
"avr": {"connected": False, "input": None, "inputs": []},
"avr": {"connected": False, "input": None, "inputs": [], "volume": None},
"heos_ok": True,
"errors": [],
}
host_pid = None
avr_now_playing = None
avr_replies = {}
with self._lock:
try:
self.scan()
@@ -502,14 +510,19 @@ class Controller:
]
request_keys += [(key, "volume"), (key, "play_state"), (key, "now_playing")]
if host_pid is not None:
requests.append(("player/get_now_playing_media", {"pid": host_pid}))
request_keys.append((None, "avr_now_playing"))
# The AVR is a player like any other, so its own volume
# rides along in the same batch as the rooms'.
requests += [
("player/get_volume", {"pid": host_pid}),
("player/get_now_playing_media", {"pid": host_pid}),
]
request_keys += [(None, "volume"), (None, "now_playing")]
results = self.heos.command_batch(requests) if requests else []
by_room = {}
for (key, field), result in zip(request_keys, results):
if key is None:
avr_now_playing = result
avr_replies[field] = result
else:
by_room.setdefault(key, {})[field] = result
@@ -533,7 +546,7 @@ class Controller:
volume_reply = data.get("volume")
if isinstance(volume_reply, HeosError):
raise volume_reply
room["volume"] = int(parse_message(volume_reply["heos"]["message"]).get("level", -1))
room["volume"] = self._level_in(volume_reply)
play_reply = data.get("play_state")
if isinstance(play_reply, HeosError):
@@ -569,6 +582,7 @@ class Controller:
try:
current_input = None
avr_now_playing = avr_replies.get("now_playing")
if host_pid is not None and avr_now_playing is not None and not isinstance(avr_now_playing, HeosError):
payload = avr_now_playing.get("payload") or {}
mid = payload.get("mid", "")
@@ -578,6 +592,7 @@ class Controller:
"connected": host_pid is not None,
"inputs": self.avr_inputs(),
"input": current_input,
"volume": self._level_in(avr_replies.get("volume")),
"now_playing": self.zidoo_now_playing(current_input),
}
except (HeosError, TargetError) as exc: