Home Assistant Unofficial Reference 2024.12.1
media_player.py
Go to the documentation of this file.
1 """Support for HDMI CEC devices as media players."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from pycec.commands import CecCommand, KeyPressCommand, KeyReleaseCommand
9 from pycec.const import (
10  KEY_BACKWARD,
11  KEY_FORWARD,
12  KEY_MUTE_TOGGLE,
13  KEY_PAUSE,
14  KEY_PLAY,
15  KEY_STOP,
16  KEY_VOLUME_DOWN,
17  KEY_VOLUME_UP,
18  POWER_OFF,
19  POWER_ON,
20  STATUS_PLAY,
21  STATUS_STILL,
22  STATUS_STOP,
23  TYPE_AUDIO,
24  TYPE_PLAYBACK,
25  TYPE_RECORDER,
26  TYPE_TUNER,
27 )
28 
30  DOMAIN as MP_DOMAIN,
31  MediaPlayerEntity,
32  MediaPlayerEntityFeature,
33  MediaPlayerState,
34  MediaType,
35 )
36 from homeassistant.core import HomeAssistant
37 from homeassistant.helpers.entity_platform import AddEntitiesCallback
38 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
39 
40 from .const import ATTR_NEW, DOMAIN
41 from .entity import CecEntity
42 
43 _LOGGER = logging.getLogger(__name__)
44 
45 ENTITY_ID_FORMAT = MP_DOMAIN + ".{}"
46 
47 
49  hass: HomeAssistant,
50  config: ConfigType,
51  add_entities: AddEntitiesCallback,
52  discovery_info: DiscoveryInfoType | None = None,
53 ) -> None:
54  """Find and return HDMI devices as +switches."""
55  if discovery_info and ATTR_NEW in discovery_info:
56  _LOGGER.debug("Setting up HDMI devices %s", discovery_info[ATTR_NEW])
57  entities = []
58  for device in discovery_info[ATTR_NEW]:
59  hdmi_device = hass.data[DOMAIN][device]
60  entities.append(CecPlayerEntity(hdmi_device, hdmi_device.logical_address))
61  add_entities(entities, True)
62 
63 
65  """Representation of a HDMI device as a Media player."""
66 
67  def __init__(self, device, logical) -> None:
68  """Initialize the HDMI device."""
69  CecEntity.__init__(self, device, logical)
70  self.entity_identity_identity_identity_id = f"{MP_DOMAIN}.hdmi_{hex(self._logical_address)[2:]}"
71 
72  def send_keypress(self, key):
73  """Send keypress to CEC adapter."""
74  _LOGGER.debug(
75  "Sending keypress %s to device %s", hex(key), hex(self._logical_address_logical_address)
76  )
77  self._device_device.send_command(KeyPressCommand(key, dst=self._logical_address_logical_address))
78  self._device_device.send_command(KeyReleaseCommand(dst=self._logical_address_logical_address))
79 
80  def send_playback(self, key):
81  """Send playback status to CEC adapter."""
82  self._device_device.async_send_command(CecCommand(key, dst=self._logical_address_logical_address))
83 
84  def mute_volume(self, mute: bool) -> None:
85  """Mute volume."""
86  self.send_keypresssend_keypress(KEY_MUTE_TOGGLE)
87 
88  def media_previous_track(self) -> None:
89  """Go to previous track."""
90  self.send_keypresssend_keypress(KEY_BACKWARD)
91 
92  def turn_on(self) -> None:
93  """Turn device on."""
94  self._device_device.turn_on()
95  self._attr_state_attr_state = MediaPlayerState.ON
96 
97  def clear_playlist(self) -> None:
98  """Clear players playlist."""
99  raise NotImplementedError
100 
101  def turn_off(self) -> None:
102  """Turn device off."""
103  self._device_device.turn_off()
104  self._attr_state_attr_state = MediaPlayerState.OFF
105 
106  def media_stop(self) -> None:
107  """Stop playback."""
108  self.send_keypresssend_keypress(KEY_STOP)
109  self._attr_state_attr_state = MediaPlayerState.IDLE
110 
112  self, media_type: MediaType | str, media_id: str, **kwargs: Any
113  ) -> None:
114  """Not supported."""
115  raise NotImplementedError
116 
117  def media_next_track(self) -> None:
118  """Skip to next track."""
119  self.send_keypresssend_keypress(KEY_FORWARD)
120 
121  def media_seek(self, position: float) -> None:
122  """Not supported."""
123  raise NotImplementedError
124 
125  def set_volume_level(self, volume: float) -> None:
126  """Set volume level, range 0..1."""
127  raise NotImplementedError
128 
129  def media_pause(self) -> None:
130  """Pause playback."""
131  self.send_keypresssend_keypress(KEY_PAUSE)
132  self._attr_state_attr_state = MediaPlayerState.PAUSED
133 
134  def select_source(self, source: str) -> None:
135  """Not supported."""
136  raise NotImplementedError
137 
138  def media_play(self) -> None:
139  """Start playback."""
140  self.send_keypresssend_keypress(KEY_PLAY)
141  self._attr_state_attr_state = MediaPlayerState.PLAYING
142 
143  def volume_up(self) -> None:
144  """Increase volume."""
145  _LOGGER.debug("%s: volume up", self._logical_address_logical_address)
146  self.send_keypresssend_keypress(KEY_VOLUME_UP)
147 
148  def volume_down(self) -> None:
149  """Decrease volume."""
150  _LOGGER.debug("%s: volume down", self._logical_address_logical_address)
151  self.send_keypresssend_keypress(KEY_VOLUME_DOWN)
152 
153  def update(self) -> None:
154  """Update device status."""
155  device = self._device_device
156  if device.power_status in [POWER_OFF, 3]:
157  self._attr_state_attr_state = MediaPlayerState.OFF
158  elif not self.support_pausesupport_pause:
159  if device.power_status in [POWER_ON, 4]:
160  self._attr_state_attr_state = MediaPlayerState.ON
161  elif device.status == STATUS_PLAY:
162  self._attr_state_attr_state = MediaPlayerState.PLAYING
163  elif device.status == STATUS_STOP:
164  self._attr_state_attr_state = MediaPlayerState.IDLE
165  elif device.status == STATUS_STILL:
166  self._attr_state_attr_state = MediaPlayerState.PAUSED
167  else:
168  _LOGGER.warning("Unknown state: %s", device.status)
169 
170  @property
171  def supported_features(self) -> MediaPlayerEntityFeature:
172  """Flag media player features that are supported."""
173  if self.type_idtype_idtype_id == TYPE_RECORDER or self.typetypetype == TYPE_PLAYBACK:
174  return (
175  MediaPlayerEntityFeature.TURN_ON
176  | MediaPlayerEntityFeature.TURN_OFF
177  | MediaPlayerEntityFeature.PLAY_MEDIA
178  | MediaPlayerEntityFeature.PAUSE
179  | MediaPlayerEntityFeature.STOP
180  | MediaPlayerEntityFeature.PREVIOUS_TRACK
181  | MediaPlayerEntityFeature.NEXT_TRACK
182  )
183  if self.typetypetype == TYPE_TUNER:
184  return (
185  MediaPlayerEntityFeature.TURN_ON
186  | MediaPlayerEntityFeature.TURN_OFF
187  | MediaPlayerEntityFeature.PLAY_MEDIA
188  | MediaPlayerEntityFeature.PAUSE
189  | MediaPlayerEntityFeature.STOP
190  )
191  if self.type_idtype_idtype_id == TYPE_AUDIO:
192  return (
193  MediaPlayerEntityFeature.TURN_ON
194  | MediaPlayerEntityFeature.TURN_OFF
195  | MediaPlayerEntityFeature.VOLUME_STEP
196  | MediaPlayerEntityFeature.VOLUME_MUTE
197  )
198  return MediaPlayerEntityFeature.TURN_ON | MediaPlayerEntityFeature.TURN_OFF
None play_media(self, MediaType|str media_type, str media_id, **Any kwargs)
None add_entities(AsusWrtRouter router, AddEntitiesCallback async_add_entities, set[str] tracked)
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: media_player.py:53
None async_send_command(HomeAssistant hass, Mapping[str, Any] data)
Definition: __init__.py:87