Update Spotify state after mutation (#129607)
This commit is contained in:
parent
41a81cbf15
commit
02750452df
2 changed files with 34 additions and 2 deletions
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
import asyncio
|
||||||
|
from collections.abc import Awaitable, Callable, Coroutine
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, Concatenate
|
||||||
|
|
||||||
from spotifyaio import (
|
from spotifyaio import (
|
||||||
Device,
|
Device,
|
||||||
|
@ -63,6 +64,7 @@ REPEAT_MODE_MAPPING_TO_HA = {
|
||||||
REPEAT_MODE_MAPPING_TO_SPOTIFY = {
|
REPEAT_MODE_MAPPING_TO_SPOTIFY = {
|
||||||
value: key for key, value in REPEAT_MODE_MAPPING_TO_HA.items()
|
value: key for key, value in REPEAT_MODE_MAPPING_TO_HA.items()
|
||||||
}
|
}
|
||||||
|
AFTER_REQUEST_SLEEP = 1
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
@ -93,6 +95,19 @@ def ensure_item[_R](
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def async_refresh_after[_T: SpotifyEntity, **_P](
|
||||||
|
func: Callable[Concatenate[_T, _P], Awaitable[None]],
|
||||||
|
) -> Callable[Concatenate[_T, _P], Coroutine[Any, Any, None]]:
|
||||||
|
"""Define a wrapper to yield and refresh after."""
|
||||||
|
|
||||||
|
async def _async_wrap(self: _T, *args: _P.args, **kwargs: _P.kwargs) -> None:
|
||||||
|
await func(self, *args, **kwargs)
|
||||||
|
await asyncio.sleep(AFTER_REQUEST_SLEEP)
|
||||||
|
await self.coordinator.async_refresh()
|
||||||
|
|
||||||
|
return _async_wrap
|
||||||
|
|
||||||
|
|
||||||
class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
|
class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
|
||||||
"""Representation of a Spotify controller."""
|
"""Representation of a Spotify controller."""
|
||||||
|
|
||||||
|
@ -267,30 +282,37 @@ class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
|
||||||
return None
|
return None
|
||||||
return REPEAT_MODE_MAPPING_TO_HA.get(self.currently_playing.repeat_mode)
|
return REPEAT_MODE_MAPPING_TO_HA.get(self.currently_playing.repeat_mode)
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_set_volume_level(self, volume: float) -> None:
|
async def async_set_volume_level(self, volume: float) -> None:
|
||||||
"""Set the volume level."""
|
"""Set the volume level."""
|
||||||
await self.coordinator.client.set_volume(int(volume * 100))
|
await self.coordinator.client.set_volume(int(volume * 100))
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_media_play(self) -> None:
|
async def async_media_play(self) -> None:
|
||||||
"""Start or resume playback."""
|
"""Start or resume playback."""
|
||||||
await self.coordinator.client.start_playback()
|
await self.coordinator.client.start_playback()
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_media_pause(self) -> None:
|
async def async_media_pause(self) -> None:
|
||||||
"""Pause playback."""
|
"""Pause playback."""
|
||||||
await self.coordinator.client.pause_playback()
|
await self.coordinator.client.pause_playback()
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_media_previous_track(self) -> None:
|
async def async_media_previous_track(self) -> None:
|
||||||
"""Skip to previous track."""
|
"""Skip to previous track."""
|
||||||
await self.coordinator.client.previous_track()
|
await self.coordinator.client.previous_track()
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_media_next_track(self) -> None:
|
async def async_media_next_track(self) -> None:
|
||||||
"""Skip to next track."""
|
"""Skip to next track."""
|
||||||
await self.coordinator.client.next_track()
|
await self.coordinator.client.next_track()
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_media_seek(self, position: float) -> None:
|
async def async_media_seek(self, position: float) -> None:
|
||||||
"""Send seek command."""
|
"""Send seek command."""
|
||||||
await self.coordinator.client.seek_track(int(position * 1000))
|
await self.coordinator.client.seek_track(int(position * 1000))
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_play_media(
|
async def async_play_media(
|
||||||
self, media_type: MediaType | str, media_id: str, **kwargs: Any
|
self, media_type: MediaType | str, media_id: str, **kwargs: Any
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -334,6 +356,7 @@ class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
|
||||||
|
|
||||||
await self.coordinator.client.start_playback(**kwargs)
|
await self.coordinator.client.start_playback(**kwargs)
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_select_source(self, source: str) -> None:
|
async def async_select_source(self, source: str) -> None:
|
||||||
"""Select playback device."""
|
"""Select playback device."""
|
||||||
for device in self.devices.data:
|
for device in self.devices.data:
|
||||||
|
@ -341,10 +364,12 @@ class SpotifyMediaPlayer(SpotifyEntity, MediaPlayerEntity):
|
||||||
await self.coordinator.client.transfer_playback(device.device_id)
|
await self.coordinator.client.transfer_playback(device.device_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_set_shuffle(self, shuffle: bool) -> None:
|
async def async_set_shuffle(self, shuffle: bool) -> None:
|
||||||
"""Enable/Disable shuffle mode."""
|
"""Enable/Disable shuffle mode."""
|
||||||
await self.coordinator.client.set_shuffle(state=shuffle)
|
await self.coordinator.client.set_shuffle(state=shuffle)
|
||||||
|
|
||||||
|
@async_refresh_after
|
||||||
async def async_set_repeat(self, repeat: RepeatMode) -> None:
|
async def async_set_repeat(self, repeat: RepeatMode) -> None:
|
||||||
"""Set repeat mode."""
|
"""Set repeat mode."""
|
||||||
if repeat not in REPEAT_MODE_MAPPING_TO_SPOTIFY:
|
if repeat not in REPEAT_MODE_MAPPING_TO_SPOTIFY:
|
||||||
|
|
|
@ -84,6 +84,13 @@ async def setup_credentials(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(autouse=True)
|
||||||
|
async def patch_sleep() -> Generator[AsyncMock]:
|
||||||
|
"""Fixture to setup credentials."""
|
||||||
|
with patch("homeassistant.components.spotify.media_player.AFTER_REQUEST_SLEEP", 0):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def mock_spotify() -> Generator[AsyncMock]:
|
def mock_spotify() -> Generator[AsyncMock]:
|
||||||
"""Mock the Spotify API."""
|
"""Mock the Spotify API."""
|
||||||
|
|
Loading…
Add table
Reference in a new issue