mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Fix Sonos play imported playlists (#113934)
This commit is contained in:
parent
1779fe8f62
commit
f26a7843c6
@ -497,6 +497,20 @@ def get_media(
|
|||||||
"""Fetch media/album."""
|
"""Fetch media/album."""
|
||||||
search_type = MEDIA_TYPES_TO_SONOS.get(search_type, search_type)
|
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:
|
if not item_id.startswith("A:ALBUM") and search_type == SONOS_ALBUM:
|
||||||
item_id = "A:ALBUMARTIST/" + "/".join(item_id.split("/")[2:])
|
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)
|
soco.play_uri(media_id, force_radio=is_radio)
|
||||||
elif media_type == MediaType.PLAYLIST:
|
elif media_type == MediaType.PLAYLIST:
|
||||||
if media_id.startswith("S:"):
|
if media_id.startswith("S:"):
|
||||||
item = media_browser.get_media(self.media.library, media_id, media_type)
|
playlist = media_browser.get_media(
|
||||||
soco.play_uri(item.get_uri())
|
self.media.library, media_id, media_type
|
||||||
return
|
)
|
||||||
try:
|
else:
|
||||||
playlists = soco.get_sonos_playlists(complete_result=True)
|
playlists = soco.get_sonos_playlists(complete_result=True)
|
||||||
playlist = next(p for p in playlists if p.title == media_id)
|
playlist = next((p for p in playlists if p.title == media_id), None)
|
||||||
except StopIteration:
|
if not playlist:
|
||||||
_LOGGER.error('Could not find a Sonos playlist named "%s"', media_id)
|
_LOGGER.error('Could not find a Sonos playlist named "%s"', media_id)
|
||||||
else:
|
else:
|
||||||
soco.clear_queue()
|
soco.clear_queue()
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
"""Tests for the Sonos Media Player platform."""
|
"""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.const import STATE_IDLE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.device_registry import (
|
from homeassistant.helpers.device_registry import (
|
||||||
@ -8,6 +16,8 @@ from homeassistant.helpers.device_registry import (
|
|||||||
DeviceRegistry,
|
DeviceRegistry,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .conftest import SoCoMockFactory
|
||||||
|
|
||||||
|
|
||||||
async def test_device_registry(
|
async def test_device_registry(
|
||||||
hass: HomeAssistant, device_registry: DeviceRegistry, async_autosetup_sonos, soco
|
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["friendly_name"] == "Zone A"
|
||||||
assert attributes["is_volume_muted"] is False
|
assert attributes["is_volume_muted"] is False
|
||||||
assert attributes["volume_level"] == 0.19
|
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…
x
Reference in New Issue
Block a user