mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Define media_player entity attributes as class variables (#51192)
This commit is contained in:
parent
39e62f9c90
commit
17b2678aee
@ -31,7 +31,7 @@ from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
|
||||
from .const import ATTR_MANUFACTURER, DEFAULT_NAME, DOMAIN
|
||||
|
||||
@ -100,7 +100,7 @@ class DuneHDPlayerEntity(MediaPlayerEntity):
|
||||
return True
|
||||
|
||||
@property
|
||||
def state(self) -> StateType:
|
||||
def state(self) -> str | None:
|
||||
"""Return player state."""
|
||||
state = STATE_OFF
|
||||
if "playback_position" in self._state:
|
||||
|
@ -1,7 +1,6 @@
|
||||
"""Denon HEOS Media Player."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Sequence
|
||||
from functools import reduce, wraps
|
||||
import logging
|
||||
from operator import ior
|
||||
@ -362,7 +361,7 @@ class HeosMediaPlayer(MediaPlayerEntity):
|
||||
return self._source_manager.get_current_source(self._player.now_playing_media)
|
||||
|
||||
@property
|
||||
def source_list(self) -> Sequence[str]:
|
||||
def source_list(self) -> list[str]:
|
||||
"""List of available input sources."""
|
||||
return self._source_manager.source_list
|
||||
|
||||
|
@ -5,7 +5,7 @@ import asyncio
|
||||
import base64
|
||||
import collections
|
||||
from contextlib import suppress
|
||||
from datetime import timedelta
|
||||
import datetime as dt
|
||||
import functools as ft
|
||||
import hashlib
|
||||
import logging
|
||||
@ -57,6 +57,7 @@ import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import ( # noqa: F401
|
||||
PLATFORM_SCHEMA,
|
||||
PLATFORM_SCHEMA_BASE,
|
||||
datetime,
|
||||
)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
@ -137,7 +138,7 @@ CACHE_URL = "url"
|
||||
CACHE_CONTENT = "content"
|
||||
ENTITY_IMAGE_CACHE = {CACHE_IMAGES: collections.OrderedDict(), CACHE_MAXSIZE: 16}
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=10)
|
||||
SCAN_INTERVAL = dt.timedelta(seconds=10)
|
||||
|
||||
DEVICE_CLASS_TV = "tv"
|
||||
DEVICE_CLASS_SPEAKER = "speaker"
|
||||
@ -371,11 +372,43 @@ class MediaPlayerEntity(Entity):
|
||||
|
||||
_access_token: str | None = None
|
||||
|
||||
_attr_app_id: str | None = None
|
||||
_attr_app_name: str | None = None
|
||||
_attr_group_members: list[str] | None = None
|
||||
_attr_is_volume_muted: bool | None = None
|
||||
_attr_media_album_artist: str | None = None
|
||||
_attr_media_album_name: str | None = None
|
||||
_attr_media_artist: str | None = None
|
||||
_attr_media_channel: str | None = None
|
||||
_attr_media_content_id: str | None = None
|
||||
_attr_media_content_type: str | None = None
|
||||
_attr_media_duration: int | None = None
|
||||
_attr_media_episode: str | None = None
|
||||
_attr_media_image_hash: str | None
|
||||
_attr_media_image_remotely_accessible: bool = False
|
||||
_attr_media_image_url: str | None = None
|
||||
_attr_media_playlist: str | None = None
|
||||
_attr_media_position_updated_at: dt.datetime | None = None
|
||||
_attr_media_position: int | None = None
|
||||
_attr_media_season: str | None = None
|
||||
_attr_media_series_title: str | None = None
|
||||
_attr_media_title: str | None = None
|
||||
_attr_media_track: int | None = None
|
||||
_attr_repeat: str | None = None
|
||||
_attr_shuffle: bool | None = None
|
||||
_attr_sound_mode_list: list[str] | None = None
|
||||
_attr_sound_mode: str | None = None
|
||||
_attr_source_list: list[str] | None = None
|
||||
_attr_source: str | None = None
|
||||
_attr_state: str | None = None
|
||||
_attr_supported_features: int = 0
|
||||
_attr_volume_level: float | None = None
|
||||
|
||||
# Implement these for your media player
|
||||
@property
|
||||
def state(self):
|
||||
def state(self) -> str | None:
|
||||
"""State of the player."""
|
||||
return None
|
||||
return self._attr_state
|
||||
|
||||
@property
|
||||
def access_token(self) -> str:
|
||||
@ -385,56 +418,59 @@ class MediaPlayerEntity(Entity):
|
||||
return self._access_token
|
||||
|
||||
@property
|
||||
def volume_level(self):
|
||||
def volume_level(self) -> float | None:
|
||||
"""Volume level of the media player (0..1)."""
|
||||
return None
|
||||
return self._attr_volume_level
|
||||
|
||||
@property
|
||||
def is_volume_muted(self):
|
||||
def is_volume_muted(self) -> bool | None:
|
||||
"""Boolean if volume is currently muted."""
|
||||
return None
|
||||
return self._attr_is_volume_muted
|
||||
|
||||
@property
|
||||
def media_content_id(self):
|
||||
def media_content_id(self) -> str | None:
|
||||
"""Content ID of current playing media."""
|
||||
return None
|
||||
return self._attr_media_content_id
|
||||
|
||||
@property
|
||||
def media_content_type(self):
|
||||
def media_content_type(self) -> str | None:
|
||||
"""Content type of current playing media."""
|
||||
return None
|
||||
return self._attr_media_content_type
|
||||
|
||||
@property
|
||||
def media_duration(self):
|
||||
def media_duration(self) -> int | None:
|
||||
"""Duration of current playing media in seconds."""
|
||||
return None
|
||||
return self._attr_media_duration
|
||||
|
||||
@property
|
||||
def media_position(self):
|
||||
def media_position(self) -> int | None:
|
||||
"""Position of current playing media in seconds."""
|
||||
return None
|
||||
return self._attr_media_position
|
||||
|
||||
@property
|
||||
def media_position_updated_at(self):
|
||||
def media_position_updated_at(self) -> dt.datetime | None:
|
||||
"""When was the position of the current playing media valid.
|
||||
|
||||
Returns value from homeassistant.util.dt.utcnow().
|
||||
"""
|
||||
return None
|
||||
return self._attr_media_position_updated_at
|
||||
|
||||
@property
|
||||
def media_image_url(self):
|
||||
def media_image_url(self) -> str | None:
|
||||
"""Image url of current playing media."""
|
||||
return None
|
||||
return self._attr_media_image_url
|
||||
|
||||
@property
|
||||
def media_image_remotely_accessible(self) -> bool:
|
||||
"""If the image url is remotely accessible."""
|
||||
return False
|
||||
return self._attr_media_image_remotely_accessible
|
||||
|
||||
@property
|
||||
def media_image_hash(self):
|
||||
def media_image_hash(self) -> str | None:
|
||||
"""Hash value for media image."""
|
||||
if hasattr(self, "_attr_media_image_hash"):
|
||||
return self._attr_media_image_hash
|
||||
|
||||
url = self.media_image_url
|
||||
if url is not None:
|
||||
return hashlib.sha256(url.encode("utf-8")).hexdigest()[:16]
|
||||
@ -463,104 +499,104 @@ class MediaPlayerEntity(Entity):
|
||||
return None, None
|
||||
|
||||
@property
|
||||
def media_title(self):
|
||||
def media_title(self) -> str | None:
|
||||
"""Title of current playing media."""
|
||||
return None
|
||||
return self._attr_media_title
|
||||
|
||||
@property
|
||||
def media_artist(self):
|
||||
def media_artist(self) -> str | None:
|
||||
"""Artist of current playing media, music track only."""
|
||||
return None
|
||||
return self._attr_media_artist
|
||||
|
||||
@property
|
||||
def media_album_name(self):
|
||||
def media_album_name(self) -> str | None:
|
||||
"""Album name of current playing media, music track only."""
|
||||
return None
|
||||
return self._attr_media_album_name
|
||||
|
||||
@property
|
||||
def media_album_artist(self):
|
||||
def media_album_artist(self) -> str | None:
|
||||
"""Album artist of current playing media, music track only."""
|
||||
return None
|
||||
return self._attr_media_album_artist
|
||||
|
||||
@property
|
||||
def media_track(self):
|
||||
def media_track(self) -> int | None:
|
||||
"""Track number of current playing media, music track only."""
|
||||
return None
|
||||
return self._attr_media_track
|
||||
|
||||
@property
|
||||
def media_series_title(self):
|
||||
def media_series_title(self) -> str | None:
|
||||
"""Title of series of current playing media, TV show only."""
|
||||
return None
|
||||
return self._attr_media_series_title
|
||||
|
||||
@property
|
||||
def media_season(self):
|
||||
def media_season(self) -> str | None:
|
||||
"""Season of current playing media, TV show only."""
|
||||
return None
|
||||
return self._attr_media_season
|
||||
|
||||
@property
|
||||
def media_episode(self):
|
||||
def media_episode(self) -> str | None:
|
||||
"""Episode of current playing media, TV show only."""
|
||||
return None
|
||||
return self._attr_media_episode
|
||||
|
||||
@property
|
||||
def media_channel(self):
|
||||
def media_channel(self) -> str | None:
|
||||
"""Channel currently playing."""
|
||||
return None
|
||||
return self._attr_media_channel
|
||||
|
||||
@property
|
||||
def media_playlist(self):
|
||||
def media_playlist(self) -> str | None:
|
||||
"""Title of Playlist currently playing."""
|
||||
return None
|
||||
return self._attr_media_playlist
|
||||
|
||||
@property
|
||||
def app_id(self):
|
||||
def app_id(self) -> str | None:
|
||||
"""ID of the current running app."""
|
||||
return None
|
||||
return self._attr_app_id
|
||||
|
||||
@property
|
||||
def app_name(self):
|
||||
def app_name(self) -> str | None:
|
||||
"""Name of the current running app."""
|
||||
return None
|
||||
return self._attr_app_name
|
||||
|
||||
@property
|
||||
def source(self):
|
||||
def source(self) -> str | None:
|
||||
"""Name of the current input source."""
|
||||
return None
|
||||
return self._attr_source
|
||||
|
||||
@property
|
||||
def source_list(self):
|
||||
def source_list(self) -> list[str] | None:
|
||||
"""List of available input sources."""
|
||||
return None
|
||||
return self._attr_source_list
|
||||
|
||||
@property
|
||||
def sound_mode(self):
|
||||
def sound_mode(self) -> str | None:
|
||||
"""Name of the current sound mode."""
|
||||
return None
|
||||
return self._attr_sound_mode
|
||||
|
||||
@property
|
||||
def sound_mode_list(self):
|
||||
def sound_mode_list(self) -> list[str] | None:
|
||||
"""List of available sound modes."""
|
||||
return None
|
||||
return self._attr_sound_mode_list
|
||||
|
||||
@property
|
||||
def shuffle(self):
|
||||
def shuffle(self) -> bool | None:
|
||||
"""Boolean if shuffle is enabled."""
|
||||
return None
|
||||
return self._attr_shuffle
|
||||
|
||||
@property
|
||||
def repeat(self):
|
||||
def repeat(self) -> str | None:
|
||||
"""Return current repeat mode."""
|
||||
return None
|
||||
return self._attr_repeat
|
||||
|
||||
@property
|
||||
def group_members(self):
|
||||
def group_members(self) -> list[str] | None:
|
||||
"""List of members which are currently grouped together."""
|
||||
return None
|
||||
return self._attr_group_members
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
def supported_features(self) -> int:
|
||||
"""Flag media player features that are supported."""
|
||||
return 0
|
||||
return self._attr_supported_features
|
||||
|
||||
def turn_on(self):
|
||||
"""Turn the media player on."""
|
||||
|
@ -67,8 +67,6 @@ from .const import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ICON = "mdi:spotify"
|
||||
|
||||
SCAN_INTERVAL = timedelta(seconds=30)
|
||||
|
||||
SUPPORT_SPOTIFY = (
|
||||
@ -211,12 +209,12 @@ def spotify_exception_handler(func):
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
result = func(self, *args, **kwargs)
|
||||
self.player_available = True
|
||||
self._attr_available = True
|
||||
return result
|
||||
except requests.RequestException:
|
||||
self.player_available = False
|
||||
self._attr_available = False
|
||||
except SpotifyException as exc:
|
||||
self.player_available = False
|
||||
self._attr_available = False
|
||||
if exc.reason == "NO_ACTIVE_DEVICE":
|
||||
raise HomeAssistantError("No active playback device found") from None
|
||||
|
||||
@ -226,6 +224,10 @@ def spotify_exception_handler(func):
|
||||
class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
"""Representation of a Spotify controller."""
|
||||
|
||||
_attr_icon = "mdi:spotify"
|
||||
_attr_media_content_type = MEDIA_TYPE_MUSIC
|
||||
_attr_media_image_remotely_accessible = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session: OAuth2Session,
|
||||
@ -247,40 +249,22 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
self._currently_playing: dict | None = {}
|
||||
self._devices: list[dict] | None = []
|
||||
self._playlist: dict | None = None
|
||||
self._spotify: Spotify = None
|
||||
|
||||
self.player_available = False
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def icon(self) -> str:
|
||||
"""Return the icon."""
|
||||
return ICON
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return self.player_available
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return the unique ID."""
|
||||
return self._id
|
||||
self._attr_name = self._name
|
||||
self._attr_unique_id = user_id
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information about this entity."""
|
||||
model = "Spotify Free"
|
||||
if self._me is not None:
|
||||
model = self._me["product"]
|
||||
product = self._me["product"]
|
||||
model = f"Spotify {product}"
|
||||
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self._id)},
|
||||
"manufacturer": "Spotify AB",
|
||||
"model": f"Spotify {model}".rstrip(),
|
||||
"model": model,
|
||||
"name": self._name,
|
||||
}
|
||||
|
||||
@ -304,11 +288,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
item = self._currently_playing.get("item") or {}
|
||||
return item.get("uri")
|
||||
|
||||
@property
|
||||
def media_content_type(self) -> str | None:
|
||||
"""Return the media type."""
|
||||
return MEDIA_TYPE_MUSIC
|
||||
|
||||
@property
|
||||
def media_duration(self) -> int | None:
|
||||
"""Duration of current playing media in seconds."""
|
||||
@ -340,11 +319,6 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
return None
|
||||
return fetch_image_url(self._currently_playing["item"]["album"])
|
||||
|
||||
@property
|
||||
def media_image_remotely_accessible(self) -> bool:
|
||||
"""If the image url is remotely accessible."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def media_title(self) -> str | None:
|
||||
"""Return the media title."""
|
||||
@ -357,7 +331,7 @@ class SpotifyMediaPlayer(MediaPlayerEntity):
|
||||
if self._currently_playing.get("item") is None:
|
||||
return None
|
||||
return ", ".join(
|
||||
[artist["name"] for artist in self._currently_playing["item"]["artists"]]
|
||||
artist["name"] for artist in self._currently_playing["item"]["artists"]
|
||||
)
|
||||
|
||||
@property
|
||||
|
Loading…
x
Reference in New Issue
Block a user