diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index 84f826ed1..039ceb730 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -135,7 +135,7 @@ def apply_metadata(items, album_info): else: item.artist_sort = album_info.artist_sort item.albumartist_sort = album_info.artist_sort - + # Release date. if album_info.year: item.year = album_info.year @@ -143,7 +143,7 @@ def apply_metadata(items, album_info): item.month = album_info.month if album_info.day: item.day = album_info.day - + # Title and track index. item.title = track_info.title item.track = index + 1 @@ -151,7 +151,7 @@ def apply_metadata(items, album_info): # Disc and disc count. item.disc = track_info.medium item.disctotal = album_info.mediums - + # MusicBrainz IDs. item.mb_trackid = track_info.track_id item.mb_albumid = album_info.album_id @@ -160,9 +160,21 @@ def apply_metadata(items, album_info): else: item.mb_artistid = album_info.artist_id item.mb_albumartistid = album_info.artist_id + item.mb_releasegroupid = album_info.releasegroup_id + + # Compilation flag. + item.comp = album_info.va + + # Miscellaneous metadata. item.albumtype = album_info.albumtype if album_info.label: item.label = album_info.label - - # Compilation flag. - item.comp = album_info.va + item.asin = album_info.asin + item.catalognum = album_info.catalognum + item.script = album_info.script + item.language = album_info.language + item.country = album_info.country + item.albumstatus = album_info.albumstatus + item.media = album_info.media + item.albumdisambig = album_info.albumdisambig + item.disctitle = track_info.disctitle diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 4f3ee3752..2d33516ea 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -37,13 +37,24 @@ class AlbumInfo(object): - ``label``: music label responsible for the release - ``mediums``: the number of discs in this release - ``artist_sort``: name of the release's artist for sorting + - ``releasegroup_id``: MBID for the album's release group + - ``catalognum``: the label's catalog number for the release + - ``script``: character set used for metadata + - ``language``: human language of the metadata + - ``country``: the release country + - ``albumstatus``: MusicBrainz release status (Official, etc.) + - ``media``: delivery mechanism (Vinyl, etc.) + - ``albumdisambig``: MusicBrainz release disambiguation comment The fields up through ``tracks`` are required. The others are optional and may be None. """ def __init__(self, album, album_id, artist, artist_id, tracks, asin=None, albumtype=None, va=False, year=None, month=None, day=None, - label=None, mediums=None, artist_sort=None): + label=None, mediums=None, artist_sort=None, + releasegroup_id=None, catalognum=None, script=None, + language=None, country=None, albumstatus=None, media=None, + albumdisambig=None): self.album = album self.album_id = album_id self.artist = artist @@ -58,6 +69,14 @@ class AlbumInfo(object): self.label = label self.mediums = mediums self.artist_sort = artist_sort + self.releasegroup_id = releasegroup_id + self.catalognum = catalognum + self.script = script + self.language = language + self.country = country + self.albumstatus = albumstatus + self.media = media + self.albumdisambig = albumdisambig class TrackInfo(object): """Describes a canonical track present on a release. Appears as part @@ -71,13 +90,14 @@ class TrackInfo(object): - ``medium``: the disc number this track appears on in the album - ``medium_index``: the track's position on the disc - ``artist_sort``: name of the track artist for sorting + - ``disctitle``: name of the individual medium (subtitle) Only ``title`` and ``track_id`` are required. The rest of the fields may be None. """ def __init__(self, title, track_id, artist=None, artist_id=None, length=None, medium=None, medium_index=None, - artist_sort=None): + artist_sort=None, disctitle=None): self.title = title self.track_id = track_id self.artist = artist @@ -86,6 +106,8 @@ class TrackInfo(object): self.medium = medium self.medium_index = medium_index self.artist_sort = artist_sort + self.disctitle = disctitle + # Aggregation of sources. diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index af7c2eb8d..a4f56d16a 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -96,6 +96,7 @@ def album_info(release): # Basic info. track_infos = [] for medium in release['medium-list']: + disctitle = medium.get('title') for track in medium['track-list']: ti = track_info(track['recording'], int(medium['position']), @@ -104,6 +105,7 @@ def album_info(release): # Track title may be distinct from underling recording # title. ti.title = track['title'] + ti.disctitle = disctitle track_infos.append(ti) info = beets.autotag.hooks.AlbumInfo( release['title'], @@ -115,8 +117,11 @@ def album_info(release): artist_sort=release['artist-credit'][0]['artist']['sort-name'], ) info.va = info.artist_id == VARIOUS_ARTISTS_ID - if 'asin' in release: - info.asin = release['asin'] + info.asin = release.get('asin') + info.releasegroup_id = release['release-group']['id'] + info.albumdisambig = release['release-group'].get('disambiguation') + info.country = release.get('country') + info.albumstatus = release.get('status') # Release type not always populated. if 'type' in release['release-group']: @@ -139,6 +144,18 @@ def album_info(release): label = label_info['label']['name'] if label != '[no label]': info.label = label + info.catalognum = label_info.get('catalog-number') + + # Text representation data. + if release.get('text-representation'): + rep = release['text-representation'] + info.script = rep['script'] + info.language = rep['language'] + + # Media (format). + if release['medium-list']: + first_medium = release['medium-list'][0] + info.media = first_medium.get('format') return info diff --git a/test/test_mb.py b/test/test_mb.py index 0300c2c7f..2daf7ba5c 100644 --- a/test/test_mb.py +++ b/test/test_mb.py @@ -22,9 +22,12 @@ class MBAlbumInfoTest(unittest.TestCase): release = { 'title': 'ALBUM TITLE', 'id': 'ALBUM ID', + 'asin': 'ALBUM ASIN', 'release-group': { 'type': 'Album', 'first-release-date': date_str, + 'id': 'RELEASE GROUP ID', + 'disambiguation': 'DISAMBIGUATION', }, 'artist-credit': [ {'artist': { @@ -35,6 +38,16 @@ class MBAlbumInfoTest(unittest.TestCase): ], 'date': '3001', 'medium-list': [], + 'label-info-list': [{ + 'catalog-number': 'CATALOG NUMBER', + 'label': {'name': 'LABEL NAME'}, + }], + 'text-representation': { + 'script': 'SCRIPT', + 'language': 'LANGUAGE', + }, + 'country': 'COUNTRY', + 'status': 'STATUS', } if tracks: track_list = [] @@ -46,6 +59,8 @@ class MBAlbumInfoTest(unittest.TestCase): release['medium-list'].append({ 'position': '1', 'track-list': track_list, + 'format': 'FORMAT', + 'title': 'MEDIUM TITLE', }) return release @@ -57,7 +72,7 @@ class MBAlbumInfoTest(unittest.TestCase): if duration is not None: track['length'] = duration return track - + def test_parse_release_with_year(self): release = self._make_release('1984') d = mb.album_info(release) @@ -172,6 +187,58 @@ class MBAlbumInfoTest(unittest.TestCase): d = mb.album_info(release) self.assertEqual(d.artist_sort, 'ARTIST SORT NAME') + def test_parse_releasegroupid(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.releasegroup_id, 'RELEASE GROUP ID') + + def test_parse_asin(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.asin, 'ALBUM ASIN') + + def test_parse_catalognum(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.catalognum, 'CATALOG NUMBER') + + def test_parse_textrepr(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.script, 'SCRIPT') + self.assertEqual(d.language, 'LANGUAGE') + + def test_parse_country(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.country, 'COUNTRY') + + def test_parse_status(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.albumstatus, 'STATUS') + + def test_parse_media(self): + tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0), + self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)] + release = self._make_release(None, tracks=tracks) + d = mb.album_info(release) + self.assertEqual(d.media, 'FORMAT') + + def test_parse_disambig(self): + release = self._make_release(None) + d = mb.album_info(release) + self.assertEqual(d.albumdisambig, 'DISAMBIGUATION') + + def test_parse_disctitle(self): + tracks = [self._make_track('TITLE ONE', 'ID ONE', 100.0 * 1000.0), + self._make_track('TITLE TWO', 'ID TWO', 200.0 * 1000.0)] + release = self._make_release(None, tracks=tracks) + d = mb.album_info(release) + t = d.tracks + self.assertEqual(t[0].disctitle, 'MEDIUM TITLE') + self.assertEqual(t[1].disctitle, 'MEDIUM TITLE') + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)