diff --git a/homeassistant/components/music_assistant/media_player.py b/homeassistant/components/music_assistant/media_player.py index 91c9d5ffd90..a11e334824a 100644 --- a/homeassistant/components/music_assistant/media_player.py +++ b/homeassistant/components/music_assistant/media_player.py @@ -42,7 +42,7 @@ from homeassistant.components.media_player import ( ) from homeassistant.const import ATTR_NAME, STATE_OFF from homeassistant.core import HomeAssistant, ServiceResponse, SupportsResponse -from homeassistant.exceptions import HomeAssistantError +from homeassistant.exceptions import HomeAssistantError, ServiceValidationError from homeassistant.helpers import config_validation as cv, entity_registry as er from homeassistant.helpers.entity_platform import ( AddConfigEntryEntitiesCallback, @@ -227,6 +227,7 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity): self._set_supported_features() self._attr_device_class = MediaPlayerDeviceClass.SPEAKER self._prev_time: float = 0 + self._source_list_mapping: dict[str, str] = {} async def async_added_to_hass(self) -> None: """Register callbacks.""" @@ -292,10 +293,20 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity): self._attr_state = MediaPlayerState(player.state.value) else: self._attr_state = MediaPlayerState(STATE_OFF) - self._attr_source = player.active_source - self._attr_source_list = [ - source.name for source in player.source_list if not source.passive - ] + # active source and source list (translate to HA source names) + source_mappings: dict[str, str] = {} + active_source_name: str | None = None + for source in player.source_list: + if source.id == player.active_source: + active_source_name = source.name + if source.passive: + # ignore passive sources because HA does not differentiate between + # active and passive sources + continue + source_mappings[source.name] = source.id + self._attr_source_list = list(source_mappings.keys()) + self._source_list_mapping = source_mappings + self._attr_source = active_source_name group_members: list[str] = [] if player.group_childs: @@ -466,7 +477,12 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity): @catch_musicassistant_error async def async_select_source(self, source: str) -> None: """Select input source.""" - await self.mass.players.player_command_select_source(self.player_id, source) + source_id = self._source_list_mapping.get(source) + if source_id is None: + raise ServiceValidationError( + f"Source '{source}' not found for player {self.name}" + ) + await self.mass.players.player_command_select_source(self.player_id, source_id) @catch_musicassistant_error async def _async_handle_play_media( diff --git a/tests/components/music_assistant/snapshots/test_media_player.ambr b/tests/components/music_assistant/snapshots/test_media_player.ambr index 5782156e722..e7c2eec6f4b 100644 --- a/tests/components/music_assistant/snapshots/test_media_player.ambr +++ b/tests/components/music_assistant/snapshots/test_media_player.ambr @@ -54,7 +54,7 @@ 'media_duration': 300, 'media_position': 0, 'media_title': 'Test Track', - 'source': 'spotify', + 'source': 'Spotify Connect', 'supported_features': , 'volume_level': 0.2, }), @@ -126,7 +126,6 @@ 'media_title': 'November Rain', 'repeat': 'all', 'shuffle': True, - 'source': 'test_group_player_1', 'supported_features': , 'volume_level': 0.06, }), diff --git a/tests/components/music_assistant/test_media_player.py b/tests/components/music_assistant/test_media_player.py index e2b45db45e4..eb1e64485c4 100644 --- a/tests/components/music_assistant/test_media_player.py +++ b/tests/components/music_assistant/test_media_player.py @@ -637,7 +637,7 @@ async def test_media_player_select_source_action( SERVICE_SELECT_SOURCE, { ATTR_ENTITY_ID: entity_id, - ATTR_INPUT_SOURCE: "linein", + ATTR_INPUT_SOURCE: "Line-In", }, blocking=True, )