mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 15:47:12 +00:00
Recreate PR134142 after rebase conflicts
This commit is contained in:
parent
d1f0e0a70f
commit
d431e3ffee
@ -18,6 +18,8 @@ from homeassistant.components.media_player import (
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.network import is_internal_request
|
||||
|
||||
from .const import UNPLAYABLE_TYPES
|
||||
|
||||
LIBRARY = [
|
||||
"Favorites",
|
||||
"Artists",
|
||||
@ -26,6 +28,8 @@ LIBRARY = [
|
||||
"Playlists",
|
||||
"Genres",
|
||||
"New Music",
|
||||
"Apps",
|
||||
"Radios",
|
||||
]
|
||||
|
||||
MEDIA_TYPE_TO_SQUEEZEBOX = {
|
||||
@ -41,6 +45,9 @@ MEDIA_TYPE_TO_SQUEEZEBOX = {
|
||||
MediaType.TRACK: "title",
|
||||
MediaType.PLAYLIST: "playlist",
|
||||
MediaType.GENRE: "genre",
|
||||
MediaType.APPS: "apps",
|
||||
"Apps": "apps",
|
||||
"Radios": "radios",
|
||||
}
|
||||
|
||||
SQUEEZEBOX_ID_BY_TYPE = {
|
||||
@ -50,10 +57,14 @@ SQUEEZEBOX_ID_BY_TYPE = {
|
||||
MediaType.PLAYLIST: "playlist_id",
|
||||
MediaType.GENRE: "genre_id",
|
||||
"Favorites": "item_id",
|
||||
MediaType.APPS: "item_id",
|
||||
}
|
||||
|
||||
CONTENT_TYPE_MEDIA_CLASS: dict[str | MediaType, dict[str, MediaClass | None]] = {
|
||||
"Favorites": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
|
||||
"Apps": {"item": MediaClass.DIRECTORY, "children": MediaClass.APP},
|
||||
"Radios": {"item": MediaClass.DIRECTORY, "children": MediaClass.APP},
|
||||
"App": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
|
||||
"Artists": {"item": MediaClass.DIRECTORY, "children": MediaClass.ARTIST},
|
||||
"Albums": {"item": MediaClass.DIRECTORY, "children": MediaClass.ALBUM},
|
||||
"Tracks": {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
|
||||
@ -65,6 +76,8 @@ CONTENT_TYPE_MEDIA_CLASS: dict[str | MediaType, dict[str, MediaClass | None]] =
|
||||
MediaType.TRACK: {"item": MediaClass.TRACK, "children": None},
|
||||
MediaType.GENRE: {"item": MediaClass.GENRE, "children": MediaClass.ARTIST},
|
||||
MediaType.PLAYLIST: {"item": MediaClass.PLAYLIST, "children": MediaClass.TRACK},
|
||||
MediaType.APP: {"item": MediaClass.DIRECTORY, "children": MediaClass.TRACK},
|
||||
MediaType.APPS: {"item": MediaClass.DIRECTORY, "children": MediaClass.APP},
|
||||
}
|
||||
|
||||
CONTENT_TYPE_TO_CHILD_TYPE = {
|
||||
@ -78,9 +91,16 @@ CONTENT_TYPE_TO_CHILD_TYPE = {
|
||||
"Playlists": MediaType.PLAYLIST,
|
||||
"Genres": MediaType.GENRE,
|
||||
"Favorites": None, # can only be determined after inspecting the item
|
||||
"Apps": MediaClass.APP,
|
||||
"Radios": MediaClass.APP,
|
||||
"App": None, # can only be determined after inspecting the item
|
||||
"New Music": MediaType.ALBUM,
|
||||
MediaType.APPS: MediaType.APP,
|
||||
MediaType.APP: MediaType.TRACK,
|
||||
}
|
||||
|
||||
KNOWN_APPS: set[str | None] = set()
|
||||
|
||||
|
||||
async def build_item_response(
|
||||
entity: MediaPlayerEntity,
|
||||
@ -118,7 +138,7 @@ async def build_item_response(
|
||||
children = []
|
||||
list_playable = []
|
||||
for item in result["items"]:
|
||||
item_id = str(item["id"])
|
||||
item_id = str(item.get("id", ""))
|
||||
item_thumbnail: str | None = None
|
||||
if item_type:
|
||||
child_item_type: MediaType | str = item_type
|
||||
@ -144,6 +164,46 @@ async def build_item_response(
|
||||
can_expand = item["hasitems"]
|
||||
can_play = item["isaudio"] and item.get("url")
|
||||
|
||||
if search_type in ["Apps", "Radios"]:
|
||||
# item["cmd"] contains the name of the command to use with the cli for the app
|
||||
# add the command to the dictionaries
|
||||
if item["title"] == "Search" or item.get("type") in UNPLAYABLE_TYPES:
|
||||
# Skip searches in apps as they'd need UI or if the link isn't to audio
|
||||
continue
|
||||
_cmd = "app-" + item["cmd"]
|
||||
MEDIA_TYPE_TO_SQUEEZEBOX.update({_cmd: _cmd})
|
||||
SQUEEZEBOX_ID_BY_TYPE.update({_cmd: "item_id"})
|
||||
CONTENT_TYPE_MEDIA_CLASS.update(
|
||||
{
|
||||
_cmd: {
|
||||
"item": MediaClass.DIRECTORY,
|
||||
"children": MediaClass.TRACK,
|
||||
}
|
||||
}
|
||||
)
|
||||
CONTENT_TYPE_TO_CHILD_TYPE.update({_cmd: MediaType.TRACK})
|
||||
|
||||
if _cmd not in KNOWN_APPS:
|
||||
KNOWN_APPS.add(_cmd)
|
||||
|
||||
child_item_type = _cmd
|
||||
child_media_class = CONTENT_TYPE_MEDIA_CLASS[_cmd]
|
||||
can_expand = True
|
||||
can_play = False
|
||||
|
||||
if search_type in KNOWN_APPS:
|
||||
if (
|
||||
item.get("title") in ["Search", None]
|
||||
or item.get("type") in UNPLAYABLE_TYPES
|
||||
):
|
||||
# Skip searches in apps as they'd need UI
|
||||
continue
|
||||
|
||||
child_item_type = search_type
|
||||
child_media_class = CONTENT_TYPE_MEDIA_CLASS[search_type]
|
||||
can_play = item["isaudio"] and item.get("url")
|
||||
can_expand = item["hasitems"]
|
||||
|
||||
if artwork_track_id := item.get("artwork_track_id"):
|
||||
if internal_request:
|
||||
item_thumbnail = player.generate_image_url_from_track_id(
|
||||
@ -153,6 +213,8 @@ async def build_item_response(
|
||||
item_thumbnail = entity.get_browse_image_url(
|
||||
item_type, item_id, artwork_track_id
|
||||
)
|
||||
elif search_type in ["Apps", "Radios"]:
|
||||
item_thumbnail = player.generate_image_url(item["icon"])
|
||||
else:
|
||||
item_thumbnail = item.get("image_url") # will not be proxied by HA
|
||||
|
||||
@ -176,6 +238,7 @@ async def build_item_response(
|
||||
assert media_class["item"] is not None
|
||||
if not search_id:
|
||||
search_id = search_type
|
||||
|
||||
return BrowseMedia(
|
||||
title=result.get("title"),
|
||||
media_class=media_class["item"],
|
||||
@ -215,7 +278,7 @@ async def library_payload(hass: HomeAssistant, player: Player) -> BrowseMedia:
|
||||
media_class=media_class["children"],
|
||||
media_content_id=item,
|
||||
media_content_type=item,
|
||||
can_play=item != "Favorites",
|
||||
can_play=item not in ["Favorites", "Apps", "Radios"],
|
||||
can_expand=True,
|
||||
)
|
||||
)
|
||||
@ -251,8 +314,13 @@ async def generate_playlist(
|
||||
raise BrowseError(f"Media type not supported: {media_type}")
|
||||
|
||||
browse_id = (SQUEEZEBOX_ID_BY_TYPE[media_type], media_id)
|
||||
if media_type[:4] == "app-":
|
||||
category = media_type
|
||||
else:
|
||||
category = "titles"
|
||||
|
||||
result = await player.async_browse(
|
||||
"titles", limit=browse_limit, browse_id=browse_id
|
||||
category, limit=browse_limit, browse_id=browse_id
|
||||
)
|
||||
if result and "items" in result:
|
||||
items: list = result["items"]
|
||||
|
@ -27,7 +27,12 @@ STATUS_QUERY_LIBRARYNAME = "libraryname"
|
||||
STATUS_QUERY_MAC = "mac"
|
||||
STATUS_QUERY_UUID = "uuid"
|
||||
STATUS_QUERY_VERSION = "version"
|
||||
SQUEEZEBOX_SOURCE_STRINGS = ("source:", "wavin:", "spotify:")
|
||||
SQUEEZEBOX_SOURCE_STRINGS = (
|
||||
"source:",
|
||||
"wavin:",
|
||||
"spotify:",
|
||||
"loop:",
|
||||
)
|
||||
SIGNAL_PLAYER_DISCOVERED = "squeezebox_player_discovered"
|
||||
SIGNAL_PLAYER_REDISCOVERED = "squeezebox_player_rediscovered"
|
||||
DISCOVERY_INTERVAL = 60
|
||||
@ -36,5 +41,4 @@ CONF_BROWSE_LIMIT = "browse_limit"
|
||||
CONF_VOLUME_STEP = "volume_step"
|
||||
DEFAULT_BROWSE_LIMIT = 1000
|
||||
DEFAULT_VOLUME_STEP = 5
|
||||
ATTR_ANNOUNCE_VOLUME = "announce_volume"
|
||||
ATTR_ANNOUNCE_TIMEOUT = "announce_timeout"
|
||||
UNPLAYABLE_TYPES = ("text", "actions")
|
||||
|
@ -142,6 +142,9 @@ async def mock_async_browse(
|
||||
"title": "title",
|
||||
"playlists": "playlist",
|
||||
"playlist": "title",
|
||||
"apps": "app",
|
||||
"radios": "app",
|
||||
"app-fakecommand": "track",
|
||||
}
|
||||
fake_items = [
|
||||
{
|
||||
@ -152,6 +155,8 @@ async def mock_async_browse(
|
||||
"item_type": child_types[media_type],
|
||||
"artwork_track_id": "b35bb9e9",
|
||||
"url": "file:///var/lib/squeezeboxserver/music/track_1.mp3",
|
||||
"cmd": "fakecommand",
|
||||
"icon": "plugins/Qobuz/html/images/qobuz.png",
|
||||
},
|
||||
{
|
||||
"title": "Fake Item 2",
|
||||
@ -161,6 +166,8 @@ async def mock_async_browse(
|
||||
"item_type": child_types[media_type],
|
||||
"image_url": "http://lms.internal:9000/html/images/favorites.png",
|
||||
"url": "file:///var/lib/squeezeboxserver/music/track_2.mp3",
|
||||
"cmd": "fakecommand",
|
||||
"icon": "plugins/Qobuz/html/images/qobuz.png",
|
||||
},
|
||||
{
|
||||
"title": "Fake Item 3",
|
||||
@ -169,6 +176,8 @@ async def mock_async_browse(
|
||||
"isaudio": True,
|
||||
"album_id": FAKE_VALID_ITEM_ID if media_type == "favorites" else None,
|
||||
"url": "file:///var/lib/squeezeboxserver/music/track_3.mp3",
|
||||
"cmd": "fakecommand",
|
||||
"icon": "plugins/Qobuz/html/images/qobuz.png",
|
||||
},
|
||||
]
|
||||
|
||||
@ -232,6 +241,9 @@ def mock_pysqueezebox_player(uuid: str) -> MagicMock:
|
||||
mock_player.async_play_announcement = AsyncMock(
|
||||
side_effect=mock_async_play_announcement
|
||||
)
|
||||
mock_player.generate_image_url = MagicMock(
|
||||
return_value="http://lms.internal:9000/html/images/favorites.png"
|
||||
)
|
||||
mock_player.name = TEST_PLAYER_NAME
|
||||
mock_player.player_id = uuid
|
||||
mock_player.mode = "stop"
|
||||
|
@ -79,6 +79,8 @@ async def test_async_browse_media_with_subitems(
|
||||
"Playlists",
|
||||
"Genres",
|
||||
"New Music",
|
||||
"Apps",
|
||||
"Radios",
|
||||
):
|
||||
with patch(
|
||||
"homeassistant.components.squeezebox.browse_media.is_internal_request",
|
||||
|
Loading…
x
Reference in New Issue
Block a user