1
mirror of https://github.com/home-assistant/core synced 2024-08-02 23:40:32 +02:00
ha-core/homeassistant/components/esphome/media_player.py

162 lines
5.0 KiB
Python

"""Support for ESPHome media players."""
from __future__ import annotations
from typing import Any
from aioesphomeapi import (
MediaPlayerCommand,
MediaPlayerEntityState,
MediaPlayerInfo,
MediaPlayerState,
)
from homeassistant.components import media_source
from homeassistant.components.media_player import (
MediaPlayerDeviceClass,
MediaPlayerEntity,
)
from homeassistant.components.media_player.browse_media import (
BrowseMedia,
async_process_play_media_url,
)
from homeassistant.components.media_player.const import MediaPlayerEntityFeature
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_IDLE, STATE_PAUSED, STATE_PLAYING
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import (
EsphomeEntity,
EsphomeEnumMapper,
esphome_state_property,
platform_async_setup_entry,
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up esphome media players based on a config entry."""
await platform_async_setup_entry(
hass,
entry,
async_add_entities,
component_key="media_player",
info_type=MediaPlayerInfo,
entity_type=EsphomeMediaPlayer,
state_type=MediaPlayerEntityState,
)
_STATES: EsphomeEnumMapper[MediaPlayerState, str] = EsphomeEnumMapper(
{
MediaPlayerState.IDLE: STATE_IDLE,
MediaPlayerState.PLAYING: STATE_PLAYING,
MediaPlayerState.PAUSED: STATE_PAUSED,
}
)
class EsphomeMediaPlayer(
EsphomeEntity[MediaPlayerInfo, MediaPlayerEntityState], MediaPlayerEntity
):
"""A media player implementation for esphome."""
_attr_device_class = MediaPlayerDeviceClass.SPEAKER
@property # type: ignore[misc]
@esphome_state_property
def state(self) -> str | None:
"""Return current state."""
return _STATES.from_esphome(self._state.state)
@property # type: ignore[misc]
@esphome_state_property
def is_volume_muted(self) -> bool:
"""Return true if volume is muted."""
return self._state.muted
@property # type: ignore[misc]
@esphome_state_property
def volume_level(self) -> float | None:
"""Volume level of the media player (0..1)."""
return self._state.volume
@property
def supported_features(self) -> int:
"""Flag supported features."""
flags = (
MediaPlayerEntityFeature.PLAY_MEDIA
| MediaPlayerEntityFeature.BROWSE_MEDIA
| MediaPlayerEntityFeature.STOP
| MediaPlayerEntityFeature.VOLUME_SET
| MediaPlayerEntityFeature.VOLUME_MUTE
)
if self._static_info.supports_pause:
flags |= MediaPlayerEntityFeature.PAUSE | MediaPlayerEntityFeature.PLAY
return flags
async def async_play_media(
self, media_type: str, media_id: str, **kwargs: Any
) -> None:
"""Send the play command with media url to the media player."""
if media_source.is_media_source_id(media_id):
sourced_media = await media_source.async_resolve_media(
self.hass, media_id, self.entity_id
)
media_id = sourced_media.url
media_id = async_process_play_media_url(self.hass, media_id)
await self._client.media_player_command(
self._static_info.key,
media_url=media_id,
)
async def async_browse_media(
self, media_content_type: str | None = None, media_content_id: str | None = None
) -> BrowseMedia:
"""Implement the websocket media browsing helper."""
return await media_source.async_browse_media(
self.hass,
media_content_id,
content_filter=lambda item: item.media_content_type.startswith("audio/"),
)
async def async_set_volume_level(self, volume: float) -> None:
"""Set volume level, range 0..1."""
await self._client.media_player_command(
self._static_info.key,
volume=volume,
)
async def async_media_pause(self) -> None:
"""Send pause command."""
await self._client.media_player_command(
self._static_info.key,
command=MediaPlayerCommand.PAUSE,
)
async def async_media_play(self) -> None:
"""Send play command."""
await self._client.media_player_command(
self._static_info.key,
command=MediaPlayerCommand.PLAY,
)
async def async_media_stop(self) -> None:
"""Send stop command."""
await self._client.media_player_command(
self._static_info.key,
command=MediaPlayerCommand.STOP,
)
async def async_mute_volume(self, mute: bool) -> None:
"""Mute the volume."""
await self._client.media_player_command(
self._static_info.key,
command=MediaPlayerCommand.MUTE if mute else MediaPlayerCommand.UNMUTE,
)