async def test_is_media_source_id(): """Test media source validation.""" assert media_source.is_media_source_id(const.URI_SCHEME) assert media_source.is_media_source_id(f"{const.URI_SCHEME}domain") assert media_source.is_media_source_id( f"{const.URI_SCHEME}domain/identifier") assert not media_source.is_media_source_id("test")
async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: """Play media from a URL or file.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media( self.hass, media_id) media_type = MEDIA_TYPE_MUSIC media_id = sourced_media.url # Sign and prefix with URL if playing a relative URL if media_id[0] == "/": media_id = async_sign_path( self.hass, quote(media_id), timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME), ) # prepend external URL hass_url = get_url(self.hass) media_id = f"{hass_url}{media_id}" if media_type != MEDIA_TYPE_MUSIC: LOGGER.error( "Invalid media type %s. Only %s is supported", media_type, MEDIA_TYPE_MUSIC, ) return await self._vlc.add(media_id) self._state = STATE_PLAYING
async def async_browse_media(self, media_content_type=None, media_content_id=None): """Implement the websocket media browsing helper.""" _LOGGER.debug( "Reached async_browse_media with content_type %s and content_id %s", media_content_type, media_content_id, ) if media_content_type in [None, "library"]: return await library_payload(self.hass, self._player) if media_source.is_media_source_id(media_content_id): return await media_source.async_browse_media( self.hass, media_content_id, content_filter=media_source_content_filter) payload = { "search_type": media_content_type, "search_id": media_content_id, } return await build_item_response(self, self._player, payload)
async def async_play_media( self, media_type: str, media_id: str, enqueue: MediaPlayerEnqueue | None = None, announce: bool | None = None, **kwargs: Any, ) -> None: """Send the play_media command to the media player.""" # Handle media_source 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) queue_opt = QUEUE_OPTION_MAP.get(enqueue, QueueOption.PLAY) if announce is None: announce = "/api/tts_proxy" in media_id if announce: announce_sound = "/api/tts_proxy" in media_id self.hass.create_task( self.player.active_queue.play_alert(media_id, announce_sound)) else: await self.player.active_queue.play_media(media_id, queue_opt)
async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: """Play a piece of media.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_MUSIC play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = async_process_play_media_url(self.hass, play_item.url) if media_type != MEDIA_TYPE_MUSIC: raise HomeAssistantError("Only music media type is supported") _LOGGER.debug("Playing Media %s for %s Speaker", media_id, self.device.name) await self.async_media_stop() try: await self.device.play_audio(media_id, blocking=False) except StreamError as err: raise HomeAssistantError(err) from err else: # update state after starting player self._async_updated_event() # wait until player finishes to update state again await self.device.wait_until_audio_completes() self._async_updated_event()
async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: """Send the play_media command to the media player.""" # If input (file) has a file format supported by pyatv, then stream it with # RAOP. Otherwise try to play it with regular AirPlay. if media_type == MEDIA_TYPE_APP: await self.atv.apps.launch_app(media_id) return if media_source.is_media_source_id(media_id): play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id) media_id = async_process_play_media_url(self.hass, play_item.url) media_type = MEDIA_TYPE_MUSIC if self._is_feature_available( FeatureName.StreamFile) and (media_type == MEDIA_TYPE_MUSIC or await is_streamable(media_id)): _LOGGER.debug("Streaming %s via RAOP", media_id) await self.atv.stream.stream_file(media_id) elif self._is_feature_available(FeatureName.PlayUrl): _LOGGER.debug("Playing %s via AirPlay", media_id) await self.atv.stream.play_url(media_id) else: _LOGGER.error( "Media streaming is not possible with current configuration")
async def async_play_media(self, media_type, media_id, **kwargs): """Send the media player the command for playing a playlist.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_MUSIC play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = play_item.url if media_type == MEDIA_TYPE_PLAYLIST: _LOGGER.debug("Playing playlist: %s", media_id) if media_id in self._playlists: self._currentplaylist = media_id else: self._currentplaylist = None _LOGGER.warning("Unknown playlist name %s", media_id) await self._client.clear() await self._client.load(media_id) await self._client.play() else: media_id = async_process_play_media_url(self.hass, media_id) await self._client.clear() self._currentplaylist = None await self._client.add(media_id) await self._client.play()
async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: """Play a piece of media.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_URL play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id) media_id = play_item.url if media_type in (MEDIA_TYPE_URL, MEDIA_TYPE_MUSIC): media_id = async_process_play_media_url(self.hass, media_id) await self._player.play_url(media_id) return if media_type == "quick_select": # media_id may be an int or a str selects = await self._player.get_quick_selects() try: index: int | None = int(media_id) except ValueError: # Try finding index by name index = next( (index for index, select in selects.items() if select == media_id), None, ) if index is None: raise ValueError(f"Invalid quick select '{media_id}'") await self._player.play_quick_select(index) return if media_type == MEDIA_TYPE_PLAYLIST: playlists = await self._player.heos.get_playlists() playlist = next((p for p in playlists if p.name == media_id), None) if not playlist: raise ValueError(f"Invalid playlist '{media_id}'") add_queue_option = HA_HEOS_ENQUEUE_MAP.get( kwargs.get(ATTR_MEDIA_ENQUEUE)) await self._player.add_to_queue(playlist, add_queue_option) return if media_type == "favorite": # media_id may be an int or str try: index = int(media_id) except ValueError: # Try finding index by name index = next( (index for index, favorite in self._source_manager. favorites.items() if favorite.name == media_id), None, ) if index is None: raise ValueError(f"Invalid favorite '{media_id}'") await self._player.play_favorite(index) return raise ValueError(f"Unsupported media type '{media_type}'")
async def async_play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Play media from a URL or file, launch an application, or tune to a channel.""" extra: dict[str, Any] = kwargs.get(ATTR_MEDIA_EXTRA) or {} # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media( self.hass, media_id) media_type = MEDIA_TYPE_URL media_id = sourced_media.url # Sign and prefix with URL if playing a relative URL if media_id[0] == "/": media_id = async_sign_path( self.hass, quote(media_id), dt.timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME), ) # prepend external URL hass_url = get_url(self.hass) media_id = f"{hass_url}{media_id}" if media_type not in PLAY_MEDIA_SUPPORTED_TYPES: _LOGGER.error( "Invalid media type %s. Only %s, %s, %s, and camera HLS streams are supported", media_type, MEDIA_TYPE_APP, MEDIA_TYPE_CHANNEL, MEDIA_TYPE_URL, ) return if media_type == MEDIA_TYPE_APP: params = { param: extra[attr] for attr, param in ATTRS_TO_LAUNCH_PARAMS.items() if attr in extra } await self.coordinator.roku.launch(media_id, params) elif media_type == MEDIA_TYPE_CHANNEL: await self.coordinator.roku.tune(media_id) elif media_type == MEDIA_TYPE_URL: params = { param: extra[attr] for (attr, param) in ATTRS_TO_PLAY_VIDEO_PARAMS.items() if attr in extra } await self.coordinator.roku.play_on_roku(media_id, params) elif media_type == FORMAT_CONTENT_TYPE[HLS_PROVIDER]: params = { "MediaType": "hls", } await self.coordinator.roku.play_on_roku(media_id, params) await self.coordinator.async_request_refresh()
async def async_play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media(self.hass, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url # If media ID is a relative URL, we serve it from HA. # Create a signed path. if media_id[0] == "/": # Sign URL with Home Assistant Cast User config_entries = self.hass.config_entries.async_entries(CAST_DOMAIN) user_id = config_entries[0].data["user_id"] user = await self.hass.auth.async_get_user(user_id) if user.refresh_tokens: refresh_token: RefreshToken = list(user.refresh_tokens.values())[0] media_id = async_sign_path( self.hass, refresh_token.id, media_id, timedelta(minutes=5), ) # prepend external URL hass_url = get_url(self.hass, prefer_external=True) media_id = f"{hass_url}{media_id}" await self.hass.async_add_executor_job( ft.partial(self.play_media, media_type, media_id, **kwargs) )
async def async_play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media( self.hass, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url # If media ID is a relative URL, we serve it from HA. # Create a signed path. if media_id[0] == "/": # Sign URL with Safegate Pro Cast User config_entry_id = self.registry_entry.config_entry_id config_entry = self.hass.config_entries.async_get_entry( config_entry_id) user_id = config_entry.data["user_id"] user = await self.hass.auth.async_get_user(user_id) if user.refresh_tokens: refresh_token: RefreshToken = list( user.refresh_tokens.values())[0] media_id = async_sign_path( self.hass, refresh_token.id, quote(media_id), timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME), ) # prepend external URL hass_url = get_url(self.hass, prefer_external=True) media_id = f"{hass_url}{media_id}" await self.hass.async_add_executor_job( ft.partial(self.play_media, media_type, media_id, **kwargs))
async def async_play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Play media.""" if media_source.is_media_source_id(media_id): play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id ) media_id = play_item.url if self.state == STATE_OFF: await self.async_turn_on() if media_id: parts = media_id.split(":") if parts[0] == "list": if (index := parts[3]) == "-1": index = "0" await self.coordinator.musiccast.play_list_media(index, self._zone_id) return if parts[0] == "presets": index = parts[1] await self.coordinator.musiccast.recall_netusb_preset( self._zone_id, index ) return if parts[0] in ("http", "https") or media_id.startswith("/"): media_id = async_process_play_media_url(self.hass, media_id) await self.coordinator.musiccast.play_url_media( self._zone_id, media_id, "HomeAssistant" ) return
def play_media(self, media_type, media_id, **kwargs): # Play a piece of media. # <ServiceCall media_player.play_media: media_content_type=music, media_content_id=http://192.168.13.91:8123/api/tts_proxy/74a4297365735b6c107b85e034347ce013eeae01_en_-_google.mp3, entity_id=['media_player.mt_office']> self._parent.send('mrad.setzone "{}"'.format(self._zoneId)) self._parent.send('mrad.setsource') media_type = media_type.lower() if media_source.is_media_source_id(media_id): media_type = "music" media_id = (asyncio.run_coroutine_threadsafe( media_source.async_resolve_media(self._hass, media_id, self.entity_id), self._hass.loop, ).result().url) media_id = async_process_play_media_url(self.hass, media_id) if media_type == "music": self._parent.send('duckplay "{}"'.format(media_id)) elif media_type == "scene": self._parent.send('recallscene "{}"'.format(media_id)) elif media_type == "preset": self._parent.send('recallpreset "{}"'.format(media_id)) elif media_type == "radiostation": self._parent.send('playradiostation "{}"'.format(media_id)) else: _LOGGER.error("Unexpected media_type='%s'.", media_type)
async def async_play_media(self, media_type, media_id, **kwargs): """Play media from media_source.""" if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media(self.hass, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url # If media ID is a relative URL, we serve it from HA. if media_id[0] == "/": user = await self.hass.auth.async_get_owner() if user.refresh_tokens: refresh_token: RefreshToken = list(user.refresh_tokens.values())[0] # Use kwargs so it works both before and after the change in Home Assistant 2022.2 media_id = async_sign_path( hass=self.hass, refresh_token_id=refresh_token.id, path=media_id, expiration=timedelta(minutes=5) ) # Prepend external URL. hass_url = get_url(self.hass, allow_internal=True) media_id = f"{hass_url}{media_id}" _LOGGER.info("Meural device %s: Playing media. Media type is %s, previewing image from %s", self.name, media_type, media_id) await self.local_meural.send_postcard(media_id, media_type) # Play gallery (playlist or album) by ID. elif media_type in ['playlist']: _LOGGER.info("Meural device %s: Playing media. Media type is %s, playing gallery %s", self.name, media_type, media_id) await self.local_meural.send_change_gallery(media_id) # "Preview image from URL. elif media_type in [ 'image/jpg', 'image/png', 'image/jpeg' ]: _LOGGER.info("Meural device %s: Playing media. Media type is %s, previewing image from %s", self.name, media_type, media_id) await self.local_meural.send_postcard(media_id, media_type) # Play item (artwork) by ID. Play locally if item is in currently displayed gallery. If not, play using Meural server.""" elif media_type in ['item']: if media_id.isdigit(): currentgallery_id = self._gallery_status["current_gallery"] currentitems = await self.local_meural.send_get_items_by_gallery(currentgallery_id) in_playlist = next((g["title"] for g in currentitems if g["id"] == media_id), None) if in_playlist is None: _LOGGER.info("Meural device %s: Playing media. Item %s is not in current gallery, trying to display via Meural server", self.name, media_id) try: await self.meural.device_load_item(self.meural_device_id, media_id) except: _LOGGER.error("Meural device %s: Playing media. Error while trying to display %s item %s via Meural server", self.name, media_type, media_id, exc_info=True) else: _LOGGER.info("Meural device %s: Playing media. Item %s is in current gallery %s, trying to display via local device", self.name, media_id, self._gallery_status["current_gallery_name"]) await self.local_meural.send_change_item(media_id) else: _LOGGER.error("Meural device %s: Playing media. ID %s is not an item", self.name, media_id) # This is an unsupported media type. else: _LOGGER.error("Meural device %s: Playing media. Does not support displaying this %s media with ID %s", self.name, media_type, media_id)
async def async_play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" if media_source.is_media_source_id(media_id): play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = async_process_play_media_url(self.hass, play_item.url) await self.hass.async_add_executor_job( partial(self.play_media, media_type, media_id, **kwargs))
async def async_play_media(self, media_type, media_id, **kwargs): if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_URL play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = play_item.url if media_type in (MEDIA_TYPE_URL, MEDIA_TYPE_MUSIC): media_id = async_process_play_media_url(self.hass, media_id) self.connection.send("play", media_content_id=media_id)
async def async_play_media(self, media_type, media_id, **kwargs): """Send the play_media command to the media player.""" index = None enqueue: MediaPlayerEnqueue | None = kwargs.get(ATTR_MEDIA_ENQUEUE) if enqueue == MediaPlayerEnqueue.ADD: cmd = "add" elif enqueue == MediaPlayerEnqueue.NEXT: cmd = "insert" elif enqueue == MediaPlayerEnqueue.PLAY: cmd = "play_now" else: cmd = "play" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_MUSIC play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id ) media_id = play_item.url if media_type in MEDIA_TYPE_MUSIC: if not media_id.startswith(SQUEEZEBOX_SOURCE_STRINGS): # do not process special squeezebox "source" media ids media_id = async_process_play_media_url(self.hass, media_id) await self._player.async_load_url(media_id, cmd) return if media_type == MEDIA_TYPE_PLAYLIST: try: # a saved playlist by number payload = { "search_id": int(media_id), "search_type": MEDIA_TYPE_PLAYLIST, } playlist = await generate_playlist(self._player, payload) except ValueError: # a list of urls content = json.loads(media_id) playlist = content["urls"] index = content["index"] else: payload = { "search_id": media_id, "search_type": media_type, } playlist = await generate_playlist(self._player, payload) _LOGGER.debug("Generated playlist: %s", playlist) await self._player.async_load_playlist(playlist, cmd) if index is not None: await self._player.async_index(index)
async def async_play_media( self, media_type: str, media_id: str, **kwargs: Any ) -> None: """Play a piece of media.""" if media_source.is_media_source_id(media_id): play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id ) media_id = async_process_play_media_url(self.hass, play_item.url) await self.coordinator.fully.playSound(media_id, AUDIOMANAGER_STREAM_MUSIC) self._attr_state = STATE_PLAYING self.async_write_ha_state()
async def async_play_media(self, media_type, media_id, **kwargs): """Play media.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_URL play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = play_item.url if media_type != MEDIA_TYPE_URL: _LOGGER.warning("Unsupported media_type: %s", media_type) return media_id = async_process_play_media_url(self.hass, media_id) await self._remote.async_play_media(media_type, media_id)
async def test_generate_media_source_id(): """Test identifier generation.""" tests = [ (None, None), (None, ""), ("", ""), ("domain", None), ("domain", ""), ("domain", "identifier"), ] for domain, identifier in tests: assert media_source.is_media_source_id( media_source.generate_media_source_id(domain, identifier))
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) 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_play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Send the play_media command to the media player.""" to_send_media_type: str | None = media_type # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media(self.hass, media_id) media_id = sourced_media.url to_send_media_type = sourced_media.mime_type if to_send_media_type and not to_send_media_type.startswith("audio/"): to_send_media_type = None media_id = async_process_play_media_url(self.hass, media_id) await self.player.play_url(media_id, mime_type=to_send_media_type)
async def async_play_media(self, media_type, media_id, **kwargs): """Play media.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media(self.hass, media_id) media_id = sourced_media.url elif media_type != MEDIA_TYPE_MUSIC: _LOGGER.error("Invalid media type") return media_id = async_process_play_media_url(self.hass, media_id) await self.hass.async_add_executor_job(self._player.queue, media_id)
async def async_play_media(self, media_type, media_id, **kwargs): """Send the play_media command to the media player.""" if self.is_grouped and not self.is_master: return if media_source.is_media_source_id(media_id): play_item = await media_source.async_resolve_media( self.hass, media_id, self.entity_id) media_id = play_item.url media_id = async_process_play_media_url(self.hass, media_id) url = f"Play?url={media_id}" return await self.send_bluesound_command(url)
async def async_play_media(self, media_type, media_id, **kwargs): """ Send the play_media command to the media player. If ATTR_MEDIA_ENQUEUE is True, add `media_id` to the current playlist. """ cmd = "play" index = None if kwargs.get(ATTR_MEDIA_ENQUEUE): cmd = "add" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_MUSIC play_item = await media_source.async_resolve_media(self.hass, media_id) media_id = play_item.url if media_type in MEDIA_TYPE_MUSIC: media_id = async_process_play_media_url(self.hass, media_id) await self._player.async_load_url(media_id, cmd) return if media_type == MEDIA_TYPE_PLAYLIST: try: # a saved playlist by number payload = { "search_id": int(media_id), "search_type": MEDIA_TYPE_PLAYLIST, } playlist = await generate_playlist(self._player, payload) except ValueError: # a list of urls content = json.loads(media_id) playlist = content["urls"] index = content["index"] else: payload = { "search_id": media_id, "search_type": media_type, } playlist = await generate_playlist(self._player, payload) _LOGGER.debug("Generated playlist: %s", playlist) await self._player.async_load_playlist(playlist, cmd) if index is not None: await self._player.async_index(index)
async def async_play_media(self, media_type, media_id, **kwargs): """Send the play_media command to the media player.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_MUSIC play_item = await media_source.async_resolve_media( self.hass, media_id) media_id = play_item.url if media_type != MEDIA_TYPE_MUSIC: _LOGGER.error( "Invalid media type %s. Only %s is supported", media_type, MEDIA_TYPE_MUSIC, ) return media_id = async_process_play_media_url(self.hass, media_id) track_details = {"title": "Home Assistant", "uri": media_id} await self._device.play_media(track_details)
async def async_browse_media(self, media_content_type=None, media_content_id=None): """Implement the websocket media browsing helper.""" is_internal = is_internal_request(self.hass) async def _get_thumbnail_url( media_content_type, media_content_id, media_image_id=None, thumbnail_url=None, ): if is_internal: return self._kodi.thumbnail_url(thumbnail_url) return self.get_browse_image_url( media_content_type, urllib.parse.quote_plus(media_content_id), media_image_id, ) if media_content_type in [None, "library"]: return await library_payload(self.hass) if media_source.is_media_source_id(media_content_id): return await media_source.async_browse_media( self.hass, media_content_id, content_filter=media_source_content_filter) payload = { "search_type": media_content_type, "search_id": media_content_id, } response = await build_item_response(self._kodi, payload, _get_thumbnail_url) if response is None: raise BrowseError( f"Media not found: {media_content_type} / {media_content_id}") return response
async def async_play_media( self, media_type: str, media_id: str, **kwargs: Any ) -> None: """Play a piece of media.""" _LOGGER.debug("Playing media: %s, %s, %s", media_type, media_id, kwargs) assert self._device is not None didl_metadata: str | None = None title: str = "" # If media is media_source, resolve it to url and MIME type, and maybe metadata if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media(self.hass, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url _LOGGER.debug("sourced_media is %s", sourced_media) if sourced_metadata := getattr(sourced_media, "didl_metadata", None): didl_metadata = didl_lite.to_xml_string(sourced_metadata).decode( "utf-8" ) title = sourced_metadata.title
async def async_play_media( self, media_type: str, media_id: str, **kwargs: Any ) -> None: """Send the play_media command to the media player.""" if media_source.is_media_source_id(media_id): media_type = MEDIA_TYPE_URL play_item = await media_source.async_resolve_media(self.hass, media_id) media_id = play_item.url media_type_lower = media_type.lower() if media_type_lower == MEDIA_TYPE_CHANNEL: await self._kodi.play_channel(int(media_id)) elif media_type_lower == MEDIA_TYPE_PLAYLIST: await self._kodi.play_playlist(int(media_id)) elif media_type_lower == "file": await self._kodi.play_file(media_id) elif media_type_lower == "directory": await self._kodi.play_directory(media_id) elif media_type_lower in [ MEDIA_TYPE_ARTIST, MEDIA_TYPE_ALBUM, MEDIA_TYPE_TRACK, ]: await self.async_clear_playlist() await self.async_add_to_playlist(media_type_lower, media_id) await self._kodi.play_playlist(0) elif media_type_lower in [ MEDIA_TYPE_MOVIE, MEDIA_TYPE_EPISODE, MEDIA_TYPE_SEASON, MEDIA_TYPE_TVSHOW, ]: await self._kodi.play_item( {MAP_KODI_MEDIA_TYPES[media_type_lower]: int(media_id)} ) else: media_id = async_process_play_media_url(self.hass, media_id) await self._kodi.play_file(media_id)
async def async_play_media(self, media_type: str, media_id: str, **kwargs: Any) -> None: """Play media from a URL or file.""" # Handle media_source if media_source.is_media_source_id(media_id): sourced_media = await media_source.async_resolve_media( self.hass, media_id) media_type = sourced_media.mime_type media_id = sourced_media.url if media_type != MEDIA_TYPE_MUSIC and not media_type.startswith( "audio/"): raise HomeAssistantError( f"Invalid media type {media_type}. Only {MEDIA_TYPE_MUSIC} is supported" ) # If media ID is a relative URL, we serve it from HA. media_id = async_process_play_media_url( self.hass, media_id, for_supervisor_network=self._using_addon) await self._vlc.add(media_id) self._state = STATE_PLAYING