Fix Sonos play imported playlists (#113934)
parent
1779fe8f62
commit
f26a7843c6
|
@ -497,6 +497,20 @@ def get_media(
|
|||
"""Fetch media/album."""
|
||||
search_type = MEDIA_TYPES_TO_SONOS.get(search_type, search_type)
|
||||
|
||||
if search_type == "playlists":
|
||||
# Format is S:TITLE or S:ITEM_ID
|
||||
splits = item_id.split(":")
|
||||
title = splits[1] if len(splits) > 1 else None
|
||||
playlist = next(
|
||||
(
|
||||
p
|
||||
for p in media_library.get_playlists()
|
||||
if (item_id == p.item_id or title == p.title)
|
||||
),
|
||||
None,
|
||||
)
|
||||
return playlist
|
||||
|
||||
if not item_id.startswith("A:ALBUM") and search_type == SONOS_ALBUM:
|
||||
item_id = "A:ALBUMARTIST/" + "/".join(item_id.split("/")[2:])
|
||||
|
||||
|
|
|
@ -626,13 +626,13 @@ class SonosMediaPlayerEntity(SonosEntity, MediaPlayerEntity):
|
|||
soco.play_uri(media_id, force_radio=is_radio)
|
||||
elif media_type == MediaType.PLAYLIST:
|
||||
if media_id.startswith("S:"):
|
||||
item = media_browser.get_media(self.media.library, media_id, media_type)
|
||||
soco.play_uri(item.get_uri())
|
||||
return
|
||||
try:
|
||||
playlist = media_browser.get_media(
|
||||
self.media.library, media_id, media_type
|
||||
)
|
||||
else:
|
||||
playlists = soco.get_sonos_playlists(complete_result=True)
|
||||
playlist = next(p for p in playlists if p.title == media_id)
|
||||
except StopIteration:
|
||||
playlist = next((p for p in playlists if p.title == media_id), None)
|
||||
if not playlist:
|
||||
_LOGGER.error('Could not find a Sonos playlist named "%s"', media_id)
|
||||
else:
|
||||
soco.clear_queue()
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
"""Tests for the Sonos Media Player platform."""
|
||||
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.media_player import (
|
||||
DOMAIN as MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
)
|
||||
from homeassistant.const import STATE_IDLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import (
|
||||
|
@ -8,6 +16,8 @@ from homeassistant.helpers.device_registry import (
|
|||
DeviceRegistry,
|
||||
)
|
||||
|
||||
from .conftest import SoCoMockFactory
|
||||
|
||||
|
||||
async def test_device_registry(
|
||||
hass: HomeAssistant, device_registry: DeviceRegistry, async_autosetup_sonos, soco
|
||||
|
@ -53,3 +63,110 @@ async def test_entity_basic(
|
|||
assert attributes["friendly_name"] == "Zone A"
|
||||
assert attributes["is_volume_muted"] is False
|
||||
assert attributes["volume_level"] == 0.19
|
||||
|
||||
|
||||
class _MockMusicServiceItem:
|
||||
"""Mocks a Soco MusicServiceItem."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
item_id: str,
|
||||
parent_id: str,
|
||||
item_class: str,
|
||||
) -> None:
|
||||
"""Initialize the mock item."""
|
||||
self.title = title
|
||||
self.item_id = item_id
|
||||
self.item_class = item_class
|
||||
self.parent_id = parent_id
|
||||
|
||||
def get_uri(self) -> str:
|
||||
"""Return URI."""
|
||||
return self.item_id.replace("S://", "x-file-cifs://")
|
||||
|
||||
|
||||
_mock_playlists = [
|
||||
_MockMusicServiceItem(
|
||||
"playlist1",
|
||||
"S://192.168.1.68/music/iTunes/iTunes%20Music%20Library.xml#GUID_1",
|
||||
"A:PLAYLISTS",
|
||||
"object.container.playlistContainer",
|
||||
),
|
||||
_MockMusicServiceItem(
|
||||
"playlist2",
|
||||
"S://192.168.1.68/music/iTunes/iTunes%20Music%20Library.xml#GUID_2",
|
||||
"A:PLAYLISTS",
|
||||
"object.container.playlistContainer",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("media_content_id", "expected_item_id"),
|
||||
[
|
||||
(
|
||||
_mock_playlists[0].item_id,
|
||||
_mock_playlists[0].item_id,
|
||||
),
|
||||
(
|
||||
f"S:{_mock_playlists[1].title}",
|
||||
_mock_playlists[1].item_id,
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_play_media_music_library_playlist(
|
||||
hass: HomeAssistant,
|
||||
soco_factory: SoCoMockFactory,
|
||||
async_autosetup_sonos,
|
||||
discover,
|
||||
media_content_id,
|
||||
expected_item_id,
|
||||
) -> None:
|
||||
"""Test that playlists can be found by id or title."""
|
||||
soco_mock = soco_factory.mock_list.get("192.168.42.2")
|
||||
soco_mock.music_library.get_playlists.return_value = _mock_playlists
|
||||
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
{
|
||||
"entity_id": "media_player.zone_a",
|
||||
"media_content_type": "playlist",
|
||||
"media_content_id": media_content_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert soco_mock.clear_queue.call_count == 1
|
||||
assert soco_mock.add_to_queue.call_count == 1
|
||||
assert soco_mock.add_to_queue.call_args_list[0].args[0].item_id == expected_item_id
|
||||
assert soco_mock.play_from_queue.call_count == 1
|
||||
|
||||
|
||||
async def test_play_media_music_library_playlist_dne(
|
||||
hass: HomeAssistant,
|
||||
soco_factory: SoCoMockFactory,
|
||||
async_autosetup_sonos,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
"""Test error handling when attempting to play a non-existent playlist ."""
|
||||
media_content_id = "S:nonexistent"
|
||||
soco_mock = soco_factory.mock_list.get("192.168.42.2")
|
||||
soco_mock.music_library.get_playlists.return_value = _mock_playlists
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
caplog.clear()
|
||||
await hass.services.async_call(
|
||||
MP_DOMAIN,
|
||||
SERVICE_PLAY_MEDIA,
|
||||
{
|
||||
"entity_id": "media_player.zone_a",
|
||||
"media_content_type": "playlist",
|
||||
"media_content_id": media_content_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
assert soco_mock.play_uri.call_count == 0
|
||||
assert media_content_id in caplog.text
|
||||
assert "playlist" in caplog.text
|
||||
|
|
Loading…
Reference in New Issue