Compare commits
2 commits
dev
...
cast_use_s
Author | SHA1 | Date | |
---|---|---|---|
|
deb196af36 | ||
|
46239cc97c |
1 changed files with 79 additions and 40 deletions
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
from contextlib import suppress
|
from contextlib import suppress
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import functools as ft
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
@ -21,7 +20,7 @@ from pychromecast.socket_client import (
|
||||||
)
|
)
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import media_source, plex, zeroconf
|
from homeassistant.components import media_source, plex, spotify, zeroconf
|
||||||
from homeassistant.components.http.auth import async_sign_path
|
from homeassistant.components.http.auth import async_sign_path
|
||||||
from homeassistant.components.media_player import (
|
from homeassistant.components.media_player import (
|
||||||
BrowseError,
|
BrowseError,
|
||||||
|
@ -461,33 +460,10 @@ class CastDevice(MediaPlayerEntity):
|
||||||
media_controller = self._media_controller()
|
media_controller = self._media_controller()
|
||||||
media_controller.seek(position)
|
media_controller.seek(position)
|
||||||
|
|
||||||
async def async_browse_media(self, media_content_type=None, media_content_id=None):
|
async def _async_root_payload(self, content_filter):
|
||||||
"""Implement the websocket media browsing helper."""
|
"""Generate root node."""
|
||||||
kwargs = {}
|
|
||||||
children = []
|
children = []
|
||||||
|
# Add external sources
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
if "plex" in self.hass.config.components:
|
if "plex" in self.hass.config.components:
|
||||||
children.append(
|
children.append(
|
||||||
BrowseMedia(
|
BrowseMedia(
|
||||||
|
@ -501,15 +477,30 @@ class CastDevice(MediaPlayerEntity):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "spotify" in self.hass.config.components:
|
||||||
|
children.append(
|
||||||
|
BrowseMedia(
|
||||||
|
title="Spotify",
|
||||||
|
media_class=MEDIA_CLASS_APP,
|
||||||
|
media_content_id="",
|
||||||
|
media_content_type="spotify",
|
||||||
|
thumbnail="https://brands.home-assistant.io/_/spotify/logo.png",
|
||||||
|
can_play=False,
|
||||||
|
can_expand=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add local media source
|
||||||
try:
|
try:
|
||||||
result = await media_source.async_browse_media(
|
result = await media_source.async_browse_media(
|
||||||
self.hass, media_content_id, **kwargs
|
self.hass, None, content_filter=content_filter
|
||||||
)
|
)
|
||||||
children.append(result)
|
children.append(result)
|
||||||
except BrowseError:
|
except BrowseError:
|
||||||
if not children:
|
if not children:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# If there's only one media source, resolve it
|
||||||
if len(children) == 1:
|
if len(children) == 1:
|
||||||
return await self.async_browse_media(
|
return await self.async_browse_media(
|
||||||
children[0].media_content_type,
|
children[0].media_content_type,
|
||||||
|
@ -526,6 +517,44 @@ class CastDevice(MediaPlayerEntity):
|
||||||
children=children,
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
if spotify.is_spotify_media_type(media_content_type):
|
||||||
|
return await spotify.async_browse_media(
|
||||||
|
self.hass, media_content_type, media_content_id, can_play_artist=False
|
||||||
|
)
|
||||||
|
|
||||||
|
if media_content_type == "spotify":
|
||||||
|
return await spotify.async_browse_media(
|
||||||
|
self.hass, None, None, can_play_artist=False
|
||||||
|
)
|
||||||
|
|
||||||
|
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):
|
async def async_play_media(self, media_type, media_id, **kwargs):
|
||||||
"""Play a piece of media."""
|
"""Play a piece of media."""
|
||||||
# Handle media_source
|
# Handle media_source
|
||||||
|
@ -547,12 +576,6 @@ class CastDevice(MediaPlayerEntity):
|
||||||
hass_url = get_url(self.hass, prefer_external=True)
|
hass_url = get_url(self.hass, prefer_external=True)
|
||||||
media_id = f"{hass_url}{media_id}"
|
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, {})
|
extra = kwargs.get(ATTR_MEDIA_EXTRA, {})
|
||||||
metadata = extra.get("metadata")
|
metadata = extra.get("metadata")
|
||||||
|
|
||||||
|
@ -571,7 +594,9 @@ class CastDevice(MediaPlayerEntity):
|
||||||
if "app_id" in app_data:
|
if "app_id" in app_data:
|
||||||
app_id = app_data.pop("app_id")
|
app_id = app_data.pop("app_id")
|
||||||
_LOGGER.info("Starting Cast app by ID %s", 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:
|
if app_data:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Extra keys %s were ignored. Please use app_name to cast media",
|
"Extra keys %s were ignored. Please use app_name to cast media",
|
||||||
|
@ -581,21 +606,35 @@ class CastDevice(MediaPlayerEntity):
|
||||||
|
|
||||||
app_name = app_data.pop("app_name")
|
app_name = app_data.pop("app_name")
|
||||||
try:
|
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:
|
except NotImplementedError:
|
||||||
_LOGGER.error("App %s not supported", app_name)
|
_LOGGER.error("App %s not supported", app_name)
|
||||||
|
|
||||||
# Handle plex
|
# Handle plex
|
||||||
elif media_id and media_id.startswith(PLEX_URI_SCHEME):
|
elif media_id and media_id.startswith(PLEX_URI_SCHEME):
|
||||||
media_id = media_id[len(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:
|
if media is None:
|
||||||
return
|
return
|
||||||
controller = PlexController()
|
controller = PlexController()
|
||||||
self._chromecast.register_handler(controller)
|
self._chromecast.register_handler(controller)
|
||||||
controller.play_media(media)
|
await self.hass.async_add_executor_job(controller.play_media, media)
|
||||||
|
|
||||||
|
# Handle spotify
|
||||||
|
elif media_id and media_id.startswith("spotify:"):
|
||||||
|
data = {"entity_id": self.entity_id, "uri": media_id}
|
||||||
|
await self.hass.services.async_call(
|
||||||
|
"spotcast", "start", data, blocking=False
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
app_data = {"media_id": media_id, "media_type": media_type, **extra}
|
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):
|
def _media_status(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue