mirror of
https://github.com/home-assistant/core.git
synced 2026-06-01 13:14:35 +01:00
676e9c7f29
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
113 lines
3.6 KiB
Python
113 lines
3.6 KiB
Python
"""Component to embed Google Cast."""
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Protocol
|
|
from uuid import UUID
|
|
|
|
from pychromecast import Chromecast
|
|
from pychromecast.controllers.multizone import MultizoneManager
|
|
from pychromecast.discovery import CastBrowser
|
|
|
|
from homeassistant.components.media_player import BrowseMedia, MediaType
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import Platform
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers import device_registry as dr
|
|
from homeassistant.helpers.integration_platform import (
|
|
async_process_integration_platforms,
|
|
)
|
|
|
|
from . import home_assistant_cast
|
|
from .const import DOMAIN
|
|
|
|
PLATFORMS = [Platform.MEDIA_PLAYER]
|
|
|
|
type CastConfigEntry = ConfigEntry[CastRuntimeData]
|
|
|
|
|
|
@dataclass
|
|
class CastRuntimeData:
|
|
"""Runtime data for the Cast integration."""
|
|
|
|
cast_platforms: dict[str, CastProtocol] = field(default_factory=dict)
|
|
unknown_models: dict[str | None, tuple[str | None, str | None]] = field(
|
|
default_factory=dict
|
|
)
|
|
added_cast_devices: set[UUID] = field(default_factory=set)
|
|
browser: CastBrowser | None = None
|
|
multizone_manager: MultizoneManager | None = None
|
|
|
|
|
|
async def async_setup_entry(hass: HomeAssistant, entry: CastConfigEntry) -> bool:
|
|
"""Set up Cast from a config entry."""
|
|
entry.runtime_data = CastRuntimeData()
|
|
await home_assistant_cast.async_setup_ha_cast(hass, entry)
|
|
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
|
|
|
@callback
|
|
def _register_cast_platform(
|
|
hass: HomeAssistant, integration_domain: str, platform: CastProtocol
|
|
) -> None:
|
|
"""Register a cast platform."""
|
|
if (
|
|
not hasattr(platform, "async_get_media_browser_root_object")
|
|
or not hasattr(platform, "async_browse_media")
|
|
or not hasattr(platform, "async_play_media")
|
|
):
|
|
raise HomeAssistantError(f"Invalid cast platform {platform}")
|
|
entry.runtime_data.cast_platforms[integration_domain] = platform
|
|
|
|
await async_process_integration_platforms(hass, DOMAIN, _register_cast_platform)
|
|
return True
|
|
|
|
|
|
class CastProtocol(Protocol):
|
|
"""Define the format of cast platforms."""
|
|
|
|
async def async_get_media_browser_root_object(
|
|
self, hass: HomeAssistant, cast_type: str
|
|
) -> list[BrowseMedia]:
|
|
"""Create a list of root objects for media browsing."""
|
|
|
|
async def async_browse_media(
|
|
self,
|
|
hass: HomeAssistant,
|
|
media_content_type: MediaType | str,
|
|
media_content_id: str,
|
|
cast_type: str,
|
|
) -> BrowseMedia | None:
|
|
"""Browse media.
|
|
|
|
Return a BrowseMedia object or None if the media does not belong to
|
|
this platform.
|
|
"""
|
|
|
|
async def async_play_media(
|
|
self,
|
|
hass: HomeAssistant,
|
|
cast_entity_id: str,
|
|
chromecast: Chromecast,
|
|
media_type: MediaType | str,
|
|
media_id: str,
|
|
) -> bool:
|
|
"""Play media.
|
|
|
|
Return True if the media is played by the platform, False if not.
|
|
"""
|
|
|
|
|
|
async def async_remove_entry(hass: HomeAssistant, entry: CastConfigEntry) -> None:
|
|
"""Remove Home Assistant Cast user."""
|
|
await home_assistant_cast.async_remove_user(hass, entry)
|
|
|
|
|
|
async def async_remove_config_entry_device(
|
|
hass: HomeAssistant, config_entry: CastConfigEntry, device_entry: dr.DeviceEntry
|
|
) -> bool:
|
|
"""Remove cast config entry from a device.
|
|
|
|
The actual cleanup is done in CastMediaPlayerEntity.async_will_remove_from_hass.
|
|
"""
|
|
return True
|