mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Add seek, shuffle, and repeat controls to Cambridge Audio (#125758)
* Add advanced transport controls to Cambridge Audio * Use TransportControl model for play/pause
This commit is contained in:
parent
cee14afc03
commit
2db488b7a4
@ -4,13 +4,20 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from aiostreammagic import StreamMagicClient
|
from aiostreammagic import (
|
||||||
|
RepeatMode as CambridgeRepeatMode,
|
||||||
|
ShuffleMode,
|
||||||
|
StreamMagicClient,
|
||||||
|
TransportControl,
|
||||||
|
)
|
||||||
|
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
|
MediaPlayerDeviceClass,
|
||||||
MediaPlayerEntity,
|
MediaPlayerEntity,
|
||||||
MediaPlayerEntityFeature,
|
MediaPlayerEntityFeature,
|
||||||
MediaPlayerState,
|
MediaPlayerState,
|
||||||
MediaType,
|
MediaType,
|
||||||
|
RepeatMode,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -30,6 +37,16 @@ PREAMP_FEATURES = (
|
|||||||
| MediaPlayerEntityFeature.VOLUME_STEP
|
| MediaPlayerEntityFeature.VOLUME_STEP
|
||||||
)
|
)
|
||||||
|
|
||||||
|
TRANSPORT_FEATURES: dict[TransportControl, MediaPlayerEntityFeature] = {
|
||||||
|
TransportControl.PLAY: MediaPlayerEntityFeature.PLAY,
|
||||||
|
TransportControl.PAUSE: MediaPlayerEntityFeature.PAUSE,
|
||||||
|
TransportControl.TRACK_NEXT: MediaPlayerEntityFeature.NEXT_TRACK,
|
||||||
|
TransportControl.TRACK_PREVIOUS: MediaPlayerEntityFeature.PREVIOUS_TRACK,
|
||||||
|
TransportControl.TOGGLE_REPEAT: MediaPlayerEntityFeature.REPEAT_SET,
|
||||||
|
TransportControl.TOGGLE_SHUFFLE: MediaPlayerEntityFeature.SHUFFLE_SET,
|
||||||
|
TransportControl.SEEK: MediaPlayerEntityFeature.SEEK,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -46,6 +63,7 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
|
|
||||||
_attr_name = None
|
_attr_name = None
|
||||||
_attr_media_content_type = MediaType.MUSIC
|
_attr_media_content_type = MediaType.MUSIC
|
||||||
|
_attr_device_class = MediaPlayerDeviceClass.RECEIVER
|
||||||
|
|
||||||
def __init__(self, client: StreamMagicClient) -> None:
|
def __init__(self, client: StreamMagicClient) -> None:
|
||||||
"""Initialize an Cambridge Audio entity."""
|
"""Initialize an Cambridge Audio entity."""
|
||||||
@ -71,16 +89,12 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
features = BASE_FEATURES
|
features = BASE_FEATURES
|
||||||
if self.client.state.pre_amp_mode:
|
if self.client.state.pre_amp_mode:
|
||||||
features |= PREAMP_FEATURES
|
features |= PREAMP_FEATURES
|
||||||
if "play_pause" in controls:
|
if TransportControl.PLAY_PAUSE in controls:
|
||||||
features |= MediaPlayerEntityFeature.PLAY | MediaPlayerEntityFeature.PAUSE
|
features |= MediaPlayerEntityFeature.PLAY | MediaPlayerEntityFeature.PAUSE
|
||||||
if "play" in controls:
|
for control in controls:
|
||||||
features |= MediaPlayerEntityFeature.PLAY
|
feature = TRANSPORT_FEATURES.get(control)
|
||||||
if "pause" in controls:
|
if feature:
|
||||||
features |= MediaPlayerEntityFeature.PAUSE
|
features |= feature
|
||||||
if "track_next" in controls:
|
|
||||||
features |= MediaPlayerEntityFeature.NEXT_TRACK
|
|
||||||
if "track_previous" in controls:
|
|
||||||
features |= MediaPlayerEntityFeature.PREVIOUS_TRACK
|
|
||||||
return features
|
return features
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -164,6 +178,22 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
volume = self.client.state.volume_percent or 0
|
volume = self.client.state.volume_percent or 0
|
||||||
return volume / 100
|
return volume / 100
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shuffle(self) -> bool | None:
|
||||||
|
"""Current shuffle configuration."""
|
||||||
|
mode_shuffle = self.client.play_state.mode_shuffle
|
||||||
|
if not mode_shuffle:
|
||||||
|
return False
|
||||||
|
return mode_shuffle != ShuffleMode.OFF
|
||||||
|
|
||||||
|
@property
|
||||||
|
def repeat(self) -> RepeatMode | None:
|
||||||
|
"""Current repeat configuration."""
|
||||||
|
mode_repeat = RepeatMode.OFF
|
||||||
|
if self.client.play_state.mode_repeat == CambridgeRepeatMode.ALL:
|
||||||
|
mode_repeat = RepeatMode.ALL
|
||||||
|
return mode_repeat
|
||||||
|
|
||||||
async def async_media_play_pause(self) -> None:
|
async def async_media_play_pause(self) -> None:
|
||||||
"""Toggle play/pause the current media."""
|
"""Toggle play/pause the current media."""
|
||||||
await self.client.play_pause()
|
await self.client.play_pause()
|
||||||
@ -171,7 +201,10 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
async def async_media_pause(self) -> None:
|
async def async_media_pause(self) -> None:
|
||||||
"""Pause the current media."""
|
"""Pause the current media."""
|
||||||
controls = self.client.now_playing.controls
|
controls = self.client.now_playing.controls
|
||||||
if "pause" not in controls and "play_pause" in controls:
|
if (
|
||||||
|
TransportControl.PAUSE not in controls
|
||||||
|
and TransportControl.PLAY_PAUSE in controls
|
||||||
|
):
|
||||||
await self.client.play_pause()
|
await self.client.play_pause()
|
||||||
else:
|
else:
|
||||||
await self.client.pause()
|
await self.client.pause()
|
||||||
@ -182,8 +215,14 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
|
|
||||||
async def async_media_play(self) -> None:
|
async def async_media_play(self) -> None:
|
||||||
"""Play the current media."""
|
"""Play the current media."""
|
||||||
if self.state == MediaPlayerState.PAUSED:
|
controls = self.client.now_playing.controls
|
||||||
|
if (
|
||||||
|
TransportControl.PLAY not in controls
|
||||||
|
and TransportControl.PLAY_PAUSE in controls
|
||||||
|
):
|
||||||
await self.client.play_pause()
|
await self.client.play_pause()
|
||||||
|
else:
|
||||||
|
await self.client.play()
|
||||||
|
|
||||||
async def async_media_next_track(self) -> None:
|
async def async_media_next_track(self) -> None:
|
||||||
"""Skip to the next track."""
|
"""Skip to the next track."""
|
||||||
@ -222,7 +261,22 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||||||
|
|
||||||
async def async_mute_volume(self, mute: bool) -> None:
|
async def async_mute_volume(self, mute: bool) -> None:
|
||||||
"""Set the mute state."""
|
"""Set the mute state."""
|
||||||
if mute:
|
await self.client.set_mute(mute)
|
||||||
await self.client.mute()
|
|
||||||
else:
|
async def async_media_seek(self, position: float) -> None:
|
||||||
await self.client.unmute()
|
"""Seek to a position in the current media."""
|
||||||
|
await self.client.media_seek(int(position))
|
||||||
|
|
||||||
|
async def async_set_shuffle(self, shuffle: bool) -> None:
|
||||||
|
"""Set the shuffle mode for the current queue."""
|
||||||
|
shuffle_mode = ShuffleMode.OFF
|
||||||
|
if shuffle:
|
||||||
|
shuffle_mode = ShuffleMode.ALL
|
||||||
|
await self.client.set_shuffle(shuffle_mode)
|
||||||
|
|
||||||
|
async def async_set_repeat(self, repeat: RepeatMode) -> None:
|
||||||
|
"""Set the repeat mode for the current queue."""
|
||||||
|
repeat_mode = CambridgeRepeatMode.OFF
|
||||||
|
if repeat:
|
||||||
|
repeat_mode = CambridgeRepeatMode.ALL
|
||||||
|
await self.client.set_repeat(repeat_mode)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user