parent
dc1928f3eb
commit
3fea4efb9f
|
@ -275,11 +275,11 @@ class GroupManager:
|
|||
|
||||
player_id_to_entity_id_map = self.entity_id_map
|
||||
for group in groups.values():
|
||||
leader_entity_id = player_id_to_entity_id_map.get(group.leader.player_id)
|
||||
leader_entity_id = player_id_to_entity_id_map.get(group.lead_player_id)
|
||||
member_entity_ids = [
|
||||
player_id_to_entity_id_map[member.player_id]
|
||||
for member in group.members
|
||||
if member.player_id in player_id_to_entity_id_map
|
||||
player_id_to_entity_id_map[member]
|
||||
for member in group.member_player_ids
|
||||
if member in player_id_to_entity_id_map
|
||||
]
|
||||
# Make sure the group leader is always the first element
|
||||
group_info = [leader_entity_id, *member_entity_ids]
|
||||
|
@ -422,7 +422,7 @@ class SourceManager:
|
|||
None,
|
||||
)
|
||||
if index is not None:
|
||||
await player.play_favorite(index)
|
||||
await player.play_preset_station(index)
|
||||
return
|
||||
|
||||
input_source = next(
|
||||
|
@ -434,7 +434,7 @@ class SourceManager:
|
|||
None,
|
||||
)
|
||||
if input_source is not None:
|
||||
await player.play_input_source(input_source)
|
||||
await player.play_input_source(input_source.media_id)
|
||||
return
|
||||
|
||||
_LOGGER.error("Unknown source: %s", source)
|
||||
|
@ -447,7 +447,7 @@ class SourceManager:
|
|||
(
|
||||
input_source.name
|
||||
for input_source in self.inputs
|
||||
if input_source.input_name == now_playing_media.media_id
|
||||
if input_source.media_id == now_playing_media.media_id
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"documentation": "https://www.home-assistant.io/integrations/heos",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["pyheos"],
|
||||
"requirements": ["pyheos==0.8.0"],
|
||||
"requirements": ["pyheos==0.9.0"],
|
||||
"single_config_entry": true,
|
||||
"ssdp": [
|
||||
{
|
||||
|
|
|
@ -47,9 +47,9 @@ BASE_SUPPORTED_FEATURES = (
|
|||
)
|
||||
|
||||
PLAY_STATE_TO_STATE = {
|
||||
heos_const.PLAY_STATE_PLAY: MediaPlayerState.PLAYING,
|
||||
heos_const.PLAY_STATE_STOP: MediaPlayerState.IDLE,
|
||||
heos_const.PLAY_STATE_PAUSE: MediaPlayerState.PAUSED,
|
||||
heos_const.PlayState.PLAY: MediaPlayerState.PLAYING,
|
||||
heos_const.PlayState.STOP: MediaPlayerState.IDLE,
|
||||
heos_const.PlayState.PAUSE: MediaPlayerState.PAUSED,
|
||||
}
|
||||
|
||||
CONTROL_TO_SUPPORT = {
|
||||
|
@ -61,11 +61,11 @@ CONTROL_TO_SUPPORT = {
|
|||
}
|
||||
|
||||
HA_HEOS_ENQUEUE_MAP = {
|
||||
None: heos_const.ADD_QUEUE_REPLACE_AND_PLAY,
|
||||
MediaPlayerEnqueue.ADD: heos_const.ADD_QUEUE_ADD_TO_END,
|
||||
MediaPlayerEnqueue.REPLACE: heos_const.ADD_QUEUE_REPLACE_AND_PLAY,
|
||||
MediaPlayerEnqueue.NEXT: heos_const.ADD_QUEUE_PLAY_NEXT,
|
||||
MediaPlayerEnqueue.PLAY: heos_const.ADD_QUEUE_PLAY_NOW,
|
||||
None: heos_const.AddCriteriaType.REPLACE_AND_PLAY,
|
||||
MediaPlayerEnqueue.ADD: heos_const.AddCriteriaType.ADD_TO_END,
|
||||
MediaPlayerEnqueue.REPLACE: heos_const.AddCriteriaType.REPLACE_AND_PLAY,
|
||||
MediaPlayerEnqueue.NEXT: heos_const.AddCriteriaType.PLAY_NEXT,
|
||||
MediaPlayerEnqueue.PLAY: heos_const.AddCriteriaType.PLAY_NOW,
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -268,7 +268,7 @@ class HeosMediaPlayer(MediaPlayerEntity):
|
|||
)
|
||||
if index is None:
|
||||
raise ValueError(f"Invalid favorite '{media_id}'")
|
||||
await self._player.play_favorite(index)
|
||||
await self._player.play_preset_station(index)
|
||||
return
|
||||
|
||||
raise ValueError(f"Unsupported media type '{media_type}'")
|
||||
|
|
|
@ -1977,7 +1977,7 @@ pygti==0.9.4
|
|||
pyhaversion==22.8.0
|
||||
|
||||
# homeassistant.components.heos
|
||||
pyheos==0.8.0
|
||||
pyheos==0.9.0
|
||||
|
||||
# homeassistant.components.hive
|
||||
pyhiveapi==0.5.16
|
||||
|
|
|
@ -1606,7 +1606,7 @@ pygti==0.9.4
|
|||
pyhaversion==22.8.0
|
||||
|
||||
# homeassistant.components.heos
|
||||
pyheos==0.8.0
|
||||
pyheos==0.9.0
|
||||
|
||||
# homeassistant.components.hive
|
||||
pyhiveapi==0.5.16
|
||||
|
|
|
@ -5,15 +5,7 @@ from __future__ import annotations
|
|||
from collections.abc import Sequence
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from pyheos import (
|
||||
Dispatcher,
|
||||
Heos,
|
||||
HeosGroup,
|
||||
HeosPlayer,
|
||||
HeosSource,
|
||||
InputSource,
|
||||
const,
|
||||
)
|
||||
from pyheos import Dispatcher, Heos, HeosGroup, HeosPlayer, MediaItem, const
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
|
@ -124,12 +116,13 @@ def player_fixture(quick_selects):
|
|||
player.version = "1.0.0"
|
||||
player.is_muted = False
|
||||
player.available = True
|
||||
player.state = const.PLAY_STATE_STOP
|
||||
player.state = const.PlayState.STOP
|
||||
player.ip_address = f"127.0.0.{i}"
|
||||
player.network = "wired"
|
||||
player.shuffle = False
|
||||
player.repeat = const.REPEAT_OFF
|
||||
player.repeat = const.RepeatType.OFF
|
||||
player.volume = 25
|
||||
player.now_playing_media = Mock()
|
||||
player.now_playing_media.supported_controls = const.CONTROLS_ALL
|
||||
player.now_playing_media.album_id = 1
|
||||
player.now_playing_media.queue_id = 1
|
||||
|
@ -151,34 +144,52 @@ def player_fixture(quick_selects):
|
|||
@pytest.fixture(name="group")
|
||||
def group_fixture(players):
|
||||
"""Create a HEOS group consisting of two players."""
|
||||
group = Mock(HeosGroup)
|
||||
group.leader = players[1]
|
||||
group.members = [players[2]]
|
||||
group.group_id = 999
|
||||
group = HeosGroup(
|
||||
name="Group", group_id=999, lead_player_id=1, member_player_ids=[2]
|
||||
)
|
||||
|
||||
return {group.group_id: group}
|
||||
|
||||
|
||||
@pytest.fixture(name="favorites")
|
||||
def favorites_fixture() -> dict[int, HeosSource]:
|
||||
def favorites_fixture() -> dict[int, MediaItem]:
|
||||
"""Create favorites fixture."""
|
||||
station = Mock(HeosSource)
|
||||
station.type = const.TYPE_STATION
|
||||
station.name = "Today's Hits Radio"
|
||||
station.media_id = "123456789"
|
||||
radio = Mock(HeosSource)
|
||||
radio.type = const.TYPE_STATION
|
||||
radio.name = "Classical MPR (Classical Music)"
|
||||
radio.media_id = "s1234"
|
||||
station = MediaItem(
|
||||
source_id=const.MUSIC_SOURCE_PANDORA,
|
||||
name="Today's Hits Radio",
|
||||
media_id="123456789",
|
||||
type=const.MediaType.STATION,
|
||||
playable=True,
|
||||
browsable=False,
|
||||
image_url="",
|
||||
heos=None,
|
||||
)
|
||||
radio = MediaItem(
|
||||
source_id=const.MUSIC_SOURCE_TUNEIN,
|
||||
name="Classical MPR (Classical Music)",
|
||||
media_id="s1234",
|
||||
type=const.MediaType.STATION,
|
||||
playable=True,
|
||||
browsable=False,
|
||||
image_url="",
|
||||
heos=None,
|
||||
)
|
||||
return {1: station, 2: radio}
|
||||
|
||||
|
||||
@pytest.fixture(name="input_sources")
|
||||
def input_sources_fixture() -> Sequence[InputSource]:
|
||||
def input_sources_fixture() -> Sequence[MediaItem]:
|
||||
"""Create a set of input sources for testing."""
|
||||
source = Mock(InputSource)
|
||||
source.player_id = 1
|
||||
source.input_name = const.INPUT_AUX_IN_1
|
||||
source.name = "HEOS Drive - Line In 1"
|
||||
source = MediaItem(
|
||||
source_id=1,
|
||||
name="HEOS Drive - Line In 1",
|
||||
media_id=const.INPUT_AUX_IN_1,
|
||||
type=const.MediaType.STATION,
|
||||
playable=True,
|
||||
browsable=False,
|
||||
image_url="",
|
||||
heos=None,
|
||||
)
|
||||
return [source]
|
||||
|
||||
|
||||
|
@ -240,11 +251,17 @@ def quick_selects_fixture() -> dict[int, str]:
|
|||
|
||||
|
||||
@pytest.fixture(name="playlists")
|
||||
def playlists_fixture() -> Sequence[HeosSource]:
|
||||
def playlists_fixture() -> Sequence[MediaItem]:
|
||||
"""Create favorites fixture."""
|
||||
playlist = Mock(HeosSource)
|
||||
playlist.type = const.TYPE_PLAYLIST
|
||||
playlist.name = "Awesome Music"
|
||||
playlist = MediaItem(
|
||||
source_id=const.MUSIC_SOURCE_PLAYLISTS,
|
||||
name="Awesome Music",
|
||||
type=const.MediaType.PLAYLIST,
|
||||
playable=True,
|
||||
browsable=True,
|
||||
image_url="",
|
||||
heos=None,
|
||||
)
|
||||
return [playlist]
|
||||
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ async def test_updates_from_signals(
|
|||
player = controller.players[1]
|
||||
|
||||
# Test player does not update for other players
|
||||
player.state = const.PLAY_STATE_PLAY
|
||||
player.state = const.PlayState.PLAY
|
||||
player.heos.dispatcher.send(
|
||||
const.SIGNAL_PLAYER_EVENT, 2, const.EVENT_PLAYER_STATE_CHANGED
|
||||
)
|
||||
|
@ -124,7 +124,7 @@ async def test_updates_from_signals(
|
|||
assert state.state == STATE_IDLE
|
||||
|
||||
# Test player_update standard events
|
||||
player.state = const.PLAY_STATE_PLAY
|
||||
player.state = const.PlayState.PLAY
|
||||
player.heos.dispatcher.send(
|
||||
const.SIGNAL_PLAYER_EVENT, player.player_id, const.EVENT_PLAYER_STATE_CHANGED
|
||||
)
|
||||
|
@ -241,7 +241,7 @@ async def test_updates_from_players_changed(
|
|||
async_dispatcher_connect(hass, SIGNAL_HEOS_UPDATED, set_signal)
|
||||
|
||||
assert hass.states.get("media_player.test_player").state == STATE_IDLE
|
||||
player.state = const.PLAY_STATE_PLAY
|
||||
player.state = const.PlayState.PLAY
|
||||
player.heos.dispatcher.send(
|
||||
const.SIGNAL_CONTROLLER_EVENT, const.EVENT_PLAYERS_CHANGED, change_data
|
||||
)
|
||||
|
@ -551,7 +551,7 @@ async def test_select_favorite(
|
|||
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_favorite.assert_called_once_with(1)
|
||||
player.play_preset_station.assert_called_once_with(1)
|
||||
# Test state is matched by station name
|
||||
player.now_playing_media.station = favorite.name
|
||||
player.heos.dispatcher.send(
|
||||
|
@ -576,7 +576,7 @@ async def test_select_radio_favorite(
|
|||
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_favorite.assert_called_once_with(2)
|
||||
player.play_preset_station.assert_called_once_with(2)
|
||||
# Test state is matched by album id
|
||||
player.now_playing_media.station = "Classical"
|
||||
player.now_playing_media.album_id = favorite.media_id
|
||||
|
@ -601,14 +601,14 @@ async def test_select_radio_favorite_command_error(
|
|||
player = controller.players[1]
|
||||
# Test set radio preset
|
||||
favorite = favorites[2]
|
||||
player.play_favorite.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
player.play_preset_station.side_effect = CommandFailedError(None, "Failure", 1)
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_SELECT_SOURCE,
|
||||
{ATTR_ENTITY_ID: "media_player.test_player", ATTR_INPUT_SOURCE: favorite.name},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_favorite.assert_called_once_with(2)
|
||||
player.play_preset_station.assert_called_once_with(2)
|
||||
assert "Unable to select source: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -629,7 +629,7 @@ async def test_select_input_source(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_input_source.assert_called_once_with(input_source)
|
||||
player.play_input_source.assert_called_once_with(input_source.media_id)
|
||||
# Test state is matched by media id
|
||||
player.now_playing_media.source_id = const.MUSIC_SOURCE_AUX_INPUT
|
||||
player.now_playing_media.media_id = const.INPUT_AUX_IN_1
|
||||
|
@ -681,7 +681,7 @@ async def test_select_input_command_error(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_input_source.assert_called_once_with(input_source)
|
||||
player.play_input_source.assert_called_once_with(input_source.media_id)
|
||||
assert "Unable to select source: Failure (1)" in caplog.text
|
||||
|
||||
|
||||
|
@ -831,7 +831,7 @@ async def test_play_media_playlist(
|
|||
blocking=True,
|
||||
)
|
||||
player.add_to_queue.assert_called_once_with(
|
||||
playlist, const.ADD_QUEUE_REPLACE_AND_PLAY
|
||||
playlist, const.AddCriteriaType.REPLACE_AND_PLAY
|
||||
)
|
||||
# Play with enqueuing
|
||||
player.add_to_queue.reset_mock()
|
||||
|
@ -846,7 +846,9 @@ async def test_play_media_playlist(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
player.add_to_queue.assert_called_once_with(playlist, const.ADD_QUEUE_ADD_TO_END)
|
||||
player.add_to_queue.assert_called_once_with(
|
||||
playlist, const.AddCriteriaType.ADD_TO_END
|
||||
)
|
||||
# Invalid name
|
||||
player.add_to_queue.reset_mock()
|
||||
await hass.services.async_call(
|
||||
|
@ -888,9 +890,9 @@ async def test_play_media_favorite(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_favorite.assert_called_once_with(index)
|
||||
player.play_preset_station.assert_called_once_with(index)
|
||||
# Play by name
|
||||
player.play_favorite.reset_mock()
|
||||
player.play_preset_station.reset_mock()
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
|
@ -901,9 +903,9 @@ async def test_play_media_favorite(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
player.play_favorite.assert_called_once_with(index)
|
||||
player.play_preset_station.assert_called_once_with(index)
|
||||
# Invalid name
|
||||
player.play_favorite.reset_mock()
|
||||
player.play_preset_station.reset_mock()
|
||||
await hass.services.async_call(
|
||||
MEDIA_PLAYER_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
|
@ -914,7 +916,7 @@ async def test_play_media_favorite(
|
|||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert player.play_favorite.call_count == 0
|
||||
assert player.play_preset_station.call_count == 0
|
||||
assert "Unable to play media: Invalid favorite 'Invalid'" in caplog.text
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue