Add seek, shuffle, and repeat controls to Cambridge Audio (#125758)
* Add advanced transport controls to Cambridge Audio * Use TransportControl model for play/pausepull/124650/head^2
parent
cee14afc03
commit
2db488b7a4
|
@ -4,13 +4,20 @@ from __future__ import annotations
|
|||
|
||||
from datetime import datetime
|
||||
|
||||
from aiostreammagic import StreamMagicClient
|
||||
from aiostreammagic import (
|
||||
RepeatMode as CambridgeRepeatMode,
|
||||
ShuffleMode,
|
||||
StreamMagicClient,
|
||||
TransportControl,
|
||||
)
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
MediaPlayerDeviceClass,
|
||||
MediaPlayerEntity,
|
||||
MediaPlayerEntityFeature,
|
||||
MediaPlayerState,
|
||||
MediaType,
|
||||
RepeatMode,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -30,6 +37,16 @@ PREAMP_FEATURES = (
|
|||
| 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(
|
||||
hass: HomeAssistant,
|
||||
|
@ -46,6 +63,7 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
|
||||
_attr_name = None
|
||||
_attr_media_content_type = MediaType.MUSIC
|
||||
_attr_device_class = MediaPlayerDeviceClass.RECEIVER
|
||||
|
||||
def __init__(self, client: StreamMagicClient) -> None:
|
||||
"""Initialize an Cambridge Audio entity."""
|
||||
|
@ -71,16 +89,12 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
features = BASE_FEATURES
|
||||
if self.client.state.pre_amp_mode:
|
||||
features |= PREAMP_FEATURES
|
||||
if "play_pause" in controls:
|
||||
if TransportControl.PLAY_PAUSE in controls:
|
||||
features |= MediaPlayerEntityFeature.PLAY | MediaPlayerEntityFeature.PAUSE
|
||||
if "play" in controls:
|
||||
features |= MediaPlayerEntityFeature.PLAY
|
||||
if "pause" in controls:
|
||||
features |= MediaPlayerEntityFeature.PAUSE
|
||||
if "track_next" in controls:
|
||||
features |= MediaPlayerEntityFeature.NEXT_TRACK
|
||||
if "track_previous" in controls:
|
||||
features |= MediaPlayerEntityFeature.PREVIOUS_TRACK
|
||||
for control in controls:
|
||||
feature = TRANSPORT_FEATURES.get(control)
|
||||
if feature:
|
||||
features |= feature
|
||||
return features
|
||||
|
||||
@property
|
||||
|
@ -164,6 +178,22 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
volume = self.client.state.volume_percent or 0
|
||||
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:
|
||||
"""Toggle play/pause the current media."""
|
||||
await self.client.play_pause()
|
||||
|
@ -171,7 +201,10 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
async def async_media_pause(self) -> None:
|
||||
"""Pause the current media."""
|
||||
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()
|
||||
else:
|
||||
await self.client.pause()
|
||||
|
@ -182,8 +215,14 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
|
||||
async def async_media_play(self) -> None:
|
||||
"""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()
|
||||
else:
|
||||
await self.client.play()
|
||||
|
||||
async def async_media_next_track(self) -> None:
|
||||
"""Skip to the next track."""
|
||||
|
@ -222,7 +261,22 @@ class CambridgeAudioDevice(CambridgeAudioEntity, MediaPlayerEntity):
|
|||
|
||||
async def async_mute_volume(self, mute: bool) -> None:
|
||||
"""Set the mute state."""
|
||||
if mute:
|
||||
await self.client.mute()
|
||||
else:
|
||||
await self.client.unmute()
|
||||
await self.client.set_mute(mute)
|
||||
|
||||
async def async_media_seek(self, position: float) -> None:
|
||||
"""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…
Reference in New Issue