From 9002d85f9b7d33700435b758bf7c481cd0b64e04 Mon Sep 17 00:00:00 2001 From: tronikos Date: Sat, 22 Jun 2024 03:05:39 -0700 Subject: [PATCH] Support playback of videos in Fully Kiosk Browser (#119496) --- .../components/fully_kiosk/media_player.py | 28 ++++++++- .../fully_kiosk/test_media_player.py | 57 +++++++++++++++++++ 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/fully_kiosk/media_player.py b/homeassistant/components/fully_kiosk/media_player.py index 1e258c928e7..ae61a39bb81 100644 --- a/homeassistant/components/fully_kiosk/media_player.py +++ b/homeassistant/components/fully_kiosk/media_player.py @@ -14,6 +14,7 @@ from homeassistant.components.media_player import ( ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import AUDIOMANAGER_STREAM_MUSIC, DOMAIN, MEDIA_SUPPORT_FULLYKIOSK @@ -54,13 +55,33 @@ class FullyMediaPlayer(FullyKioskEntity, MediaPlayerEntity): ) media_id = async_process_play_media_url(self.hass, play_item.url) - await self.coordinator.fully.playSound(media_id, AUDIOMANAGER_STREAM_MUSIC) + if media_type.startswith("audio/"): + media_type = MediaType.MUSIC + elif media_type.startswith("video/"): + media_type = MediaType.VIDEO + if media_type == MediaType.MUSIC: + self._attr_media_content_type = MediaType.MUSIC + await self.coordinator.fully.playSound(media_id, AUDIOMANAGER_STREAM_MUSIC) + elif media_type == MediaType.VIDEO: + self._attr_media_content_type = MediaType.VIDEO + await self.coordinator.fully.sendCommand( + "playVideo", + url=media_id, + stream=AUDIOMANAGER_STREAM_MUSIC, + showControls=1, + exitOnCompletion=1, + ) + else: + raise HomeAssistantError(f"Unsupported media type {media_type}") self._attr_state = MediaPlayerState.PLAYING self.async_write_ha_state() async def async_media_stop(self) -> None: """Stop playing media.""" - await self.coordinator.fully.stopSound() + if self._attr_media_content_type == MediaType.VIDEO: + await self.coordinator.fully.sendCommand("stopVideo") + else: + await self.coordinator.fully.stopSound() self._attr_state = MediaPlayerState.IDLE self.async_write_ha_state() @@ -81,7 +102,8 @@ class FullyMediaPlayer(FullyKioskEntity, MediaPlayerEntity): return await media_source.async_browse_media( self.hass, media_content_id, - content_filter=lambda item: item.media_content_type.startswith("audio/"), + content_filter=lambda item: item.media_content_type.startswith("audio/") + or item.media_content_type.startswith("video/"), ) @callback diff --git a/tests/components/fully_kiosk/test_media_player.py b/tests/components/fully_kiosk/test_media_player.py index 4ee9b595a82..aa53421616f 100644 --- a/tests/components/fully_kiosk/test_media_player.py +++ b/tests/components/fully_kiosk/test_media_player.py @@ -2,11 +2,14 @@ from unittest.mock import MagicMock, Mock, patch +import pytest + from homeassistant.components import media_player from homeassistant.components.fully_kiosk.const import DOMAIN, MEDIA_SUPPORT_FULLYKIOSK from homeassistant.components.media_source import DOMAIN as MS_DOMAIN from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import device_registry as dr, entity_registry as er from homeassistant.setup import async_setup_component @@ -97,6 +100,60 @@ async def test_media_player( assert device_entry.sw_version == "1.42.5" +@pytest.mark.parametrize("media_content_type", ["video", "video/mp4"]) +async def test_media_player_video( + hass: HomeAssistant, + mock_fully_kiosk: MagicMock, + init_integration: MockConfigEntry, + media_content_type: str, +) -> None: + """Test Fully Kiosk media player for videos.""" + await hass.services.async_call( + media_player.DOMAIN, + "play_media", + { + ATTR_ENTITY_ID: "media_player.amazon_fire", + "media_content_type": media_content_type, + "media_content_id": "test.mp4", + }, + blocking=True, + ) + assert len(mock_fully_kiosk.sendCommand.mock_calls) == 1 + mock_fully_kiosk.sendCommand.assert_called_with( + "playVideo", url="test.mp4", stream=3, showControls=1, exitOnCompletion=1 + ) + + await hass.services.async_call( + media_player.DOMAIN, + "media_stop", + { + ATTR_ENTITY_ID: "media_player.amazon_fire", + }, + blocking=True, + ) + mock_fully_kiosk.sendCommand.assert_called_with("stopVideo") + + +async def test_media_player_unsupported( + hass: HomeAssistant, + mock_fully_kiosk: MagicMock, + init_integration: MockConfigEntry, +) -> None: + """Test Fully Kiosk media player for unsupported media.""" + with pytest.raises(HomeAssistantError) as error: + await hass.services.async_call( + media_player.DOMAIN, + "play_media", + { + ATTR_ENTITY_ID: "media_player.amazon_fire", + "media_content_type": "playlist", + "media_content_id": "test.m4u", + }, + blocking=True, + ) + assert error.value.args[0] == "Unsupported media type playlist" + + async def test_browse_media( hass: HomeAssistant, hass_ws_client: WebSocketGenerator,