provider_instance: str | None = None,
) -> list[Track]:
"""Return album tracks for the given provider album id."""
- if "database" not in (provider_domain, provider_instance):
- # return provider album tracks
- return await self._get_provider_album_tracks(
- item_id, provider_domain or provider_instance
- )
+ if "database" in (provider_domain, provider_instance):
+ if db_result := await self._get_db_album_tracks(item_id):
+ return db_result
+ # no results in db (yet), grab provider details
+ if db_album := await self.get_db_item(item_id):
+ for prov_mapping in db_album.provider_mappings:
+ # returns the first provider that is available
+ if not prov_mapping.available:
+ continue
+ return await self._get_provider_album_tracks(
+ prov_mapping.item_id, provider_instance=prov_mapping.provider_instance
+ )
- # db_album requested: get results from first (non-file) provider
- return await self._get_db_album_tracks(item_id)
+ # return provider album tracks
+ return await self._get_provider_album_tracks(item_id, provider_domain or provider_instance)
async def versions(
self,
await self._match(db_item)
# return final db_item after all match/metadata actions
db_item = await self.get_db_item(db_item.item_id)
- # dump album tracks in db
+ # preload album tracks in db
for prov_mapping in db_item.provider_mappings:
for track in await self._get_provider_album_tracks(
prov_mapping.item_id, prov_mapping.provider_instance
):
- await self.mass.music.tracks.add_db_item(track)
+ await self.mass.music.tracks.get(track.item_id, track.provider, details=track)
self.mass.signal_event(
EventType.MEDIA_ITEM_UPDATED if existing else EventType.MEDIA_ITEM_ADDED,
db_item.uri,
# album
if tags.album:
- # work out if we have an album folder
- album_dir = get_parentdir(file_item.path, tags.album)
+ # work out if we have an album and/or disc folder
+ # disc_dir is the folder level where the tracks are located
+ # this may be a separate disc folder (Disc 1, Disc 2 etc) underneath the album folder
+ # or this is an album folder with the disc attached
+ disc_dir = get_parentdir(file_item.path, f"disc {tags.disc or ''}")
+ album_dir = get_parentdir(disc_dir or file_item.path, tags.album)
# album artist(s)
if tags.album_artists:
track.album = await self._parse_album(
tags.album,
album_dir,
+ disc_dir,
artists=album_artists,
)
else:
if genre := info.get("genre"):
artist.metadata.genres = set(split_items(genre))
# find local images
- artist.metadata.images = await self._get_local_images(artist_path) or None
+ if images := await self._get_local_images(artist_path):
+ artist.metadata.images = images
return artist
async def _parse_album(
- self, name: str | None, album_path: str | None, artists: list[Artist]
+ self, name: str | None, album_path: str | None, disc_path: str | None, artists: list[Artist]
) -> Album | None:
"""Lookup metadata in Album folder."""
assert (name or album_path) and artists
# return basic object if there is no dedicated album folder
return album
- nfo_file = os.path.join(album_path, "album.nfo")
- if await self.exists(nfo_file):
- # found NFO file with metadata
- # https://kodi.wiki/view/NFO_files/Artists
- data = b""
- async for chunk in self.read_file_content(nfo_file):
- data += chunk
- info = await asyncio.to_thread(xmltodict.parse, data)
- info = info["album"]
- album.name = info.get("title", info.get("name", name))
- if sort_name := info.get("sortname"):
- album.sort_name = sort_name
- if musicbrainz_id := info.get("musicbrainzreleasegroupid"):
- album.musicbrainz_id = musicbrainz_id
- if mb_artist_id := info.get("musicbrainzalbumartistid"): # noqa: SIM102
- if album.artist and not album.artist.musicbrainz_id:
- album.artist.musicbrainz_id = mb_artist_id
- if description := info.get("review"):
- album.metadata.description = description
- if year := info.get("year"):
- album.year = int(year)
- if genre := info.get("genre"):
- album.metadata.genres = set(split_items(genre))
- # parse name/version
- album.name, album.version = parse_title_and_version(album.name)
-
- # find local images
- album.metadata.images = await self._get_local_images(album_path) or None
+ for folder_path in (disc_path, album_path):
+ if not folder_path:
+ continue
+ nfo_file = os.path.join(folder_path, "album.nfo")
+ if await self.exists(nfo_file):
+ # found NFO file with metadata
+ # https://kodi.wiki/view/NFO_files/Artists
+ data = b""
+ async for chunk in self.read_file_content(nfo_file):
+ data += chunk
+ info = await asyncio.to_thread(xmltodict.parse, data)
+ info = info["album"]
+ album.name = info.get("title", info.get("name", name))
+ if sort_name := info.get("sortname"):
+ album.sort_name = sort_name
+ if musicbrainz_id := info.get("musicbrainzreleasegroupid"):
+ album.musicbrainz_id = musicbrainz_id
+ if mb_artist_id := info.get("musicbrainzalbumartistid"): # noqa: SIM102
+ if album.artist and not album.artist.musicbrainz_id:
+ album.artist.musicbrainz_id = mb_artist_id
+ if description := info.get("review"):
+ album.metadata.description = description
+ if year := info.get("year"):
+ album.year = int(year)
+ if genre := info.get("genre"):
+ album.metadata.genres = set(split_items(genre))
+ # parse name/version
+ album.name, album.version = parse_title_and_version(album.name)
+ # find local images
+ if images := await self._get_local_images(folder_path):
+ if album.metadata.images is None:
+ album.metadata.images = images
+ else:
+ album.metadata.images += images
return album