diff --git a/homeassistant/components/kodi/browse_media.py b/homeassistant/components/kodi/browse_media.py index 1b0c5d521c9..e0fdb0f73fd 100644 --- a/homeassistant/components/kodi/browse_media.py +++ b/homeassistant/components/kodi/browse_media.py @@ -1,7 +1,9 @@ """Support for media browsing.""" import asyncio +import contextlib import logging +from homeassistant.components import media_source from homeassistant.components.media_player import BrowseError, BrowseMedia from homeassistant.components.media_player.const import ( MEDIA_CLASS_ALBUM, @@ -184,7 +186,7 @@ async def item_payload(item, get_thumbnail_url=None): ) -async def library_payload(): +async def library_payload(hass): """ Create response payload to describe contents of a specific library. @@ -222,6 +224,14 @@ async def library_payload(): ) ) + with contextlib.suppress(media_source.BrowseError): + item = await media_source.async_browse_media(hass, None) + # If domain is None, it's overview of available sources + if item.domain is None: + library_info.children.extend(item.children) + else: + library_info.children.append(item) + return library_info diff --git a/homeassistant/components/kodi/manifest.json b/homeassistant/components/kodi/manifest.json index 3a39a7870a3..86034ea9cfc 100644 --- a/homeassistant/components/kodi/manifest.json +++ b/homeassistant/components/kodi/manifest.json @@ -2,6 +2,7 @@ "domain": "kodi", "name": "Kodi", "documentation": "https://www.home-assistant.io/integrations/kodi", + "after_dependencies": ["media_source"], "requirements": ["pykodi==0.2.7"], "codeowners": ["@OnFreund", "@cgtobi"], "zeroconf": ["_xbmc-jsonrpc-h._tcp.local."], diff --git a/homeassistant/components/kodi/media_player.py b/homeassistant/components/kodi/media_player.py index 5067ee84826..56b0abb6a15 100644 --- a/homeassistant/components/kodi/media_player.py +++ b/homeassistant/components/kodi/media_player.py @@ -5,6 +5,7 @@ from datetime import timedelta from functools import wraps import logging import re +from typing import Any import urllib.parse import jsonrpc_base @@ -12,7 +13,11 @@ from jsonrpc_base.jsonrpc import ProtocolError, TransportError from pykodi import CannotConnectError import voluptuous as vol +from homeassistant.components import media_source from homeassistant.components.media_player import PLATFORM_SCHEMA, MediaPlayerEntity +from homeassistant.components.media_player.browse_media import ( + async_process_play_media_url, +) from homeassistant.components.media_player.const import ( MEDIA_TYPE_ALBUM, MEDIA_TYPE_ARTIST, @@ -24,6 +29,7 @@ from homeassistant.components.media_player.const import ( MEDIA_TYPE_SEASON, MEDIA_TYPE_TRACK, MEDIA_TYPE_TVSHOW, + MEDIA_TYPE_URL, MEDIA_TYPE_VIDEO, SUPPORT_BROWSE_MEDIA, SUPPORT_NEXT_TRACK, @@ -691,8 +697,15 @@ class KodiEntity(MediaPlayerEntity): await self._kodi.media_seek(position) @cmd - async def async_play_media(self, media_type, media_id, **kwargs): + 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: @@ -700,7 +713,7 @@ class KodiEntity(MediaPlayerEntity): elif media_type_lower == MEDIA_TYPE_PLAYLIST: await self._kodi.play_playlist(int(media_id)) elif media_type_lower == "directory": - await self._kodi.play_directory(str(media_id)) + await self._kodi.play_directory(media_id) elif media_type_lower in [ MEDIA_TYPE_ARTIST, MEDIA_TYPE_ALBUM, @@ -719,7 +732,9 @@ class KodiEntity(MediaPlayerEntity): {MAP_KODI_MEDIA_TYPES[media_type_lower]: int(media_id)} ) else: - await self._kodi.play_file(str(media_id)) + media_id = async_process_play_media_url(self.hass, media_id) + + await self._kodi.play_file(media_id) @cmd async def async_set_shuffle(self, shuffle): @@ -898,7 +913,10 @@ class KodiEntity(MediaPlayerEntity): ) if media_content_type in [None, "library"]: - return await library_payload() + 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) payload = { "search_type": media_content_type,