mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 00:37:53 +00:00
Adds media_browser functionality to the music assistant integration (#131577)
* Add test fixtures for all library loading * Add media browser * Add tests for media_browser
This commit is contained in:
parent
f04c50c59e
commit
40a4ff1c84
351
homeassistant/components/music_assistant/media_browser.py
Normal file
351
homeassistant/components/music_assistant/media_browser.py
Normal file
@ -0,0 +1,351 @@
|
||||
"""Media Source Implementation."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from music_assistant_models.media_items import MediaItemType
|
||||
|
||||
from homeassistant.components import media_source
|
||||
from homeassistant.components.media_player import (
|
||||
BrowseError,
|
||||
BrowseMedia,
|
||||
MediaClass,
|
||||
MediaType,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import DEFAULT_NAME, DOMAIN
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from music_assistant_client import MusicAssistantClient
|
||||
|
||||
MEDIA_TYPE_RADIO = "radio"
|
||||
|
||||
PLAYABLE_MEDIA_TYPES = [
|
||||
MediaType.PLAYLIST,
|
||||
MediaType.ALBUM,
|
||||
MediaType.ARTIST,
|
||||
MEDIA_TYPE_RADIO,
|
||||
MediaType.TRACK,
|
||||
]
|
||||
|
||||
LIBRARY_ARTISTS = "artists"
|
||||
LIBRARY_ALBUMS = "albums"
|
||||
LIBRARY_TRACKS = "tracks"
|
||||
LIBRARY_PLAYLISTS = "playlists"
|
||||
LIBRARY_RADIO = "radio"
|
||||
|
||||
|
||||
LIBRARY_TITLE_MAP = {
|
||||
LIBRARY_ARTISTS: "Artists",
|
||||
LIBRARY_ALBUMS: "Albums",
|
||||
LIBRARY_TRACKS: "Tracks",
|
||||
LIBRARY_PLAYLISTS: "Playlists",
|
||||
LIBRARY_RADIO: "Radio stations",
|
||||
}
|
||||
|
||||
LIBRARY_MEDIA_CLASS_MAP = {
|
||||
LIBRARY_ARTISTS: MediaClass.ARTIST,
|
||||
LIBRARY_ALBUMS: MediaClass.ALBUM,
|
||||
LIBRARY_TRACKS: MediaClass.TRACK,
|
||||
LIBRARY_PLAYLISTS: MediaClass.PLAYLIST,
|
||||
LIBRARY_RADIO: MediaClass.MUSIC, # radio is not accepted by HA
|
||||
}
|
||||
|
||||
MEDIA_CONTENT_TYPE_FLAC = "audio/flac"
|
||||
THUMB_SIZE = 200
|
||||
|
||||
|
||||
def media_source_filter(item: BrowseMedia) -> bool:
|
||||
"""Filter media sources."""
|
||||
return item.media_content_type.startswith("audio/")
|
||||
|
||||
|
||||
async def async_browse_media(
|
||||
hass: HomeAssistant,
|
||||
mass: MusicAssistantClient,
|
||||
media_content_id: str | None,
|
||||
media_content_type: str | None,
|
||||
) -> BrowseMedia:
|
||||
"""Browse media."""
|
||||
if media_content_id is None:
|
||||
return await build_main_listing(hass)
|
||||
|
||||
assert media_content_type is not None
|
||||
|
||||
if media_source.is_media_source_id(media_content_id):
|
||||
return await media_source.async_browse_media(
|
||||
hass, media_content_id, content_filter=media_source_filter
|
||||
)
|
||||
|
||||
if media_content_id == LIBRARY_ARTISTS:
|
||||
return await build_artists_listing(mass)
|
||||
if media_content_id == LIBRARY_ALBUMS:
|
||||
return await build_albums_listing(mass)
|
||||
if media_content_id == LIBRARY_TRACKS:
|
||||
return await build_tracks_listing(mass)
|
||||
if media_content_id == LIBRARY_PLAYLISTS:
|
||||
return await build_playlists_listing(mass)
|
||||
if media_content_id == LIBRARY_RADIO:
|
||||
return await build_radio_listing(mass)
|
||||
if "artist" in media_content_id:
|
||||
return await build_artist_items_listing(mass, media_content_id)
|
||||
if "album" in media_content_id:
|
||||
return await build_album_items_listing(mass, media_content_id)
|
||||
if "playlist" in media_content_id:
|
||||
return await build_playlist_items_listing(mass, media_content_id)
|
||||
|
||||
raise BrowseError(f"Media not found: {media_content_type} / {media_content_id}")
|
||||
|
||||
|
||||
async def build_main_listing(hass: HomeAssistant) -> BrowseMedia:
|
||||
"""Build main browse listing."""
|
||||
children: list[BrowseMedia] = []
|
||||
for library, media_class in LIBRARY_MEDIA_CLASS_MAP.items():
|
||||
child_source = BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=library,
|
||||
media_content_type=DOMAIN,
|
||||
title=LIBRARY_TITLE_MAP[library],
|
||||
children_media_class=media_class,
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
)
|
||||
children.append(child_source)
|
||||
|
||||
try:
|
||||
item = await media_source.async_browse_media(
|
||||
hass, None, content_filter=media_source_filter
|
||||
)
|
||||
# If domain is None, it's overview of available sources
|
||||
if item.domain is None and item.children is not None:
|
||||
children.extend(item.children)
|
||||
else:
|
||||
children.append(item)
|
||||
except media_source.BrowseError:
|
||||
pass
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id="",
|
||||
media_content_type=DOMAIN,
|
||||
title=DEFAULT_NAME,
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children=children,
|
||||
)
|
||||
|
||||
|
||||
async def build_playlists_listing(mass: MusicAssistantClient) -> BrowseMedia:
|
||||
"""Build Playlists browse listing."""
|
||||
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_PLAYLISTS]
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=LIBRARY_PLAYLISTS,
|
||||
media_content_type=MediaType.PLAYLIST,
|
||||
title=LIBRARY_TITLE_MAP[LIBRARY_PLAYLISTS],
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=media_class,
|
||||
children=sorted(
|
||||
[
|
||||
build_item(mass, item, can_expand=True)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for item in await mass.music.get_library_playlists(limit=500)
|
||||
if item.available
|
||||
],
|
||||
key=lambda x: x.title,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def build_playlist_items_listing(
|
||||
mass: MusicAssistantClient, identifier: str
|
||||
) -> BrowseMedia:
|
||||
"""Build Playlist items browse listing."""
|
||||
playlist = await mass.music.get_item_by_uri(identifier)
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.PLAYLIST,
|
||||
media_content_id=playlist.uri,
|
||||
media_content_type=MediaType.PLAYLIST,
|
||||
title=playlist.name,
|
||||
can_play=True,
|
||||
can_expand=True,
|
||||
children_media_class=MediaClass.TRACK,
|
||||
children=[
|
||||
build_item(mass, item, can_expand=False)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for item in await mass.music.get_playlist_tracks(
|
||||
playlist.item_id, playlist.provider
|
||||
)
|
||||
if item.available
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
async def build_artists_listing(mass: MusicAssistantClient) -> BrowseMedia:
|
||||
"""Build Albums browse listing."""
|
||||
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_ARTISTS]
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=LIBRARY_ARTISTS,
|
||||
media_content_type=MediaType.ARTIST,
|
||||
title=LIBRARY_TITLE_MAP[LIBRARY_ARTISTS],
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=media_class,
|
||||
children=sorted(
|
||||
[
|
||||
build_item(mass, artist, can_expand=True)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for artist in await mass.music.get_library_artists(limit=500)
|
||||
if artist.available
|
||||
],
|
||||
key=lambda x: x.title,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def build_artist_items_listing(
|
||||
mass: MusicAssistantClient, identifier: str
|
||||
) -> BrowseMedia:
|
||||
"""Build Artist items browse listing."""
|
||||
artist = await mass.music.get_item_by_uri(identifier)
|
||||
albums = await mass.music.get_artist_albums(artist.item_id, artist.provider)
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaType.ARTIST,
|
||||
media_content_id=artist.uri,
|
||||
media_content_type=MediaType.ARTIST,
|
||||
title=artist.name,
|
||||
can_play=True,
|
||||
can_expand=True,
|
||||
children_media_class=MediaClass.ALBUM,
|
||||
children=[
|
||||
build_item(mass, album, can_expand=True)
|
||||
for album in albums
|
||||
if album.available
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
async def build_albums_listing(mass: MusicAssistantClient) -> BrowseMedia:
|
||||
"""Build Albums browse listing."""
|
||||
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_ALBUMS]
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=LIBRARY_ALBUMS,
|
||||
media_content_type=MediaType.ALBUM,
|
||||
title=LIBRARY_TITLE_MAP[LIBRARY_ALBUMS],
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=media_class,
|
||||
children=sorted(
|
||||
[
|
||||
build_item(mass, album, can_expand=True)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for album in await mass.music.get_library_albums(limit=500)
|
||||
if album.available
|
||||
],
|
||||
key=lambda x: x.title,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def build_album_items_listing(
|
||||
mass: MusicAssistantClient, identifier: str
|
||||
) -> BrowseMedia:
|
||||
"""Build Album items browse listing."""
|
||||
album = await mass.music.get_item_by_uri(identifier)
|
||||
tracks = await mass.music.get_album_tracks(album.item_id, album.provider)
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaType.ALBUM,
|
||||
media_content_id=album.uri,
|
||||
media_content_type=MediaType.ALBUM,
|
||||
title=album.name,
|
||||
can_play=True,
|
||||
can_expand=True,
|
||||
children_media_class=MediaClass.TRACK,
|
||||
children=[
|
||||
build_item(mass, track, False) for track in tracks if track.available
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
async def build_tracks_listing(mass: MusicAssistantClient) -> BrowseMedia:
|
||||
"""Build Tracks browse listing."""
|
||||
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_TRACKS]
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=LIBRARY_TRACKS,
|
||||
media_content_type=MediaType.TRACK,
|
||||
title=LIBRARY_TITLE_MAP[LIBRARY_TRACKS],
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=media_class,
|
||||
children=sorted(
|
||||
[
|
||||
build_item(mass, track, can_expand=False)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for track in await mass.music.get_library_tracks(limit=500)
|
||||
if track.available
|
||||
],
|
||||
key=lambda x: x.title,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def build_radio_listing(mass: MusicAssistantClient) -> BrowseMedia:
|
||||
"""Build Radio browse listing."""
|
||||
media_class = LIBRARY_MEDIA_CLASS_MAP[LIBRARY_RADIO]
|
||||
return BrowseMedia(
|
||||
media_class=MediaClass.DIRECTORY,
|
||||
media_content_id=LIBRARY_RADIO,
|
||||
media_content_type=DOMAIN,
|
||||
title=LIBRARY_TITLE_MAP[LIBRARY_RADIO],
|
||||
can_play=False,
|
||||
can_expand=True,
|
||||
children_media_class=media_class,
|
||||
children=[
|
||||
build_item(mass, track, can_expand=False, media_class=media_class)
|
||||
# we only grab the first page here because the
|
||||
# HA media browser does not support paging
|
||||
for track in await mass.music.get_library_radios(limit=500)
|
||||
if track.available
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def build_item(
|
||||
mass: MusicAssistantClient,
|
||||
item: MediaItemType,
|
||||
can_expand: bool = True,
|
||||
media_class: Any = None,
|
||||
) -> BrowseMedia:
|
||||
"""Return BrowseMedia for MediaItem."""
|
||||
if artists := getattr(item, "artists", None):
|
||||
title = f"{artists[0].name} - {item.name}"
|
||||
else:
|
||||
title = item.name
|
||||
img_url = mass.get_media_item_image_url(item)
|
||||
|
||||
return BrowseMedia(
|
||||
media_class=media_class or item.media_type.value,
|
||||
media_content_id=item.uri,
|
||||
media_content_type=MediaType.MUSIC,
|
||||
title=title,
|
||||
can_play=True,
|
||||
can_expand=can_expand,
|
||||
thumbnail=img_url,
|
||||
)
|
@ -43,6 +43,7 @@ from homeassistant.util.dt import utc_from_timestamp
|
||||
from . import MusicAssistantConfigEntry
|
||||
from .const import ATTR_ACTIVE_QUEUE, ATTR_MASS_PLAYER_TYPE, DOMAIN
|
||||
from .entity import MusicAssistantEntity
|
||||
from .media_browser import async_browse_media
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from music_assistant_client import MusicAssistantClient
|
||||
@ -440,10 +441,11 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity):
|
||||
media_content_id: str | None = None,
|
||||
) -> BrowseMedia:
|
||||
"""Implement the websocket media browsing helper."""
|
||||
return await media_source.async_browse_media(
|
||||
return await async_browse_media(
|
||||
self.hass,
|
||||
self.mass,
|
||||
media_content_id,
|
||||
content_filter=lambda item: item.media_content_type.startswith("audio/"),
|
||||
media_content_type,
|
||||
)
|
||||
|
||||
def _update_media_image_url(
|
||||
|
@ -3,9 +3,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
from unittest.mock import MagicMock
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
from music_assistant_models.enums import EventType
|
||||
from music_assistant_models.media_items import Album, Artist, Playlist, Radio, Track
|
||||
from music_assistant_models.player import Player
|
||||
from music_assistant_models.player_queue import PlayerQueue
|
||||
from syrupy import SnapshotAssertion
|
||||
@ -42,6 +43,25 @@ async def setup_integration_from_fixtures(
|
||||
data={"url": MOCK_URL},
|
||||
unique_id=music_assistant_client.server_info.server_id,
|
||||
)
|
||||
music = music_assistant_client.music
|
||||
library_artists = create_library_artists_from_fixture()
|
||||
music.get_library_artists = AsyncMock(return_value=library_artists)
|
||||
library_artist_albums = create_library_artist_albums_from_fixture()
|
||||
music.get_artist_albums = AsyncMock(return_value=library_artist_albums)
|
||||
library_albums = create_library_albums_from_fixture()
|
||||
music.get_library_albums = AsyncMock(return_value=library_albums)
|
||||
library_album_tracks = create_library_album_tracks_from_fixture()
|
||||
music.get_album_tracks = AsyncMock(return_value=library_album_tracks)
|
||||
library_tracks = create_library_tracks_from_fixture()
|
||||
music.get_library_tracks = AsyncMock(return_value=library_tracks)
|
||||
library_playlists = create_library_playlists_from_fixture()
|
||||
music.get_library_playlists = AsyncMock(return_value=library_playlists)
|
||||
library_playlist_tracks = create_library_playlist_tracks_from_fixture()
|
||||
music.get_playlist_tracks = AsyncMock(return_value=library_playlist_tracks)
|
||||
library_radios = create_library_radios_from_fixture()
|
||||
music.get_library_radios = AsyncMock(return_value=library_radios)
|
||||
music.get_item_by_uri = AsyncMock()
|
||||
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
@ -61,6 +81,54 @@ def create_player_queues_from_fixture() -> list[Player]:
|
||||
]
|
||||
|
||||
|
||||
def create_library_albums_from_fixture() -> list[Album]:
|
||||
"""Create MA Albums from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_albums")
|
||||
return [Album.from_dict(album_data) for album_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_album_tracks_from_fixture() -> list[Track]:
|
||||
"""Create MA Tracks from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_album_tracks")
|
||||
return [Track.from_dict(track_data) for track_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_tracks_from_fixture() -> list[Track]:
|
||||
"""Create MA Tracks from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_tracks")
|
||||
return [Track.from_dict(track_data) for track_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_artists_from_fixture() -> list[Artist]:
|
||||
"""Create MA Artists from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_artists")
|
||||
return [Artist.from_dict(artist_data) for artist_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_artist_albums_from_fixture() -> list[Album]:
|
||||
"""Create MA Albums from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_artist_albums")
|
||||
return [Album.from_dict(album_data) for album_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_playlists_from_fixture() -> list[Playlist]:
|
||||
"""Create MA Playlists from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_playlists")
|
||||
return [Playlist.from_dict(playlist_data) for playlist_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_playlist_tracks_from_fixture() -> list[Track]:
|
||||
"""Create MA Tracks from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_playlist_tracks")
|
||||
return [Track.from_dict(track_data) for track_data in fixture_data]
|
||||
|
||||
|
||||
def create_library_radios_from_fixture() -> list[Radio]:
|
||||
"""Create MA Radios from fixture."""
|
||||
fixture_data = load_and_parse_fixture("library_radios")
|
||||
return [Radio.from_dict(radio_data) for radio_data in fixture_data]
|
||||
|
||||
|
||||
async def trigger_subscription_callback(
|
||||
hass: HomeAssistant,
|
||||
client: MagicMock,
|
||||
|
@ -0,0 +1,364 @@
|
||||
{
|
||||
"library_album_tracks": [
|
||||
{
|
||||
"item_id": "247",
|
||||
"provider": "library",
|
||||
"name": "Le Mirage",
|
||||
"version": "",
|
||||
"sort_name": "mirage, le",
|
||||
"uri": "library://track/247",
|
||||
"external_ids": [["isrc", "FR10S1794640"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "70953631",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--63Pkq9Aw",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/70953631",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "Dana Murray",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 35,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 352,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 195,
|
||||
"provider": "library",
|
||||
"name": "Dana Jean Phoenix",
|
||||
"version": "",
|
||||
"sort_name": "dana jean phoenix",
|
||||
"uri": "library://artist/195",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 95,
|
||||
"provider": "library",
|
||||
"name": "Synthwave (The 80S Revival)",
|
||||
"version": "",
|
||||
"sort_name": "synthwave (the 80s revival)",
|
||||
"uri": "library://album/95",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 1
|
||||
},
|
||||
{
|
||||
"item_id": "362",
|
||||
"provider": "library",
|
||||
"name": "Rabbit in the Headlights",
|
||||
"version": "",
|
||||
"sort_name": "rabbit in the headlights",
|
||||
"uri": "library://track/362",
|
||||
"external_ids": [["isrc", "GBLFP1645070"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "70953636",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/70953636",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "Michael Oakley",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 34,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 253,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 90,
|
||||
"provider": "library",
|
||||
"name": "Michael Oakley",
|
||||
"version": "",
|
||||
"sort_name": "michael oakley",
|
||||
"uri": "library://artist/90",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 95,
|
||||
"provider": "library",
|
||||
"name": "Synthwave (The 80S Revival)",
|
||||
"version": "",
|
||||
"sort_name": "synthwave (the 80s revival)",
|
||||
"uri": "library://album/95",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 6
|
||||
},
|
||||
{
|
||||
"item_id": "1",
|
||||
"provider": "library",
|
||||
"name": "1988 Girls",
|
||||
"version": "",
|
||||
"sort_name": "1988 girls",
|
||||
"uri": "library://track/1",
|
||||
"external_ids": [["isrc", "DEBL60768604"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "70953637",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--56X5qDS7",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/70953637",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "Kiez Beats",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 14,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 258,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 110,
|
||||
"provider": "library",
|
||||
"name": "Futurecop!",
|
||||
"version": "",
|
||||
"sort_name": "futurecop!",
|
||||
"uri": "library://artist/110",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 95,
|
||||
"provider": "library",
|
||||
"name": "Synthwave (The 80S Revival)",
|
||||
"version": "",
|
||||
"sort_name": "synthwave (the 80s revival)",
|
||||
"uri": "library://album/95",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 7
|
||||
},
|
||||
{
|
||||
"item_id": "495",
|
||||
"provider": "library",
|
||||
"name": "Timmy Goes to Space",
|
||||
"version": "",
|
||||
"sort_name": "timmy goes to space",
|
||||
"uri": "library://track/495",
|
||||
"external_ids": [["isrc", "NO2D81710001"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "70953643",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/70953643",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "Jens Kristian Espevik",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 4,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 212,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 453,
|
||||
"provider": "library",
|
||||
"name": "Mr. Maen",
|
||||
"version": "",
|
||||
"sort_name": "mr. maen",
|
||||
"uri": "library://artist/453",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 95,
|
||||
"provider": "library",
|
||||
"name": "Synthwave (The 80S Revival)",
|
||||
"version": "",
|
||||
"sort_name": "synthwave (the 80s revival)",
|
||||
"uri": "library://album/95",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 13
|
||||
}
|
||||
]
|
||||
}
|
148
tests/components/music_assistant/fixtures/library_albums.json
Normal file
148
tests/components/music_assistant/fixtures/library_albums.json
Normal file
@ -0,0 +1,148 @@
|
||||
{
|
||||
"library_albums": [
|
||||
{
|
||||
"item_id": "396",
|
||||
"provider": "library",
|
||||
"name": "Synth Punk EP",
|
||||
"version": "",
|
||||
"sort_name": "synth punk ep",
|
||||
"uri": "library://album/396",
|
||||
"external_ids": [["barcode", "872133626743"]],
|
||||
"media_type": "album",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "48563817",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/album/48563817",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/99c8bc2f/ed43/4fb2/adfb/e7e3157089d2/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "586446 Records DK",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 7,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null,
|
||||
"year": 2015,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 289,
|
||||
"provider": "library",
|
||||
"name": "A Space Love Adventure",
|
||||
"version": "",
|
||||
"sort_name": "space love adventure, a",
|
||||
"uri": "library://artist/289",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album_type": "ep"
|
||||
},
|
||||
{
|
||||
"item_id": "95",
|
||||
"provider": "library",
|
||||
"name": "Synthwave (The 80S Revival)",
|
||||
"version": "The 80S Revival",
|
||||
"sort_name": "synthwave (the 80s revival)",
|
||||
"uri": "library://album/95",
|
||||
"external_ids": [["barcode", "3614974086112"]],
|
||||
"media_type": "album",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "70953630",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--56X5qDS7",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/album/70953630",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/b7b1897c/57ed/4a31/83d7/9ab3df83183a/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "Kiez Beats",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 43,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null,
|
||||
"year": 2017,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 96,
|
||||
"provider": "library",
|
||||
"name": "Various Artists",
|
||||
"version": "",
|
||||
"sort_name": "various artists",
|
||||
"uri": "library://artist/96",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album_type": "compilation"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
{
|
||||
"library_artist_albums": [
|
||||
{
|
||||
"item_id": "115",
|
||||
"provider": "library",
|
||||
"name": "A Sea of Stars",
|
||||
"version": "",
|
||||
"sort_name": "sea of stars, a",
|
||||
"uri": "library://album/115",
|
||||
"external_ids": [["barcode", "859741010126"]],
|
||||
"media_type": "album",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "157401232",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--56X5qDS7",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/album/157401232",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/f55c749b/6642/40e3/a291/ff01fd2915cf/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "2021 NRW Records, under exclusive license to NewRetroWave, LLC",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 0,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null,
|
||||
"year": 2021,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 127,
|
||||
"provider": "library",
|
||||
"name": "W O L F C L U B",
|
||||
"version": "",
|
||||
"sort_name": "w o l f c l u b",
|
||||
"uri": "library://artist/127",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
},
|
||||
{
|
||||
"item_id": 128,
|
||||
"provider": "library",
|
||||
"name": "Dora Pereli",
|
||||
"version": "",
|
||||
"sort_name": "dora pereli",
|
||||
"uri": "library://artist/128",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album_type": "single"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
{
|
||||
"library_artists": [
|
||||
{
|
||||
"item_id": "127",
|
||||
"provider": "library",
|
||||
"name": "W O L F C L U B",
|
||||
"version": "",
|
||||
"sort_name": "w o l f c l u b",
|
||||
"uri": "library://artist/127",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "8741977",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--56X5qDS7",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "?",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "?",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/artist/8741977",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": null,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/1e01cdb6/f15d/4d8b/8440/a047976c1cac/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": null,
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": null,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
{
|
||||
"library_playlist_tracks": [
|
||||
{
|
||||
"item_id": "77616130",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "Won't Get Fooled Again",
|
||||
"version": "",
|
||||
"sort_name": "won't get fooled again",
|
||||
"uri": "tidal--Ah76MuMg://track/77616130",
|
||||
"external_ids": [["isrc", "GBUM71405419"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "77616130",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": true,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 24,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/77616130",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/3496a8ad/ea69/4d7e/bbda/045417ab59e1/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 1971 Polydor Ltd. (UK)",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 30,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": 0,
|
||||
"duration": 516,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": "24915",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "The Who",
|
||||
"version": "",
|
||||
"sort_name": "who, the",
|
||||
"uri": "tidal--Ah76MuMg://artist/24915",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "24915",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": true,
|
||||
"audio_format": {
|
||||
"content_type": "?",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "?",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/artist/24915",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": null,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/0f782232/18c8/40b7/bb13/91c6039e40e6/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": null,
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": null,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": "77616121",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "Who's Next",
|
||||
"version": "",
|
||||
"sort_name": "who's next",
|
||||
"uri": "tidal--Ah76MuMg://album/77616121",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": null
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 9
|
||||
},
|
||||
{
|
||||
"item_id": "153795",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "We're An American Band",
|
||||
"version": "Remastered 2002",
|
||||
"sort_name": "we're an american band",
|
||||
"uri": "tidal--Ah76MuMg://track/153795",
|
||||
"external_ids": [["isrc", "USCA20200334"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "153795",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": true,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/153795",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/a6d86e02/84c1/41f7/84f5/41be8571fc40/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2002 Capitol Records, LLC",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 48,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": 1,
|
||||
"duration": 207,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": "9380",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "Grand Funk Railroad",
|
||||
"version": "",
|
||||
"sort_name": "grand funk railroad",
|
||||
"uri": "tidal--Ah76MuMg://artist/9380",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "9380",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": true,
|
||||
"audio_format": {
|
||||
"content_type": "?",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "?",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/artist/9380",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": null,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/6535bf95/a06d/4d23/8262/604fa41d8126/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": null,
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": null,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": false,
|
||||
"position": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": "153794",
|
||||
"provider": "tidal--Ah76MuMg",
|
||||
"name": "We're An American Band (Expanded Edition / Remastered 2002)",
|
||||
"version": "",
|
||||
"sort_name": "we're an american band (expanded edition / remastered 2002)",
|
||||
"uri": "tidal--Ah76MuMg://album/153794",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": null
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 1
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
{
|
||||
"library_playlists": [
|
||||
{
|
||||
"item_id": "40",
|
||||
"provider": "library",
|
||||
"name": "1970s Rock Hits",
|
||||
"version": "",
|
||||
"sort_name": "1970s rock hits",
|
||||
"uri": "library://playlist/40",
|
||||
"external_ids": [],
|
||||
"media_type": "playlist",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "30da0578-0ca0-4716-b66e-5f02bcd96702",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "?",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "?",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/browse/playlist/30da0578-0ca0-4716-b66e-5f02bcd96702",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": null,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/95913801/41c1/4cc9/bf94/a0fba657bba5/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": null,
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": null,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"owner": "TIDAL",
|
||||
"is_editable": 0,
|
||||
"cache_checksum": "2023-10-09 07: 09: 23.446000+00: 00"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
{
|
||||
"library_radios": [
|
||||
{
|
||||
"item_id": "1",
|
||||
"provider": "library",
|
||||
"name": "fm4 | ORF | HQ",
|
||||
"version": "",
|
||||
"sort_name": "fm4 | orf | hq",
|
||||
"uri": "library://radio/1",
|
||||
"external_ids": [],
|
||||
"media_type": "radio",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "1e13ed4e-daa9-4728-8550-e08d89c1c8e7",
|
||||
"provider_domain": "radiobrowser",
|
||||
"provider_instance": "radiobrowser--FRc3pD3t",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "?",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "?",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": null,
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": null,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://tubestatic.orf.at/mojo/1_3/storyserver//tube/fm4/images/touch-icon-iphone-retina.png",
|
||||
"provider": "radiobrowser",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": null,
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": [
|
||||
{
|
||||
"type": "website",
|
||||
"url": "https://fm4.orf.at/"
|
||||
}
|
||||
],
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 166,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 172800
|
||||
}
|
||||
]
|
||||
}
|
556
tests/components/music_assistant/fixtures/library_tracks.json
Normal file
556
tests/components/music_assistant/fixtures/library_tracks.json
Normal file
@ -0,0 +1,556 @@
|
||||
{
|
||||
"library_tracks": [
|
||||
{
|
||||
"item_id": "456",
|
||||
"provider": "library",
|
||||
"name": "Tennessee Whiskey",
|
||||
"version": "",
|
||||
"sort_name": "tennessee whiskey",
|
||||
"uri": "library://track/456",
|
||||
"external_ids": [["isrc", "USUM71418088"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "44832786",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/44832786",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/4894ff62/9de2/4ed8/a7b9/69e217bbbdda/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2015 Mercury Records, a Division of UMG Recordings, Inc.",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 33,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 293,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 433,
|
||||
"provider": "library",
|
||||
"name": "Chris Stapleton",
|
||||
"version": "",
|
||||
"sort_name": "chris stapleton",
|
||||
"uri": "library://artist/433",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 463,
|
||||
"provider": "library",
|
||||
"name": "Traveller",
|
||||
"version": "",
|
||||
"sort_name": "traveller",
|
||||
"uri": "library://album/463",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/4894ff62/9de2/4ed8/a7b9/69e217bbbdda/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 3
|
||||
},
|
||||
{
|
||||
"item_id": "467",
|
||||
"provider": "library",
|
||||
"name": "Thelma + Louise",
|
||||
"version": "",
|
||||
"sort_name": "thelma + louise",
|
||||
"uri": "library://track/467",
|
||||
"external_ids": [["isrc", "GBUM72104380"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "194027388",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 24,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/194027388",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/04fc7c3c/b814/4855/874c/a2e456205b65/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2021 Virgin Records Limited",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 20,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 137,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 81,
|
||||
"provider": "library",
|
||||
"name": "Bastille",
|
||||
"version": "",
|
||||
"sort_name": "bastille",
|
||||
"uri": "library://artist/81",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 471,
|
||||
"provider": "library",
|
||||
"name": "Thelma + Louise",
|
||||
"version": "",
|
||||
"sort_name": "thelma + louise",
|
||||
"uri": "library://album/471",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/04fc7c3c/b814/4855/874c/a2e456205b65/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 1
|
||||
},
|
||||
{
|
||||
"item_id": "485",
|
||||
"provider": "library",
|
||||
"name": "They Don't Care About Us",
|
||||
"version": "",
|
||||
"sort_name": "they don't care about us",
|
||||
"uri": "library://track/485",
|
||||
"external_ids": [["isrc", "USSM19500629"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "5279069",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 24,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/5279069",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/a2fa5815/851d/4d2d/b6a7/17a365c838f9/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "(P) 1995 MJJ Productions Inc.",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 27,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 284,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 30,
|
||||
"provider": "library",
|
||||
"name": "Michael Jackson",
|
||||
"version": "",
|
||||
"sort_name": "michael jackson",
|
||||
"uri": "library://artist/30",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 486,
|
||||
"provider": "library",
|
||||
"name": "HIStory - PAST, PRESENT AND FUTURE - BOOK I",
|
||||
"version": "",
|
||||
"sort_name": "history - past, present and future - book i",
|
||||
"uri": "library://album/486",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/a2fa5815/851d/4d2d/b6a7/17a365c838f9/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 2,
|
||||
"track_number": 2
|
||||
},
|
||||
{
|
||||
"item_id": "486",
|
||||
"provider": "library",
|
||||
"name": "They Don't Give A F**** About Us",
|
||||
"version": "",
|
||||
"sort_name": "they don't give a f**** about us",
|
||||
"uri": "library://track/486",
|
||||
"external_ids": [["isrc", "USIR10211795"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "44066854",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/44066854",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": true,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/6b7b2b58/5dc2/4d0c/8979/7b30bb779d6f/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2002 Amaru Entertainment, Inc., Under exclusive license to Interscope Records",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 34,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 306,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 159,
|
||||
"provider": "library",
|
||||
"name": "2Pac",
|
||||
"version": "",
|
||||
"sort_name": "2pac",
|
||||
"uri": "library://artist/159",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
},
|
||||
{
|
||||
"item_id": 451,
|
||||
"provider": "library",
|
||||
"name": "The Outlawz",
|
||||
"version": "",
|
||||
"sort_name": "outlawz, the",
|
||||
"uri": "library://artist/451",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 487,
|
||||
"provider": "library",
|
||||
"name": "Better Dayz",
|
||||
"version": "",
|
||||
"sort_name": "better dayz",
|
||||
"uri": "library://album/487",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/6b7b2b58/5dc2/4d0c/8979/7b30bb779d6f/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 2,
|
||||
"track_number": 13
|
||||
},
|
||||
{
|
||||
"item_id": "487",
|
||||
"provider": "library",
|
||||
"name": "Things We Lost In The Fire",
|
||||
"version": "TORN Remix",
|
||||
"sort_name": "things we lost in the fire",
|
||||
"uri": "library://track/487",
|
||||
"external_ids": [["isrc", "GBUM71304903"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "22627902",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 16,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/22627902",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/de277fd3/cc29/4d63/a60f/13b501c5f3d0/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2013 Virgin Records Limited",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 10,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 323,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 81,
|
||||
"provider": "library",
|
||||
"name": "Bastille",
|
||||
"version": "",
|
||||
"sort_name": "bastille",
|
||||
"uri": "library://artist/81",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 488,
|
||||
"provider": "library",
|
||||
"name": "Things We Lost In The Fire",
|
||||
"version": "",
|
||||
"sort_name": "things we lost in the fire",
|
||||
"uri": "library://album/488",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/de277fd3/cc29/4d63/a60f/13b501c5f3d0/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 3
|
||||
},
|
||||
{
|
||||
"item_id": "488",
|
||||
"provider": "library",
|
||||
"name": "Those Nights",
|
||||
"version": "",
|
||||
"sort_name": "those nights",
|
||||
"uri": "library://track/488",
|
||||
"external_ids": [["isrc", "GBUM71803866"]],
|
||||
"media_type": "track",
|
||||
"provider_mappings": [
|
||||
{
|
||||
"item_id": "110750762",
|
||||
"provider_domain": "tidal",
|
||||
"provider_instance": "tidal--Ah76MuMg",
|
||||
"available": 1,
|
||||
"audio_format": {
|
||||
"content_type": "flac",
|
||||
"sample_rate": 44100,
|
||||
"bit_depth": 24,
|
||||
"channels": 2,
|
||||
"output_format_str": "flac",
|
||||
"bit_rate": 0
|
||||
},
|
||||
"url": "https://tidal.com/track/110750762",
|
||||
"details": null
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"description": null,
|
||||
"review": null,
|
||||
"explicit": false,
|
||||
"images": [
|
||||
{
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/713805f3/c08c/4c0f/8199/d63e6badac0d/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
],
|
||||
"genres": null,
|
||||
"mood": null,
|
||||
"style": null,
|
||||
"copyright": "℗ 2019 Virgin Records Limited",
|
||||
"lyrics": null,
|
||||
"label": null,
|
||||
"links": null,
|
||||
"performers": null,
|
||||
"preview": null,
|
||||
"popularity": 21,
|
||||
"release_date": null,
|
||||
"languages": null,
|
||||
"last_refresh": null
|
||||
},
|
||||
"favorite": true,
|
||||
"position": null,
|
||||
"duration": 270,
|
||||
"artists": [
|
||||
{
|
||||
"item_id": 81,
|
||||
"provider": "library",
|
||||
"name": "Bastille",
|
||||
"version": "",
|
||||
"sort_name": "bastille",
|
||||
"uri": "library://artist/81",
|
||||
"external_ids": [],
|
||||
"media_type": "artist",
|
||||
"available": true,
|
||||
"image": null
|
||||
}
|
||||
],
|
||||
"album": {
|
||||
"item_id": 489,
|
||||
"provider": "library",
|
||||
"name": "Doom Days",
|
||||
"version": "",
|
||||
"sort_name": "doom days",
|
||||
"uri": "library://album/489",
|
||||
"external_ids": [],
|
||||
"media_type": "album",
|
||||
"available": true,
|
||||
"image": {
|
||||
"type": "thumb",
|
||||
"path": "https://resources.tidal.com/images/713805f3/c08c/4c0f/8199/d63e6badac0d/750x750.jpg",
|
||||
"provider": "tidal",
|
||||
"remotely_accessible": true
|
||||
}
|
||||
},
|
||||
"disc_number": 1,
|
||||
"track_number": 10
|
||||
}
|
||||
]
|
||||
}
|
65
tests/components/music_assistant/test_media_browser.py
Normal file
65
tests/components/music_assistant/test_media_browser.py
Normal file
@ -0,0 +1,65 @@
|
||||
"""Test Music Assistant media browser implementation."""
|
||||
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.media_player import BrowseError, BrowseMedia, MediaType
|
||||
from homeassistant.components.music_assistant.const import DOMAIN
|
||||
from homeassistant.components.music_assistant.media_browser import (
|
||||
LIBRARY_ALBUMS,
|
||||
LIBRARY_ARTISTS,
|
||||
LIBRARY_PLAYLISTS,
|
||||
LIBRARY_RADIO,
|
||||
LIBRARY_TRACKS,
|
||||
async_browse_media,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .common import setup_integration_from_fixtures
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("media_content_id", "media_content_type", "expected"),
|
||||
[
|
||||
(LIBRARY_PLAYLISTS, MediaType.PLAYLIST, "library://playlist/40"),
|
||||
(LIBRARY_ARTISTS, MediaType.ARTIST, "library://artist/127"),
|
||||
(LIBRARY_ALBUMS, MediaType.ALBUM, "library://album/396"),
|
||||
(LIBRARY_TRACKS, MediaType.TRACK, "library://track/486"),
|
||||
(LIBRARY_RADIO, DOMAIN, "library://radio/1"),
|
||||
("artist", MediaType.ARTIST, "library://album/115"),
|
||||
("album", MediaType.ALBUM, "library://track/247"),
|
||||
("playlist", DOMAIN, "tidal--Ah76MuMg://track/77616130"),
|
||||
(None, None, "artists"),
|
||||
],
|
||||
)
|
||||
async def test_browse_media_root(
|
||||
hass: HomeAssistant,
|
||||
music_assistant_client: MagicMock,
|
||||
media_content_id: str,
|
||||
media_content_type: str,
|
||||
expected: str,
|
||||
) -> None:
|
||||
"""Test the async_browse_media method."""
|
||||
await setup_integration_from_fixtures(hass, music_assistant_client)
|
||||
entity_id = "media_player.test_player_1"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
browse_item: BrowseMedia = await async_browse_media(
|
||||
hass, music_assistant_client, media_content_id, media_content_type
|
||||
)
|
||||
assert browse_item.children[0].media_content_id == expected
|
||||
|
||||
|
||||
async def test_browse_media_not_found(
|
||||
hass: HomeAssistant,
|
||||
music_assistant_client: MagicMock,
|
||||
) -> None:
|
||||
"""Test the async_browse_media method when media is not found."""
|
||||
await setup_integration_from_fixtures(hass, music_assistant_client)
|
||||
entity_id = "media_player.test_player_1"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
|
||||
with pytest.raises(BrowseError, match="Media not found: unknown / unknown"):
|
||||
await async_browse_media(hass, music_assistant_client, "unknown", "unknown")
|
Loading…
x
Reference in New Issue
Block a user