core/homeassistant/components/linkplay/select.py

113 lines
3.7 KiB
Python

"""Support for LinkPlay select."""
from __future__ import annotations
from collections.abc import Awaitable, Callable, Coroutine
from dataclasses import dataclass
import logging
from typing import Any
from linkplay.bridge import LinkPlayBridge, LinkPlayPlayer
from linkplay.consts import AudioOutputHwMode
from linkplay.manufacturers import MANUFACTURER_WIIM
from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import LinkPlayConfigEntry
from .entity import LinkPlayBaseEntity, exception_wrap
_LOGGER = logging.getLogger(__name__)
AUDIO_OUTPUT_HW_MODE_MAP: dict[AudioOutputHwMode, str] = {
AudioOutputHwMode.OPTICAL: "optical",
AudioOutputHwMode.LINE_OUT: "line_out",
AudioOutputHwMode.COAXIAL: "coaxial",
AudioOutputHwMode.HEADPHONES: "headphones",
}
AUDIO_OUTPUT_HW_MODE_MAP_INV: dict[str, AudioOutputHwMode] = {
v: k for k, v in AUDIO_OUTPUT_HW_MODE_MAP.items()
}
async def _get_current_option(bridge: LinkPlayBridge) -> str:
"""Get the current hardware mode."""
modes = await bridge.player.get_audio_output_hw_mode()
return AUDIO_OUTPUT_HW_MODE_MAP[modes.hardware]
@dataclass(frozen=True, kw_only=True)
class LinkPlaySelectEntityDescription(SelectEntityDescription):
"""Class describing LinkPlay select entities."""
set_option_fn: Callable[[LinkPlayPlayer, str], Coroutine[Any, Any, None]]
current_option_fn: Callable[[LinkPlayPlayer], Awaitable[str]]
SELECT_TYPES_WIIM: tuple[LinkPlaySelectEntityDescription, ...] = (
LinkPlaySelectEntityDescription(
key="audio_output_hardware_mode",
translation_key="audio_output_hardware_mode",
current_option_fn=_get_current_option,
set_option_fn=(
lambda linkplay_bridge,
option: linkplay_bridge.player.set_audio_output_hw_mode(
AUDIO_OUTPUT_HW_MODE_MAP_INV[option]
)
),
options=list(AUDIO_OUTPUT_HW_MODE_MAP_INV),
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: LinkPlayConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the LinkPlay select from config entry."""
# add entities
if config_entry.runtime_data.bridge.device.manufacturer == MANUFACTURER_WIIM:
async_add_entities(
LinkPlaySelect(config_entry.runtime_data.bridge, description)
for description in SELECT_TYPES_WIIM
)
class LinkPlaySelect(LinkPlayBaseEntity, SelectEntity):
"""Representation of LinkPlay select."""
entity_description: LinkPlaySelectEntityDescription
def __init__(
self,
bridge: LinkPlayPlayer,
description: LinkPlaySelectEntityDescription,
) -> None:
"""Initialize LinkPlay select."""
super().__init__(bridge)
self.entity_description = description
self._attr_unique_id = f"{bridge.device.uuid}-{description.key}"
async def async_update(self) -> None:
"""Get the current value from the device."""
try:
# modes = await self.entity_description.current_option_fn(self._bridge)
self._attr_current_option = await self.entity_description.current_option_fn(
self._bridge
)
except ValueError as ex:
_LOGGER.debug(
"Cannot retrieve hardware mode value from device with error:, %s", ex
)
self._attr_current_option = None
@exception_wrap
async def async_select_option(self, option: str) -> None:
"""Set the option."""
await self.entity_description.set_option_fn(self._bridge, option)