From 225e90c99e11ee277952d754b472cc4646901a0b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 21 Jun 2024 13:38:51 +0200 Subject: [PATCH] Add playback of autotrack lens to Reolink (#119829) Co-authored-by: Robert Resch Co-authored-by: Franck Nijhof --- .../components/reolink/media_source.py | 64 +++++++++++++++---- tests/components/reolink/test_media_source.py | 21 ++++++ 2 files changed, 72 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/reolink/media_source.py b/homeassistant/components/reolink/media_source.py index c941f5ed055..5d3c16b00fd 100644 --- a/homeassistant/components/reolink/media_source.py +++ b/homeassistant/components/reolink/media_source.py @@ -34,7 +34,15 @@ async def async_get_media_source(hass: HomeAssistant) -> ReolinkVODMediaSource: def res_name(stream: str) -> str: """Return the user friendly name for a stream.""" - return "High res." if stream == "main" else "Low res." + match stream: + case "main": + return "High res." + case "autotrack_sub": + return "Autotrack low res." + case "autotrack_main": + return "Autotrack high res." + case _: + return "Low res." class ReolinkVODMediaSource(MediaSource): @@ -210,9 +218,6 @@ class ReolinkVODMediaSource(MediaSource): "playback only possible using sub stream", host.api.camera_name(channel), ) - return await self._async_generate_camera_days( - config_entry_id, channel, "sub" - ) children = [ BrowseMediaSource( @@ -224,16 +229,49 @@ class ReolinkVODMediaSource(MediaSource): can_play=False, can_expand=True, ), - BrowseMediaSource( - domain=DOMAIN, - identifier=f"RES|{config_entry_id}|{channel}|main", - media_class=MediaClass.CHANNEL, - media_content_type=MediaType.PLAYLIST, - title="High resolution", - can_play=False, - can_expand=True, - ), ] + if main_enc != "h265": + children.append( + BrowseMediaSource( + domain=DOMAIN, + identifier=f"RES|{config_entry_id}|{channel}|main", + media_class=MediaClass.CHANNEL, + media_content_type=MediaType.PLAYLIST, + title="High resolution", + can_play=False, + can_expand=True, + ), + ) + + if host.api.supported(channel, "autotrack_stream"): + children.append( + BrowseMediaSource( + domain=DOMAIN, + identifier=f"RES|{config_entry_id}|{channel}|autotrack_sub", + media_class=MediaClass.CHANNEL, + media_content_type=MediaType.PLAYLIST, + title="Autotrack low resolution", + can_play=False, + can_expand=True, + ), + ) + if main_enc != "h265": + children.append( + BrowseMediaSource( + domain=DOMAIN, + identifier=f"RES|{config_entry_id}|{channel}|autotrack_main", + media_class=MediaClass.CHANNEL, + media_content_type=MediaType.PLAYLIST, + title="Autotrack high resolution", + can_play=False, + can_expand=True, + ), + ) + + if len(children) == 1: + return await self._async_generate_camera_days( + config_entry_id, channel, "sub" + ) return BrowseMediaSource( domain=DOMAIN, diff --git a/tests/components/reolink/test_media_source.py b/tests/components/reolink/test_media_source.py index 3e3cdd02b46..0d86106e8e5 100644 --- a/tests/components/reolink/test_media_source.py +++ b/tests/components/reolink/test_media_source.py @@ -156,11 +156,15 @@ async def test_browsing( browse_resolution_id = f"RESs|{entry_id}|{TEST_CHANNEL}" browse_res_sub_id = f"RES|{entry_id}|{TEST_CHANNEL}|sub" browse_res_main_id = f"RES|{entry_id}|{TEST_CHANNEL}|main" + browse_res_AT_sub_id = f"RES|{entry_id}|{TEST_CHANNEL}|autotrack_sub" + browse_res_AT_main_id = f"RES|{entry_id}|{TEST_CHANNEL}|autotrack_main" assert browse.domain == DOMAIN assert browse.title == TEST_NVR_NAME assert browse.identifier == browse_resolution_id assert browse.children[0].identifier == browse_res_sub_id assert browse.children[1].identifier == browse_res_main_id + assert browse.children[2].identifier == browse_res_AT_sub_id + assert browse.children[3].identifier == browse_res_AT_main_id # browse camera recording days mock_status = MagicMock() @@ -169,6 +173,22 @@ async def test_browsing( mock_status.days = (TEST_DAY, TEST_DAY2) reolink_connect.request_vod_files.return_value = ([mock_status], []) + browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/{browse_res_sub_id}") + assert browse.domain == DOMAIN + assert browse.title == f"{TEST_NVR_NAME} Low res." + + browse = await async_browse_media( + hass, f"{URI_SCHEME}{DOMAIN}/{browse_res_AT_sub_id}" + ) + assert browse.domain == DOMAIN + assert browse.title == f"{TEST_NVR_NAME} Autotrack low res." + + browse = await async_browse_media( + hass, f"{URI_SCHEME}{DOMAIN}/{browse_res_AT_main_id}" + ) + assert browse.domain == DOMAIN + assert browse.title == f"{TEST_NVR_NAME} Autotrack high res." + browse = await async_browse_media( hass, f"{URI_SCHEME}{DOMAIN}/{browse_res_main_id}" ) @@ -225,6 +245,7 @@ async def test_browsing_unsupported_encoding( reolink_connect.request_vod_files.return_value = ([mock_status], []) reolink_connect.time.return_value = None reolink_connect.get_encoding.return_value = "h265" + reolink_connect.supported.return_value = False browse = await async_browse_media(hass, f"{URI_SCHEME}{DOMAIN}/{browse_root_id}")