mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Handle more Sonos snapshot restore scenarios (#53277)
This commit is contained in:
parent
b2528e97b6
commit
0707792bec
@ -14,7 +14,7 @@ import async_timeout
|
||||
from pysonos.core import MUSIC_SRC_LINE_IN, MUSIC_SRC_RADIO, MUSIC_SRC_TV, SoCo
|
||||
from pysonos.data_structures import DidlAudioBroadcast, DidlPlaylistContainer
|
||||
from pysonos.events_base import Event as SonosEvent, SubscriptionBase
|
||||
from pysonos.exceptions import SoCoException
|
||||
from pysonos.exceptions import SoCoException, SoCoUPnPException
|
||||
from pysonos.music_library import MusicLibrary
|
||||
from pysonos.plugins.sharelink import ShareLinkPlugin
|
||||
from pysonos.snapshot import Snapshot
|
||||
@ -25,6 +25,7 @@ from homeassistant.components.media_player import DOMAIN as MP_DOMAIN
|
||||
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as ent_reg
|
||||
from homeassistant.helpers.dispatcher import (
|
||||
async_dispatcher_send,
|
||||
@ -802,27 +803,58 @@ class SonosSpeaker:
|
||||
"""Restore snapshots for all the speakers."""
|
||||
|
||||
def _restore_groups(
|
||||
speakers: list[SonosSpeaker], with_group: bool
|
||||
speakers: set[SonosSpeaker], with_group: bool
|
||||
) -> list[list[SonosSpeaker]]:
|
||||
"""Pause all current coordinators and restore groups."""
|
||||
for speaker in (s for s in speakers if s.is_coordinator):
|
||||
if speaker.media.playback_status == SONOS_STATE_PLAYING:
|
||||
speaker.soco.pause()
|
||||
if (
|
||||
speaker.media.playback_status == SONOS_STATE_PLAYING
|
||||
and "Pause" in speaker.soco.available_actions
|
||||
):
|
||||
try:
|
||||
speaker.soco.pause()
|
||||
except SoCoUPnPException as exc:
|
||||
_LOGGER.debug(
|
||||
"Pause failed during restore of %s: %s",
|
||||
speaker.zone_name,
|
||||
speaker.soco.available_actions,
|
||||
exc_info=exc,
|
||||
)
|
||||
|
||||
groups = []
|
||||
if not with_group:
|
||||
return groups
|
||||
|
||||
if with_group:
|
||||
# Unjoin slaves first to prevent inheritance of queues
|
||||
for speaker in [s for s in speakers if not s.is_coordinator]:
|
||||
if speaker.snapshot_group != speaker.sonos_group:
|
||||
speaker.unjoin()
|
||||
# Unjoin non-coordinator speakers not contained in the desired snapshot group
|
||||
#
|
||||
# If a coordinator is unjoined from its group, another speaker from the group
|
||||
# will inherit the coordinator's playqueue and its own playqueue will be lost
|
||||
speakers_to_unjoin = set()
|
||||
for speaker in speakers:
|
||||
if speaker.sonos_group == speaker.snapshot_group:
|
||||
continue
|
||||
|
||||
# Bring back the original group topology
|
||||
for speaker in (s for s in speakers if s.snapshot_group):
|
||||
assert speaker.snapshot_group is not None
|
||||
if speaker.snapshot_group[0] == speaker:
|
||||
speakers_to_unjoin.update(
|
||||
{
|
||||
s
|
||||
for s in speaker.sonos_group[1:]
|
||||
if s not in speaker.snapshot_group
|
||||
}
|
||||
)
|
||||
|
||||
for speaker in speakers_to_unjoin:
|
||||
speaker.unjoin()
|
||||
|
||||
# Bring back the original group topology
|
||||
for speaker in (s for s in speakers if s.snapshot_group):
|
||||
assert speaker.snapshot_group is not None
|
||||
if speaker.snapshot_group[0] == speaker:
|
||||
if (
|
||||
speaker.snapshot_group != speaker.sonos_group
|
||||
and speaker.snapshot_group != [speaker]
|
||||
):
|
||||
speaker.join(speaker.snapshot_group)
|
||||
groups.append(speaker.snapshot_group.copy())
|
||||
groups.append(speaker.snapshot_group.copy())
|
||||
|
||||
return groups
|
||||
|
||||
@ -836,6 +868,11 @@ class SonosSpeaker:
|
||||
|
||||
# Find all affected players
|
||||
speakers_set = {s for s in speakers if s.soco_snapshot}
|
||||
if missing_snapshots := set(speakers) - speakers_set:
|
||||
raise HomeAssistantError(
|
||||
f"Restore failed, speakers are missing snapshots: {[s.zone_name for s in missing_snapshots]}"
|
||||
)
|
||||
|
||||
if with_group:
|
||||
for speaker in [s for s in speakers_set if s.snapshot_group]:
|
||||
assert speaker.snapshot_group is not None
|
||||
|
Loading…
x
Reference in New Issue
Block a user