Home Assistant Unofficial Reference 2024.12.1
media_player.py
Go to the documentation of this file.
1 """Play media via gstreamer."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from gsp import STATE_IDLE, STATE_PAUSED, STATE_PLAYING, GstreamerPlayer
9 import voluptuous as vol
10 
11 from homeassistant.components import media_source
13  PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
14  BrowseMedia,
15  MediaPlayerEntity,
16  MediaPlayerEntityFeature,
17  MediaPlayerState,
18  MediaType,
19  async_process_play_media_url,
20 )
21 from homeassistant.const import CONF_NAME, EVENT_HOMEASSISTANT_STOP
22 from homeassistant.core import HomeAssistant
24 from homeassistant.helpers.entity_platform import AddEntitiesCallback
25 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
26 
27 _LOGGER = logging.getLogger(__name__)
28 
29 CONF_PIPELINE = "pipeline"
30 
31 DOMAIN = "gstreamer"
32 
33 PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
34  {vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_PIPELINE): cv.string}
35 )
36 
37 GSP_STATE_MAPPING = {
38  STATE_IDLE: MediaPlayerState.IDLE,
39  STATE_PAUSED: MediaPlayerState.PAUSED,
40  STATE_PLAYING: MediaPlayerState.PLAYING,
41 }
42 
43 
45  hass: HomeAssistant,
46  config: ConfigType,
47  add_entities: AddEntitiesCallback,
48  discovery_info: DiscoveryInfoType | None = None,
49 ) -> None:
50  """Set up the Gstreamer platform."""
51 
52  name = config.get(CONF_NAME)
53  pipeline = config.get(CONF_PIPELINE)
54  player = GstreamerPlayer(pipeline)
55 
56  def _shutdown(call):
57  """Quit the player on shutdown."""
58  player.quit()
59 
60  hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, _shutdown)
61  add_entities([GstreamerDevice(player, name)])
62 
63 
65  """Representation of a Gstreamer device."""
66 
67  _attr_media_content_type = MediaType.MUSIC
68  _attr_supported_features = (
69  MediaPlayerEntityFeature.VOLUME_SET
70  | MediaPlayerEntityFeature.PLAY
71  | MediaPlayerEntityFeature.PAUSE
72  | MediaPlayerEntityFeature.PLAY_MEDIA
73  | MediaPlayerEntityFeature.NEXT_TRACK
74  | MediaPlayerEntityFeature.BROWSE_MEDIA
75  )
76 
77  def __init__(self, player: GstreamerPlayer, name: str | None) -> None:
78  """Initialize the Gstreamer device."""
79  self._player_player = player
80  self._name_name = name or DOMAIN
81  self._attr_state_attr_state = MediaPlayerState.IDLE
82  self._volume_volume = None
83  self._duration_duration = None
84  self._uri_uri = None
85  self._title_title = None
86  self._artist_artist = None
87  self._album_album = None
88 
89  def update(self) -> None:
90  """Update properties."""
91  self._attr_state_attr_state = GSP_STATE_MAPPING.get(self._player_player.state)
92  self._volume_volume = self._player_player.volume
93  self._duration_duration = self._player_player.duration
94  self._uri_uri = self._player_player.uri
95  self._title_title = self._player_player.title
96  self._album_album = self._player_player.album
97  self._artist_artist = self._player_player.artist
98 
99  def set_volume_level(self, volume: float) -> None:
100  """Set the volume level."""
101  self._player_player.volume = volume
102 
103  async def async_play_media(
104  self, media_type: MediaType | str, media_id: str, **kwargs: Any
105  ) -> None:
106  """Play media."""
107  # Handle media_source
108  if media_source.is_media_source_id(media_id):
109  sourced_media = await media_source.async_resolve_media(
110  self.hasshass, media_id, self.entity_identity_id
111  )
112  media_id = sourced_media.url
113 
114  elif media_type != MediaType.MUSIC:
115  _LOGGER.error("Invalid media type")
116  return
117 
118  media_id = async_process_play_media_url(self.hasshass, media_id)
119 
120  await self.hasshass.async_add_executor_job(self._player_player.queue, media_id)
121 
122  def media_play(self) -> None:
123  """Play."""
124  self._player_player.play()
125 
126  def media_pause(self) -> None:
127  """Pause."""
128  self._player_player.pause()
129 
130  def media_next_track(self) -> None:
131  """Next track."""
132  self._player_player.next()
133 
134  @property
135  def media_content_id(self):
136  """Content ID of currently playing media."""
137  return self._uri_uri
138 
139  @property
140  def name(self):
141  """Return the name of the device."""
142  return self._name_name
143 
144  @property
145  def volume_level(self):
146  """Return the volume level."""
147  return self._volume_volume
148 
149  @property
150  def media_duration(self):
151  """Duration of current playing media in seconds."""
152  return self._duration_duration
153 
154  @property
155  def media_title(self):
156  """Media title."""
157  return self._title_title
158 
159  @property
160  def media_artist(self):
161  """Media artist."""
162  return self._artist_artist
163 
164  @property
165  def media_album_name(self):
166  """Media album."""
167  return self._album_album
168 
170  self,
171  media_content_type: MediaType | str | None = None,
172  media_content_id: str | None = None,
173  ) -> BrowseMedia:
174  """Implement the websocket media browsing helper."""
175  return await media_source.async_browse_media(
176  self.hasshass,
177  media_content_id,
178  content_filter=lambda item: item.media_content_type.startswith("audio/"),
179  )
BrowseMedia async_browse_media(self, MediaType|str|None media_content_type=None, str|None media_content_id=None)
None __init__(self, GstreamerPlayer player, str|None name)
Definition: media_player.py:77
None async_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:49
str async_process_play_media_url(HomeAssistant hass, str media_content_id, *bool allow_relative_url=False, bool for_supervisor_network=False)
Definition: browse_media.py:36