From 31b505828bd6aee1f386bb433a08418cb88acd70 Mon Sep 17 00:00:00 2001 From: Markus Jacobsen Date: Sat, 9 Nov 2024 17:13:07 +0100 Subject: [PATCH] Simplify Bang & Olufsen source determination (#130072) --- .../components/bang_olufsen/const.py | 59 +------------------ .../components/bang_olufsen/media_player.py | 30 ---------- tests/components/bang_olufsen/const.py | 6 +- .../snapshots/test_media_player.ambr | 2 +- .../bang_olufsen/test_media_player.py | 58 +++++------------- 5 files changed, 24 insertions(+), 131 deletions(-) diff --git a/homeassistant/components/bang_olufsen/const.py b/homeassistant/components/bang_olufsen/const.py index 1e06f153cdb..209311d3e8a 100644 --- a/homeassistant/components/bang_olufsen/const.py +++ b/homeassistant/components/bang_olufsen/const.py @@ -17,62 +17,9 @@ from homeassistant.components.media_player import ( class BangOlufsenSource: """Class used for associating device source ids with friendly names. May not include all sources.""" - URI_STREAMER: Final[Source] = Source( - name="Audio Streamer", - id="uriStreamer", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - BLUETOOTH: Final[Source] = Source( - name="Bluetooth", - id="bluetooth", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - CHROMECAST: Final[Source] = Source( - name="Chromecast built-in", - id="chromeCast", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - LINE_IN: Final[Source] = Source( - name="Line-In", - id="lineIn", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - SPDIF: Final[Source] = Source( - name="Optical", - id="spdif", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - NET_RADIO: Final[Source] = Source( - name="B&O Radio", - id="netRadio", - is_seekable=False, - is_enabled=True, - is_playable=True, - ) - DEEZER: Final[Source] = Source( - name="Deezer", - id="deezer", - is_seekable=True, - is_enabled=True, - is_playable=True, - ) - TIDAL: Final[Source] = Source( - name="Tidal", - id="tidal", - is_seekable=True, - is_enabled=True, - is_playable=True, - ) + LINE_IN: Final[Source] = Source(name="Line-In", id="lineIn") + SPDIF: Final[Source] = Source(name="Optical", id="spdif") + URI_STREAMER: Final[Source] = Source(name="Audio Streamer", id="uriStreamer") BANG_OLUFSEN_STATES: dict[str, MediaPlayerState] = { diff --git a/homeassistant/components/bang_olufsen/media_player.py b/homeassistant/components/bang_olufsen/media_player.py index 5dd45573672..56aa66d32e8 100644 --- a/homeassistant/components/bang_olufsen/media_player.py +++ b/homeassistant/components/bang_olufsen/media_player.py @@ -688,36 +688,6 @@ class BangOlufsenMediaPlayer(BangOlufsenEntity, MediaPlayerEntity): @property def source(self) -> str | None: """Return the current audio source.""" - - # Try to fix some of the source_change chromecast weirdness. - if hasattr(self._playback_metadata, "title"): - # source_change is chromecast but line in is selected. - if self._playback_metadata.title == BangOlufsenSource.LINE_IN.name: - return BangOlufsenSource.LINE_IN.name - - # source_change is chromecast but bluetooth is selected. - if self._playback_metadata.title == BangOlufsenSource.BLUETOOTH.name: - return BangOlufsenSource.BLUETOOTH.name - - # source_change is line in, bluetooth or optical but stale metadata is sent through the WebSocket, - # And the source has not changed. - if self._source_change.id in ( - BangOlufsenSource.BLUETOOTH.id, - BangOlufsenSource.LINE_IN.id, - BangOlufsenSource.SPDIF.id, - ): - return BangOlufsenSource.CHROMECAST.name - - # source_change is chromecast and there is metadata but no artwork. Bluetooth does support metadata but not artwork - # So i assume that it is bluetooth and not chromecast - if ( - hasattr(self._playback_metadata, "art") - and self._playback_metadata.art is not None - and len(self._playback_metadata.art) == 0 - and self._source_change.id == BangOlufsenSource.CHROMECAST.id - ): - return BangOlufsenSource.BLUETOOTH.name - return self._source_change.name @property diff --git a/tests/components/bang_olufsen/const.py b/tests/components/bang_olufsen/const.py index 3769aef5cd3..6602a898eb6 100644 --- a/tests/components/bang_olufsen/const.py +++ b/tests/components/bang_olufsen/const.py @@ -16,6 +16,7 @@ from mozart_api.models import ( PlayQueueItemType, RenderingState, SceneProperties, + Source, UserFlow, VolumeLevel, VolumeMute, @@ -125,7 +126,10 @@ TEST_DATA_ZEROCONF_IPV6 = ZeroconfServiceInfo( }, ) -TEST_AUDIO_SOURCES = [BangOlufsenSource.TIDAL.name, BangOlufsenSource.LINE_IN.name] +TEST_SOURCE = Source( + name="Tidal", id="tidal", is_seekable=True, is_enabled=True, is_playable=True +) +TEST_AUDIO_SOURCES = [TEST_SOURCE.name, BangOlufsenSource.LINE_IN.name] TEST_VIDEO_SOURCES = ["HDMI A"] TEST_SOURCES = TEST_AUDIO_SOURCES + TEST_VIDEO_SOURCES TEST_FALLBACK_SOURCES = [ diff --git a/tests/components/bang_olufsen/snapshots/test_media_player.ambr b/tests/components/bang_olufsen/snapshots/test_media_player.ambr index e48dc39198b..ea96e286821 100644 --- a/tests/components/bang_olufsen/snapshots/test_media_player.ambr +++ b/tests/components/bang_olufsen/snapshots/test_media_player.ambr @@ -573,7 +573,7 @@ 'Test Listening Mode (234)', 'Test Listening Mode 2 (345)', ]), - 'source': 'Chromecast built-in', + 'source': 'Line-In', 'source_list': list([ 'Tidal', 'Line-In', diff --git a/tests/components/bang_olufsen/test_media_player.py b/tests/components/bang_olufsen/test_media_player.py index e991ab3d1bc..aa35b0265dc 100644 --- a/tests/components/bang_olufsen/test_media_player.py +++ b/tests/components/bang_olufsen/test_media_player.py @@ -105,6 +105,7 @@ from .const import ( TEST_SEEK_POSITION_HOME_ASSISTANT_FORMAT, TEST_SOUND_MODE_2, TEST_SOUND_MODES, + TEST_SOURCE, TEST_SOURCES, TEST_VIDEO_SOURCES, TEST_VOLUME, @@ -231,7 +232,7 @@ async def test_async_update_sources_availability( # Add a source that is available and playable mock_mozart_client.get_available_sources.return_value = SourceArray( - items=[BangOlufsenSource.TIDAL] + items=[TEST_SOURCE] ) # Send playback_source. The source is not actually used, so its attributes don't matter @@ -239,7 +240,7 @@ async def test_async_update_sources_availability( assert mock_mozart_client.get_available_sources.call_count == 2 assert (states := hass.states.get(TEST_MEDIA_PLAYER_ENTITY_ID)) - assert states.attributes[ATTR_INPUT_SOURCE_LIST] == [BangOlufsenSource.TIDAL.name] + assert states.attributes[ATTR_INPUT_SOURCE_LIST] == [TEST_SOURCE.name] async def test_async_update_playback_metadata( @@ -357,19 +358,17 @@ async def test_async_update_playback_state( @pytest.mark.parametrize( - ("reported_source", "real_source", "content_type", "progress", "metadata"), + ("source", "content_type", "progress", "metadata"), [ - # Normal source, music mediatype expected, no progress expected + # Normal source, music mediatype expected ( - BangOlufsenSource.TIDAL, - BangOlufsenSource.TIDAL, + TEST_SOURCE, MediaType.MUSIC, TEST_PLAYBACK_PROGRESS.progress, PlaybackContentMetadata(), ), - # URI source, url media type expected, no progress expected + # URI source, url media type expected ( - BangOlufsenSource.URI_STREAMER, BangOlufsenSource.URI_STREAMER, MediaType.URL, TEST_PLAYBACK_PROGRESS.progress, @@ -378,44 +377,17 @@ async def test_async_update_playback_state( # Line-In source,media type expected, progress 0 expected ( BangOlufsenSource.LINE_IN, - BangOlufsenSource.CHROMECAST, MediaType.MUSIC, 0, PlaybackContentMetadata(), ), - # Chromecast as source, but metadata says Line-In. - # Progress is not set to 0 as the source is Chromecast first - ( - BangOlufsenSource.CHROMECAST, - BangOlufsenSource.LINE_IN, - MediaType.MUSIC, - TEST_PLAYBACK_PROGRESS.progress, - PlaybackContentMetadata(title=BangOlufsenSource.LINE_IN.name), - ), - # Chromecast as source, but metadata says Bluetooth - ( - BangOlufsenSource.CHROMECAST, - BangOlufsenSource.BLUETOOTH, - MediaType.MUSIC, - TEST_PLAYBACK_PROGRESS.progress, - PlaybackContentMetadata(title=BangOlufsenSource.BLUETOOTH.name), - ), - # Chromecast as source, but metadata says Bluetooth in another way - ( - BangOlufsenSource.CHROMECAST, - BangOlufsenSource.BLUETOOTH, - MediaType.MUSIC, - TEST_PLAYBACK_PROGRESS.progress, - PlaybackContentMetadata(art=[]), - ), ], ) async def test_async_update_source_change( hass: HomeAssistant, mock_mozart_client: AsyncMock, mock_config_entry: MockConfigEntry, - reported_source: Source, - real_source: Source, + source: Source, content_type: MediaType, progress: int, metadata: PlaybackContentMetadata, @@ -444,10 +416,10 @@ async def test_async_update_source_change( # Simulate metadata playback_metadata_callback(metadata) - source_change_callback(reported_source) + source_change_callback(source) assert (states := hass.states.get(TEST_MEDIA_PLAYER_ENTITY_ID)) - assert states.attributes[ATTR_INPUT_SOURCE] == real_source.name + assert states.attributes[ATTR_INPUT_SOURCE] == source.name assert states.attributes[ATTR_MEDIA_CONTENT_TYPE] == content_type assert states.attributes[ATTR_MEDIA_POSITION] == progress @@ -774,7 +746,7 @@ async def test_async_media_next_track( ("source", "expected_result", "seek_called_times"), [ # Seekable source, seek expected - (BangOlufsenSource.DEEZER, does_not_raise(), 1), + (TEST_SOURCE, does_not_raise(), 1), # Non seekable source, seek shouldn't work (BangOlufsenSource.LINE_IN, pytest.raises(HomeAssistantError), 0), # Malformed source, seek shouldn't work @@ -862,7 +834,7 @@ async def test_async_clear_playlist( # Invalid source ("Test source", pytest.raises(ServiceValidationError), 0, 0), # Valid audio source - (BangOlufsenSource.TIDAL.name, does_not_raise(), 1, 0), + (TEST_SOURCE.name, does_not_raise(), 1, 0), # Valid video source (TEST_VIDEO_SOURCES[0], does_not_raise(), 0, 1), ], @@ -1432,7 +1404,7 @@ async def test_async_join_players( await hass.config_entries.async_setup(mock_config_entry_2.entry_id) # Set the source to a beolink expandable source - source_change_callback(BangOlufsenSource.TIDAL) + source_change_callback(TEST_SOURCE) await hass.services.async_call( MEDIA_PLAYER_DOMAIN, @@ -1468,7 +1440,7 @@ async def test_async_join_players( ), # Invalid media_player entity ( - BangOlufsenSource.TIDAL, + TEST_SOURCE, [TEST_MEDIA_PLAYER_ENTITY_ID_3], pytest.raises(ServiceValidationError), "invalid_grouping_entity", @@ -1637,7 +1609,7 @@ async def test_async_beolink_expand( ) # Set the source to a beolink expandable source - source_change_callback(BangOlufsenSource.TIDAL) + source_change_callback(TEST_SOURCE) await hass.services.async_call( DOMAIN,