device_info: DeviceInfo
supported_features: tuple[PlayerFeature, ...] = field(default=())
- elapsed_time: float = 0
- elapsed_time_last_updated: float = time.time()
- state: PlayerState = PlayerState.IDLE
-
- volume_level: int = 100
- volume_muted: bool = False
+ elapsed_time: float | None = None
+ elapsed_time_last_updated: float | None = None
+ state: PlayerState | None = None
+ volume_level: int | None = None
+ volume_muted: bool | None = None
# group_childs: Return list of player group child id's or synced child`s.
# - If this player is a dedicated group player,
_prev_volume_level: int = 0
@property
- def corrected_elapsed_time(self) -> float:
+ def corrected_elapsed_time(self) -> float | None:
"""Return the corrected/realtime elapsed time."""
+ if self.elapsed_time is None or self.elapsed_time_last_updated is None:
+ return None
if self.state == PlayerState.PLAYING:
return self.elapsed_time + (time.time() - self.elapsed_time_last_updated)
return self.elapsed_time
def current_item_id(self, uri: str) -> None:
"""Set current_item_id (for backwards compatibility)."""
self.current_media = PlayerMedia(uri)
+
+ def __post_serialize__(self, d: dict[Any, Any]) -> dict[Any, Any]:
+ """Execute action(s) on serialization."""
+ # TEMP: convert values to prevent api breakage
+ # this may be removed after 2.3 has been launched to stable
+ if self.elapsed_time is None:
+ d["elapsed_time"] = 0
+ if self.elapsed_time_last_updated is None:
+ d["elapsed_time_last_updated"] = 0
+ if self.volume_level is None:
+ d["volume_level"] = 0
+ if self.volume_muted is None:
+ d["volume_muted"] = False
+ if self.state is None:
+ d["state"] = PlayerState.IDLE
+ return d
streamdetails.pop("expires", None)
streamdetails.pop("path", None)
streamdetails.pop("decryption_key", None)
+ # pop loudness from streamdetails in api to keep api from breaking
+ # (due to the loudness field's type change in 2.3)
+ # this may be removed after 2.3 has been launched to stable
+ streamdetails.pop("loudness", None)
+ streamdetails.pop("loudness_album", None)
return d
@property
if item_id := self._parse_player_current_item_id(queue_id, player):
queue.current_index = self.index_by_id(queue_id, item_id)
if player.state in (PlayerState.PLAYING, PlayerState.PAUSED):
- queue.elapsed_time = int(player.corrected_elapsed_time)
- queue.elapsed_time_last_updated = player.elapsed_time_last_updated
+ queue.elapsed_time = int(player.corrected_elapsed_time or 0)
+ queue.elapsed_time_last_updated = player.elapsed_time_last_updated or 0
# only update these attributes if the queue is active
# and has an item loaded so we are able to resume it
- queue.state = player.state
+ queue.state = player.state or PlayerState.IDLE
queue.current_item = self.get_item(queue_id, queue.current_index)
queue.next_item = self._get_next_item(queue_id)
"""Calculate current queue index and current track elapsed time."""
# player is playing a constant stream so we need to do this the hard way
queue_index = 0
- elapsed_time_queue = player.corrected_elapsed_time
+ elapsed_time_queue = player.corrected_elapsed_time or 0
total_time = 0
track_time = 0
queue_items = self._queue_items[queue.queue_id]