1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-20 02:48:57 +00:00

Add video source reporting to Bang & Olufsen (#158675)

This commit is contained in:
Markus Jacobsen
2025-12-12 15:40:12 +01:00
committed by GitHub
parent 715a484f7e
commit 421af881fe
4 changed files with 56 additions and 6 deletions

View File

@@ -22,6 +22,7 @@ class BeoSource:
NET_RADIO: Final[Source] = Source(name="B&O Radio", id="netRadio")
SPDIF: Final[Source] = Source(name="Optical", id="spdif")
TIDAL: Final[Source] = Source(name="Tidal", id="tidal")
TV: Final[Source] = Source(name="TV", id="tv")
UNKNOWN: Final[Source] = Source(name="Unknown Source", id="unknown")
URI_STREAMER: Final[Source] = Source(name="Audio Streamer", id="uriStreamer")
@@ -55,12 +56,13 @@ BEO_REPEAT_TO_HA: dict[str, RepeatMode] = {
class BeoMediaType(StrEnum):
"""Bang & Olufsen specific media types."""
FAVOURITE = "favourite"
DEEZER = "deezer"
FAVOURITE = "favourite"
OVERLAY_TTS = "overlay_tts"
RADIO = "radio"
TIDAL = "tidal"
TTS = "provider"
OVERLAY_TTS = "overlay_tts"
TV = "tv"
class BeoModel(StrEnum):

View File

@@ -218,6 +218,7 @@ class BeoMediaPlayer(BeoEntity, MediaPlayerEntity):
self._sources: dict[str, str] = {}
self._state: str = MediaPlayerState.IDLE
self._video_sources: dict[str, str] = {}
self._video_source_id_map: dict[str, str] = {}
self._sound_modes: dict[str, int] = {}
# Beolink compatible sources
@@ -355,6 +356,9 @@ class BeoMediaPlayer(BeoEntity, MediaPlayerEntity):
and menu_item.label != "TV"
):
self._video_sources[key] = menu_item.label
self._video_source_id_map[
menu_item.content.content_uri.removeprefix("tv://")
] = menu_item.label
# Combine the source dicts
self._sources = self._audio_sources | self._video_sources
@@ -627,10 +631,11 @@ class BeoMediaPlayer(BeoEntity, MediaPlayerEntity):
def media_content_type(self) -> MediaType | str | None:
"""Return the current media type."""
content_type = {
BeoSource.URI_STREAMER.id: MediaType.URL,
BeoSource.DEEZER.id: BeoMediaType.DEEZER,
BeoSource.TIDAL.id: BeoMediaType.TIDAL,
BeoSource.NET_RADIO.id: BeoMediaType.RADIO,
BeoSource.TIDAL.id: BeoMediaType.TIDAL,
BeoSource.TV.id: BeoMediaType.TV,
BeoSource.URI_STREAMER.id: MediaType.URL,
}
# Hard to determine content type.
if self._source_change.id in content_type:
@@ -690,7 +695,11 @@ class BeoMediaPlayer(BeoEntity, MediaPlayerEntity):
@property
def source(self) -> str | None:
"""Return the current audio source."""
"""Return the current audio/video source."""
# Associate TV content ID with a video source
if self.media_content_id in self._video_source_id_map:
return self._video_source_id_map[self.media_content_id]
return self._source_change.name
@property

View File

@@ -180,6 +180,14 @@ TEST_PLAYBACK_METADATA = PlaybackContentMetadata(
track=1,
source_internal_id="123",
)
TEST_PLAYBACK_METADATA_VIDEO = PlaybackContentMetadata(
encoding="unknown",
organization="HDMI A",
title="HDMI A",
source_internal_id="hdmi_1",
output_channel_processing="TrueImage",
output_Channels="5.0.2",
)
TEST_PLAYBACK_ERROR = PlaybackError(error="Test error")
TEST_PLAYBACK_PROGRESS = PlaybackProgress(progress=123)
TEST_PLAYBACK_STATE_PAUSED = RenderingState(value="paused")

View File

@@ -100,6 +100,7 @@ from .const import (
TEST_OVERLAY_OFFSET_VOLUME_TTS,
TEST_PLAYBACK_ERROR,
TEST_PLAYBACK_METADATA,
TEST_PLAYBACK_METADATA_VIDEO,
TEST_PLAYBACK_PROGRESS,
TEST_PLAYBACK_STATE_PAUSED,
TEST_PLAYBACK_STATE_PLAYING,
@@ -433,6 +434,36 @@ async def test_async_update_source_change(
assert (ATTR_MEDIA_CONTENT_ID in states.attributes) == content_id_available
async def test_async_update_source_change_video(
hass: HomeAssistant,
integration: None,
mock_mozart_client: AsyncMock,
) -> None:
"""Test _async_update_source_change with a video source."""
playback_metadata_callback = (
mock_mozart_client.get_playback_metadata_notifications.call_args[0][0]
)
source_change_callback = (
mock_mozart_client.get_source_change_notifications.call_args[0][0]
)
assert (states := hass.states.get(TEST_MEDIA_PLAYER_ENTITY_ID))
assert ATTR_INPUT_SOURCE not in states.attributes
assert states.attributes[ATTR_MEDIA_CONTENT_TYPE] == MediaType.MUSIC
# Simulate metadata and source change
playback_metadata_callback(TEST_PLAYBACK_METADATA_VIDEO)
source_change_callback(Source(id="tv", name="TV"))
assert (states := hass.states.get(TEST_MEDIA_PLAYER_ENTITY_ID))
assert states.attributes[ATTR_INPUT_SOURCE] == TEST_PLAYBACK_METADATA_VIDEO.title
assert states.attributes[ATTR_MEDIA_CONTENT_TYPE] == BeoMediaType.TV
assert (
states.attributes[ATTR_MEDIA_CONTENT_ID]
== TEST_PLAYBACK_METADATA_VIDEO.source_internal_id
)
async def test_async_turn_off(
hass: HomeAssistant,
integration: None,
@@ -819,7 +850,7 @@ async def test_async_select_source(
audio_source_call: int,
video_source_call: int,
) -> None:
"""Test async_select_source with an invalid source."""
"""Test async_select_source with an invalid source and valid audio and video sources."""
with expected_result:
await hass.services.async_call(
MEDIA_PLAYER_DOMAIN,