diff --git a/beets/library.py b/beets/library.py index b33f1739a..e3b5bbfa0 100644 --- a/beets/library.py +++ b/beets/library.py @@ -69,6 +69,17 @@ ITEM_FIELDS = [ ('label', 'text', True, True), ('acoustid_fingerprint', 'text', True, True), ('acoustid_id', 'text', True, True), + ('mb_releasegroupid', 'text', True, True), + ('asin', 'text', True, True), + ('catalognum', 'text', True, True), + ('script', 'text', True, True), + ('language', 'text', True, True), + ('country', 'text', True, True), + ('albumstatus', 'text', True, True), + ('media', 'text', True, True), + ('albumdisambig', 'text', True, True), + ('disctitle', 'text', True, True), + ('encoder', 'text', True, True), ('length', 'real', False, True), ('bitrate', 'int', False, True), @@ -89,20 +100,28 @@ ALBUM_FIELDS = [ ('id', 'integer primary key', False), ('artpath', 'blob', False), - ('albumartist', 'text', True), - ('albumartist_sort', 'text', True), - ('album', 'text', True), - ('genre', 'text', True), - ('year', 'int', True), - ('month', 'int', True), - ('day', 'int', True), - ('tracktotal', 'int', True), - ('disctotal', 'int', True), - ('comp', 'bool', True), - ('mb_albumid', 'text', True), - ('mb_albumartistid', 'text', True), - ('albumtype', 'text', True), - ('label', 'text', True), + ('albumartist', 'text', True), + ('albumartist_sort', 'text', True), + ('album', 'text', True), + ('genre', 'text', True), + ('year', 'int', True), + ('month', 'int', True), + ('day', 'int', True), + ('tracktotal', 'int', True), + ('disctotal', 'int', True), + ('comp', 'bool', True), + ('mb_albumid', 'text', True), + ('mb_albumartistid', 'text', True), + ('albumtype', 'text', True), + ('label', 'text', True), + ('mb_releasegroupid', 'text', True), + ('asin', 'text', True), + ('script', 'text', True), + ('language', 'text', True), + ('country', 'text', True), + ('albumstatus', 'text', True), + ('media', 'text', True), + ('albumdisambig', 'text', True), ] ALBUM_KEYS = [f[0] for f in ALBUM_FIELDS] ALBUM_KEYS_ITEM = [f[0] for f in ALBUM_FIELDS if f[2]] diff --git a/beets/mediafile.py b/beets/mediafile.py index 724802e0b..4844071e7 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -855,6 +855,60 @@ class MediaFile(object): mp4 = StorageStyle("soaa"), etc = StorageStyle('ALBUMARTISTSORT'), ) + asin = MediaField( + mp3 = StorageStyle('TXXX', id3_desc=u'ASIN'), + mp4 = StorageStyle("----:com.apple.iTunes:ASIN"), + etc = StorageStyle('ASIN'), + ) + catalognum = MediaField( + mp3 = StorageStyle('TXXX', id3_desc=u'TXXX:CATALOGNUMBER'), + mp4 = StorageStyle("----:com.apple.iTunes:CATALOGNUMBER"), + etc = StorageStyle('CATALOGNUMBER'), + ) + disctitle = MediaField( + mp3 = StorageStyle('TSST'), + mp4 = StorageStyle("----:com.apple.iTunes:DISCSUBTITLE"), + etc = StorageStyle('DISCSUBTITLE'), + ) + encoder = MediaField( + mp3 = StorageStyle('TENC'), + mp4 = StorageStyle("\xa9too"), + etc = [StorageStyle('ENCODEDBY'), + StorageStyle('ENCODER')] + ) + script = MediaField( + mp3 = StorageStyle('TXXX', id3_desc=u'Script'), + mp4 = StorageStyle("----:com.apple.iTunes:SCRIPT"), + etc = StorageStyle('SCRIPT'), + ) + language = MediaField( + mp3 = StorageStyle('TLAN'), + mp4 = StorageStyle("----:com.apple.iTunes:LANGUAGE"), + etc = StorageStyle('LANGUAGE'), + ) + country = MediaField( + mp3 = StorageStyle('TXXX', + id3_desc=u'MusicBrainz Album Release Country'), + mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album " + "Release Country"), + etc = StorageStyle('RELEASECOUNTRY'), + ) + albumstatus = MediaField( + mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Status'), + mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album Status"), + etc = StorageStyle('MUSICBRAINZ_ALBUMSTATUS'), + ) + media = MediaField( + mp3 = StorageStyle('TMED'), + mp4 = StorageStyle("----:com.apple.iTunes:MEDIA"), + etc = StorageStyle('MEDIA'), + ) + albumdisambig = MediaField( + # This tag mapping was invented for beets (not used by Picard, etc). + mp3 = StorageStyle('TXXX', id3_desc=u'MusicBrainz Album Comment'), + mp4 = StorageStyle("----:com.apple.iTunes:MusicBrainz Album Comment"), + etc = StorageStyle('MUSICBRAINZ_ALBUMCOMMENT'), + ) # Album art. art = ImageField() @@ -887,6 +941,13 @@ class MediaFile(object): as_type=str), etc = StorageStyle('musicbrainz_albumartistid') ) + mb_releasegroupid = MediaField( + mp3 = StorageStyle('TXXX', + id3_desc=u'MusicBrainz Release Group Id'), + mp4 = StorageStyle('----:com.apple.iTunes:MusicBrainz Release Group Id', + as_type=str), + etc = StorageStyle('musicbrainz_releasegroupid') + ) # Acoustid fields. acoustid_fingerprint = MediaField( diff --git a/docs/changelog.rst b/docs/changelog.rst index 4a30fcdb4..5adb97af0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,6 +14,9 @@ Changelog fields, ``artist_sort`` and ``albumartist_sort``, that contain sortable artist names like "Beatles, The". These fields are also used to sort albums and items when using the ``list`` command. Thanks to Paul Provost. +* Many other **new metadata fields** were added, including ASIN, label catalog + number, disc title, encoder, and MusicBrainz release group ID. For a full list + of fields, see :ref:`itemfields`. * :doc:`/plugins/chroma`: A new command, ``beet submit``, will **submit fingerprints** to the Acoustid database. Submitting your library helps increase the coverage and accuracy of Acoustid fingerprinting. The Chromaprint diff --git a/docs/reference/pathformat.rst b/docs/reference/pathformat.rst index 35d798863..fbc5228be 100644 --- a/docs/reference/pathformat.rst +++ b/docs/reference/pathformat.rst @@ -99,6 +99,7 @@ your template. For example, the second parameter to ``%left`` must be an integer; if you write ``%left{foo,bar}``, this will be expanded to something like ````. +.. _itemfields: Available Values ---------------- @@ -136,6 +137,16 @@ Ordinary metadata: * albumtype (the MusicBrainz album type; the MusicBrainz wiki has a `list of type names`_) * label +* asin +* catalognum +* script +* language +* country +* albumstatus +* media +* albumdisambig +* disctitle +* encoder .. _list of type names: http://wiki.musicbrainz.org/XMLWebService#Release_Type_and_Status @@ -154,5 +165,6 @@ MusicBrainz and fingerprint information: * mb_albumid * mb_artistid * mb_albumartistid +* mb_releasegroupid * acoustid_fingerprint * acoustid_id diff --git a/test/rsrc/test.blb b/test/rsrc/test.blb index e152eb8bf..4fe2abf95 100644 Binary files a/test/rsrc/test.blb and b/test/rsrc/test.blb differ diff --git a/test/test_mediafile_basic.py b/test/test_mediafile_basic.py index 8131e2c1e..793ceceb5 100644 --- a/test/test_mediafile_basic.py +++ b/test/test_mediafile_basic.py @@ -171,11 +171,6 @@ correct_dicts = { 'mb_artistid':'7cf0ea9d-86b9-4dad-ba9e-2355a64899ea', 'art': None, 'label': u'the label', - - 'rg_track_peak': 0.0, - 'rg_track_gain': 0.0, - 'rg_album_peak': 0.0, - 'rg_album_gain': 0.0, }, # Additional coverage for common cases when "total" fields are unset. @@ -223,12 +218,27 @@ correct_dicts = { 'label': u'', # Additional, non-iTunes fields. + 'rg_track_peak': 0.0, + 'rg_track_gain': 0.0, + 'rg_album_peak': 0.0, + 'rg_album_gain': 0.0, 'albumartist': u'', 'mb_albumartistid': u'', 'artist_sort': u'', 'albumartist_sort': u'', 'acoustid_fingerprint': u'', 'acoustid_id': u'', + 'mb_releasegroupid': u'', + 'asin': u'', + 'catalognum': u'', + 'disctitle': u'', + 'encoder': u'', + 'script': u'', + 'language': u'', + 'country': u'', + 'albumstatus': u'', + 'media': u'', + 'albumdisambig': u'', }, # Full release date.