Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion homeassistant/components/cast/media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
from collections.abc import Callable
from contextlib import suppress
from datetime import datetime
from functools import wraps
import json
import logging
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar

import pychromecast
from pychromecast.controllers.homeassistant import HomeAssistantController
Expand All @@ -19,6 +20,7 @@
)
from pychromecast.controllers.multizone import MultizoneManager
from pychromecast.controllers.receiver import VOLUME_CONTROL_TYPE_FIXED
from pychromecast.error import PyChromecastError
from pychromecast.quick_play import quick_play
from pychromecast.socket_client import (
CONNECTION_STATUS_CONNECTED,
Expand Down Expand Up @@ -84,6 +86,34 @@
CAST_SPLASH = "https://www.home-assistant.io/images/cast/splash.png"


_CastDeviceT = TypeVar("_CastDeviceT", bound="CastDevice")
_R = TypeVar("_R")
_P = ParamSpec("_P")

_FuncType = Callable[Concatenate[_CastDeviceT, _P], _R]
_ReturnFuncType = Callable[Concatenate[_CastDeviceT, _P], _R]


def api_error(
func: _FuncType[_CastDeviceT, _P, _R],
) -> _ReturnFuncType[_CastDeviceT, _P, _R]:
"""Handle PyChromecastError and reraise a HomeAssistantError."""

@wraps(func)
def wrapper(self: _CastDeviceT, *args: _P.args, **kwargs: _P.kwargs) -> _R:
"""Wrap a CastDevice method."""
try:
return_value = func(self, *args, **kwargs)
except PyChromecastError as err:
raise HomeAssistantError(
f"{self.__class__.__name__}.{func.__name__} Failed: {err}"
) from err

return return_value

return wrapper


@callback
def _async_create_cast_device(hass: HomeAssistant, info: ChromecastInfo):
"""Create a CastDevice entity or dynamic group from the chromecast object.
Expand Down Expand Up @@ -478,6 +508,7 @@ def _media_controller(self):

return media_controller

@api_error
def turn_on(self) -> None:
"""Turn on the cast device."""

Expand All @@ -497,43 +528,52 @@ def turn_on(self) -> None:
else:
chromecast.start_app(pychromecast.config.APP_MEDIA_RECEIVER)

@api_error
def turn_off(self) -> None:
"""Turn off the cast device."""
self._get_chromecast().quit_app()

@api_error
def mute_volume(self, mute: bool) -> None:
"""Mute the volume."""
self._get_chromecast().set_volume_muted(mute)

@api_error
def set_volume_level(self, volume: float) -> None:
"""Set volume level, range 0..1."""
self._get_chromecast().set_volume(volume)

@api_error
def media_play(self) -> None:
"""Send play command."""
media_controller = self._media_controller()
media_controller.play()

@api_error
def media_pause(self) -> None:
"""Send pause command."""
media_controller = self._media_controller()
media_controller.pause()

@api_error
def media_stop(self) -> None:
"""Send stop command."""
media_controller = self._media_controller()
media_controller.stop()

@api_error
def media_previous_track(self) -> None:
"""Send previous track command."""
media_controller = self._media_controller()
media_controller.queue_prev()

@api_error
def media_next_track(self) -> None:
"""Send next track command."""
media_controller = self._media_controller()
media_controller.queue_next()

@api_error
def media_seek(self, position: float) -> None:
"""Seek the media to a specific location."""
media_controller = self._media_controller()
Expand Down Expand Up @@ -616,6 +656,7 @@ def audio_content_filter(item):
self.hass, media_content_id, content_filter=content_filter
)

@api_error
Comment thread
MartinHjelmare marked this conversation as resolved.
Outdated
async def async_play_media(
self, media_type: MediaType | str, media_id: str, **kwargs: Any
) -> None:
Expand Down