diff --git a/homeassistant/components/cast/media_player.py b/homeassistant/components/cast/media_player.py index e966e98c3f1..6cca4cfa20b 100644 --- a/homeassistant/components/cast/media_player.py +++ b/homeassistant/components/cast/media_player.py @@ -4,7 +4,6 @@ from __future__ import annotations import asyncio from contextlib import suppress from datetime import datetime, timedelta -import functools as ft import json import logging from urllib.parse import quote @@ -461,33 +460,10 @@ class CastDevice(MediaPlayerEntity): media_controller = self._media_controller() media_controller.seek(position) - async def async_browse_media(self, media_content_type=None, media_content_id=None): - """Implement the websocket media browsing helper.""" - kwargs = {} + async def _async_root_payload(self, content_filter): + """Generate root node.""" children = [] - - if self._chromecast.cast_type == pychromecast.const.CAST_TYPE_AUDIO: - kwargs["content_filter"] = lambda item: item.media_content_type.startswith( - "audio/" - ) - - if media_content_id is not None: - if plex.is_plex_media_id(media_content_id): - return await plex.async_browse_media( - self.hass, - media_content_type, - media_content_id, - platform=CAST_DOMAIN, - ) - return await media_source.async_browse_media( - self.hass, media_content_id, **kwargs - ) - - if media_content_type == "plex": - return await plex.async_browse_media( - self.hass, None, None, platform=CAST_DOMAIN - ) - + # Add external sources if "plex" in self.hass.config.components: children.append( BrowseMedia( @@ -501,15 +477,17 @@ class CastDevice(MediaPlayerEntity): ) ) + # Add local media source try: result = await media_source.async_browse_media( - self.hass, media_content_id, **kwargs + self.hass, None, content_filter=content_filter ) children.append(result) except BrowseError: if not children: raise + # If there's only one media source, resolve it if len(children) == 1: return await self.async_browse_media( children[0].media_content_type, @@ -526,6 +504,34 @@ class CastDevice(MediaPlayerEntity): children=children, ) + async def async_browse_media(self, media_content_type=None, media_content_id=None): + """Implement the websocket media browsing helper.""" + content_filter = None + + if self._chromecast.cast_type == pychromecast.const.CAST_TYPE_AUDIO: + + def audio_content_filter(item): + """Filter non audio content.""" + return item.media_content_type.startswith("audio/") + + content_filter = audio_content_filter + + if media_content_id is None: + return await self._async_root_payload(content_filter) + + if plex.is_plex_media_id(media_content_id): + return await plex.async_browse_media( + self.hass, media_content_type, media_content_id, platform=CAST_DOMAIN + ) + if media_content_type == "plex": + return await plex.async_browse_media( + self.hass, None, None, platform=CAST_DOMAIN + ) + + return await media_source.async_browse_media( + self.hass, media_content_id, content_filter=content_filter + ) + async def async_play_media(self, media_type, media_id, **kwargs): """Play a piece of media.""" # Handle media_source @@ -547,12 +553,6 @@ class CastDevice(MediaPlayerEntity): 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) - ) - - def play_media(self, media_type, media_id, **kwargs): - """Play media from a URL.""" extra = kwargs.get(ATTR_MEDIA_EXTRA, {}) metadata = extra.get("metadata") @@ -571,7 +571,9 @@ class CastDevice(MediaPlayerEntity): if "app_id" in app_data: app_id = app_data.pop("app_id") _LOGGER.info("Starting Cast app by ID %s", app_id) - self._chromecast.start_app(app_id) + await self.hass.async_add_executor_job( + self._chromecast.start_app, app_id + ) if app_data: _LOGGER.warning( "Extra keys %s were ignored. Please use app_name to cast media", @@ -581,21 +583,28 @@ class CastDevice(MediaPlayerEntity): app_name = app_data.pop("app_name") try: - quick_play(self._chromecast, app_name, app_data) + await self.hass.async_add_executor_job( + quick_play, self._chromecast, app_name, app_data + ) except NotImplementedError: _LOGGER.error("App %s not supported", app_name) + # Handle plex elif media_id and media_id.startswith(PLEX_URI_SCHEME): media_id = media_id[len(PLEX_URI_SCHEME) :] - media = lookup_plex_media(self.hass, media_type, media_id) + media = await self.hass.async_add_executor_job( + lookup_plex_media, self.hass, media_type, media_id + ) if media is None: return controller = PlexController() self._chromecast.register_handler(controller) - controller.play_media(media) + await self.hass.async_add_executor_job(controller.play_media, media) else: app_data = {"media_id": media_id, "media_type": media_type, **extra} - quick_play(self._chromecast, "default_media_receiver", app_data) + await self.hass.async_add_executor_job( + quick_play, self._chromecast, "default_media_receiver", app_data + ) def _media_status(self): """