diff --git a/picard/formats/apev2.py b/picard/formats/apev2.py index 5c8db4c17..cadec49d0 100644 --- a/picard/formats/apev2.py +++ b/picard/formats/apev2.py @@ -97,6 +97,13 @@ class APEv2File(File): "musicbrainz_trackid": "musicbrainz_recordingid", "musicbrainz_releasetrackid": "musicbrainz_trackid", "Original Artist": "originalartist", + "REPLAYGAIN_ALBUM_GAIN": "replaygain_album_gain", + "REPLAYGAIN_ALBUM_PEAK": "replaygain_album_peak", + "REPLAYGAIN_ALBUM_RANGE": "replaygain_album_range", + "REPLAYGAIN_TRACK_GAIN": "replaygain_track_gain", + "REPLAYGAIN_TRACK_PEAK": "replaygain_track_peak", + "REPLAYGAIN_TRACK_RANGE": "replaygain_track_range", + "REPLAYGAIN_REFERENCE_LOUDNESS": "replaygain_reference_loudness", } __rtranslate = dict([(v, k) for k, v in __translate.items()]) diff --git a/picard/formats/asf.py b/picard/formats/asf.py index d65f0be82..0f65eaeec 100644 --- a/picard/formats/asf.py +++ b/picard/formats/asf.py @@ -158,6 +158,13 @@ class ASFFile(File): 'artists': 'WM/ARTISTS', 'work': 'WM/Work', 'website': 'WM/AuthorURL', + 'replaygain_album_gain': 'REPLAYGAIN_ALBUM_GAIN', + 'replaygain_album_peak': 'REPLAYGAIN_ALBUM_PEAK', + 'replaygain_album_range': 'REPLAYGAIN_ALBUM_RANGE', + 'replaygain_track_gain': 'REPLAYGAIN_TRACK_GAIN', + 'replaygain_track_peak': 'REPLAYGAIN_TRACK_PEAK', + 'replaygain_track_range': 'REPLAYGAIN_TRACK_RANGE', + 'replaygain_reference_loudness': 'REPLAYGAIN_REFERENCE_LOUDNESS', } __RTRANS = dict([(b, a) for a, b in __TRANS.items()]) diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 8709b4bf6..80703eaa6 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -173,6 +173,13 @@ class ID3File(File): 'WORK': 'work', 'Writer': 'writer', 'SHOWMOVEMENT': 'showmovement', + 'REPLAYGAIN_ALBUM_GAIN': 'replaygain_album_gain', + 'REPLAYGAIN_ALBUM_PEAK': 'replaygain_album_peak', + 'REPLAYGAIN_ALBUM_RANGE': 'replaygain_album_range', + 'REPLAYGAIN_TRACK_GAIN': 'replaygain_track_gain', + 'REPLAYGAIN_TRACK_PEAK': 'replaygain_track_peak', + 'REPLAYGAIN_TRACK_RANGE': 'replaygain_track_range', + 'REPLAYGAIN_REFERENCE_LOUDNESS': 'replaygain_reference_loudness', } __rtranslate_freetext = dict([(v, k) for k, v in __translate_freetext.items()]) __translate_freetext['writer'] = 'writer' # For backward compatibility of case diff --git a/picard/formats/mp4.py b/picard/formats/mp4.py index b73008ec4..6f7636855 100644 --- a/picard/formats/mp4.py +++ b/picard/formats/mp4.py @@ -121,6 +121,13 @@ class MP4File(File): "----:com.apple.iTunes:ARTISTS": "artists", "----:com.apple.iTunes:WORK": "work", "----:com.apple.iTunes:initialkey": "key", + "----:com.apple.iTunes:REPLAYGAIN_ALBUM_GAIN": "replaygain_album_gain", + "----:com.apple.iTunes:REPLAYGAIN_ALBUM_PEAK": "replaygain_album_peak", + "----:com.apple.iTunes:REPLAYGAIN_ALBUM_RANGE": "replaygain_album_range", + "----:com.apple.iTunes:REPLAYGAIN_TRACK_GAIN": "replaygain_track_gain", + "----:com.apple.iTunes:REPLAYGAIN_TRACK_PEAK": "replaygain_track_peak", + "----:com.apple.iTunes:REPLAYGAIN_TRACK_RANGE": "replaygain_track_range", + "----:com.apple.iTunes:REPLAYGAIN_REFERENCE_LOUDNESS": "replaygain_reference_loudness", } __r_freeform_tags = dict([(v, k) for k, v in __freeform_tags.items()]) diff --git a/picard/util/tags.py b/picard/util/tags.py index 07546bf4d..7d4d55b77 100644 --- a/picard/util/tags.py +++ b/picard/util/tags.py @@ -96,6 +96,13 @@ TAG_NAMES = { 'musicbrainz_originalartistid': N_('MusicBrainz Original Artist Id'), 'originalalbum': N_('Original Album'), 'musicbrainz_originalalbumid': N_('MusicBrainz Original Release Id'), + 'replaygain_album_gain': N_('ReplayGain Album Gain'), + 'replaygain_album_peak': N_('ReplayGain Album Peak'), + 'replaygain_album_range': N_('ReplayGain Album Range'), + 'replaygain_track_gain': N_('ReplayGain Track Gain'), + 'replaygain_track_peak': N_('ReplayGain Track Peak'), + 'replaygain_track_range': N_('ReplayGain Track Range'), + 'replaygain_reference_loudness': N_('ReplayGain Reference Loudness'), } PRESERVED_TAGS = [ diff --git a/test/formats/common.py b/test/formats/common.py index 0a0c63231..31edbf2f4 100644 --- a/test/formats/common.py +++ b/test/formats/common.py @@ -130,6 +130,16 @@ TAGS = { 'work': 'Foo' } +REPLAYGAIN_TAGS = { + 'replaygain_album_gain': '-6.48 dB', + 'replaygain_album_peak': '0.978475', + 'replaygain_album_range': '7.84 dB', + 'replaygain_track_gain': '-6.16 dB', + 'replaygain_track_peak': '0.976991', + 'replaygain_track_range': '8.22 dB', + 'replaygain_reference_loudness': '-18.00 LUFS', +} + def skipUnlessTestfile(func): def _decorator(self, *args, **kwargs): @@ -190,6 +200,7 @@ class CommonTests: def setUp(self): super().setUp() self.tags = TAGS.copy() + self.replaygain_tags = REPLAYGAIN_TAGS.copy() self.setup_tags() def setup_tags(self): @@ -213,6 +224,13 @@ class CommonTests: for (key, value) in self.tags.items(): self.assertEqual(loaded_metadata[key], value, '%s: %r != %r' % (key, loaded_metadata[key], value)) + @skipUnlessTestfile + def test_replaygain_tags(self): + metadata = Metadata(self.replaygain_tags) + loaded_metadata = save_and_load_metadata(self.filename, metadata) + for (key, value) in self.replaygain_tags.items(): + self.assertEqual(loaded_metadata[key], value, '%s: %r != %r' % (key, loaded_metadata[key], value)) + @skipUnlessTestfile def test_save_does_not_modify_metadata(self): tags = dict(self.tags)