Skip to content

Commit

Permalink
Handle race conditions at startup/init
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelveldt committed Aug 26, 2024
1 parent fb7a4bd commit 7080d7f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
1 change: 1 addition & 0 deletions aiosonos/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Reference: https://docs.sonos.com/docs/types
"""

from __future__ import annotations

from enum import StrEnum
Expand Down
61 changes: 45 additions & 16 deletions aiosonos/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,62 @@
from contextlib import suppress
from typing import TYPE_CHECKING

from aiosonos.api.models import ContainerType, MusicService, PlayBackState
from aiosonos.api.models import (
ContainerType,
MetadataStatus,
MusicService,
PlayBackState,
)
from aiosonos.api.models import GroupVolume as GroupVolumeData
from aiosonos.api.models import PlaybackStatus as PlaybackStatusData
from aiosonos.api.models import PlayModes as PlayModesData
from aiosonos.const import EventType, GroupEvent
from aiosonos.exceptions import FailedCommand

from .api.models import PlaybackActions as PlaybackActionsData

if TYPE_CHECKING:
from aiosonos.api.models import Container
from aiosonos.api.models import GroupVolume as GroupVolumeData
from aiosonos.api.models import MetadataStatus
from aiosonos.api.models import PlaybackStatus as PlaybackStatusData
from aiosonos.api.models import PlayModes as PlayModesData
from aiosonos.api.models import SessionStatus, Track
from aiosonos.api.models import Container, SessionStatus, Track

from .api.models import Group as GroupData
from .api.models import PlaybackActions as PlaybackActionsData
from .client import SonosLocalApiClient


class SonosGroup:
"""Representation of a Sonos Group."""

_playback_status_data: PlaybackStatusData
_playback_metadata_data: MetadataStatus
_volume_data: GroupVolumeData
_playback_actions: PlaybackActions
_play_modes: PlayModes

def __init__(self, client: SonosLocalApiClient, data: GroupData) -> None:
"""Handle initialization."""
self.client = client
self.active_session_id: str | None = None
self._data = data
# to prevent race conditions at startup/init,
# we set some default values for the status dicts here
self._play_modes = PlayModes({})
self._volume_data = GroupVolumeData(
objectType="groupVolume", fixed=False, volume=0, mute=False
)
self._playback_actions = playback_actions = PlaybackActionsData(
canCrossfade=False,
canPause=False,
canPlay=False,
canSeek=False,
canSkipBackward=False,
canSkipForward=False,
canStop=False,
)
self._playback_status_data: PlaybackStatusData = PlaybackStatusData(
objectType="playbackStatus",
availablePlaybackActions=playback_actions,
isDucking=False,
playbackState=PlayBackState.PLAYBACK_STATE_IDLE,
playModes=PlayModesData(),
positionMillis=0,
previousPositionMillis=0,
)
self._playback_metadata_data: MetadataStatus = MetadataStatus(
objectType="metadataStatus"
)
self._playback_status_last_updated: float = 0.0
self._unsubscribe_callbacks = []

Expand All @@ -62,7 +87,9 @@ async def async_init(self) -> None:
# grab playback data and setup subscription
try:
self._volume_data = await self.client.api.group_volume.get_volume(self.id)
self._playback_status_data = await self.client.api.playback.get_playback_status(self.id)
self._playback_status_data = (
await self.client.api.playback.get_playback_status(self.id)
)
self._playback_status_last_updated = time.time()
self._playback_actions = PlaybackActions(
self._playback_status_data["availablePlaybackActions"],
Expand Down Expand Up @@ -187,7 +214,9 @@ def active_service(self) -> MusicService | None:
"""Return the active service of the active source of this group (if any)."""
if not (container := self._playback_metadata_data.get("container")):
return None
if (container_id := container.get("id")) and (service_id := container_id.get("serviceId")):
if (container_id := container.get("id")) and (
service_id := container_id.get("serviceId")
):
if service_id in MusicService:
return MusicService(service_id)
# return the raw string value if it's not a known container type
Expand Down

0 comments on commit 7080d7f

Please sign in to comment.