1 """Media player support for Android TV Remote."""
3 from __future__
import annotations
8 from androidtvremote2
import AndroidTVRemote, ConnectionClosed
13 MediaPlayerDeviceClass,
15 MediaPlayerEntityFeature,
23 from .
import AndroidTVRemoteConfigEntry
24 from .const
import CONF_APP_ICON, CONF_APP_NAME
25 from .entity
import AndroidTVRemoteBaseEntity
32 config_entry: AndroidTVRemoteConfigEntry,
33 async_add_entities: AddEntitiesCallback,
35 """Set up the Android TV media player entity based on a config entry."""
36 api = config_entry.runtime_data
41 """Android TV Remote Media Player Entity."""
43 _attr_assumed_state =
True
44 _attr_device_class = MediaPlayerDeviceClass.TV
45 _attr_supported_features = (
46 MediaPlayerEntityFeature.PAUSE
47 | MediaPlayerEntityFeature.VOLUME_STEP
48 | MediaPlayerEntityFeature.VOLUME_MUTE
49 | MediaPlayerEntityFeature.PREVIOUS_TRACK
50 | MediaPlayerEntityFeature.NEXT_TRACK
51 | MediaPlayerEntityFeature.TURN_ON
52 | MediaPlayerEntityFeature.TURN_OFF
53 | MediaPlayerEntityFeature.PLAY
54 | MediaPlayerEntityFeature.STOP
55 | MediaPlayerEntityFeature.PLAY_MEDIA
56 | MediaPlayerEntityFeature.BROWSE_MEDIA
60 self, api: AndroidTVRemote, config_entry: AndroidTVRemoteConfigEntry
62 """Initialize the entity."""
70 """Update current app info."""
73 self._apps[current_app].
get(CONF_APP_NAME, current_app)
74 if current_app
in self._apps
79 """Update volume info."""
80 if volume_info.get(
"max"):
91 """Update the state when the current app changes."""
97 """Update the state when the volume info changes."""
102 """Register callbacks."""
112 """Remove callbacks."""
119 def state(self) -> MediaPlayerState:
120 """Return the state of the device."""
122 return MediaPlayerState.ON
123 return MediaPlayerState.OFF
126 """Turn the Android TV on."""
131 """Turn the Android TV off."""
136 """Turn volume up for media player."""
140 """Turn volume down for media player."""
144 """Mute the volume."""
149 """Send play command."""
153 """Send pause command."""
157 """Send play/pause command."""
161 """Send stop command."""
165 """Send previous track command."""
169 """Send next track command."""
173 self, media_type: MediaType | str, media_id: str, **kwargs: Any
175 """Play a piece of media."""
176 if media_type == MediaType.CHANNEL:
177 if not media_id.isnumeric():
178 raise ValueError(f
"Channel must be numeric: {media_id}")
187 if media_type
in [MediaType.URL, MediaType.APP]:
191 raise ValueError(f
"Invalid media type: {media_type}")
195 media_content_type: MediaType | str |
None =
None,
196 media_content_id: str |
None =
None,
201 media_class=MediaClass.APP,
202 media_content_type=MediaType.APP,
203 media_content_id=app_id,
204 title=app.get(CONF_APP_NAME,
""),
205 thumbnail=app.get(CONF_APP_ICON,
""),
209 for app_id, app
in self._apps.items()
212 title=
"Applications",
213 media_class=MediaClass.DIRECTORY,
214 media_content_id=
"apps",
215 media_content_type=MediaType.APPS,
216 children_media_class=MediaClass.APP,
223 self, key_codes: list[str], delay_secs: float = 0.1
225 """Send a key press sequence to Android TV.
227 The delay is necessary because device may ignore
228 some commands if we send the sequence without delay.
231 for key_code
in key_codes:
232 self.
_api_api.send_key_command(key_code)
233 await asyncio.sleep(delay_secs)
234 except ConnectionClosed
as exc:
236 "Connection to Android TV device is closed"
None _send_key_command(self, str key_code, str direction="SHORT")
None _send_launch_app_command(self, str app_link)
None async_write_ha_state(self)
web.Response get(self, web.Request request, str config_key)