mirror of
https://github.com/fergalmoran/picard.git
synced 2026-03-21 20:55:08 +00:00
PICARD-1592: APEv2 tag case insensitive reading
According to specification APEv2 tags should be read case insensitive. Previously Picard only read tags for which there was no explicit mapping case insensitive, but treated all explicitly mapped tags case sensitive.
This commit is contained in:
committed by
Philipp Wolfer
parent
551c2b10f0
commit
965ee9bbce
@@ -80,34 +80,34 @@ class APEv2File(File):
|
||||
_File = None
|
||||
|
||||
__translate = {
|
||||
"Album Artist": "albumartist",
|
||||
"MixArtist": "remixer",
|
||||
"Weblink": "website",
|
||||
"DiscSubtitle": "discsubtitle",
|
||||
"BPM": "bpm",
|
||||
"ISRC": "isrc",
|
||||
"CatalogNumber": "catalognumber",
|
||||
"Barcode": "barcode",
|
||||
"EncodedBy": "encodedby",
|
||||
"Language": "language",
|
||||
"MOVEMENT": "movementnumber",
|
||||
"MOVEMENTNAME": "movement",
|
||||
"MOVEMENTTOTAL": "movementtotal",
|
||||
"SHOWMOVEMENT": "showmovement",
|
||||
"MUSICBRAINZ_ALBUMSTATUS": "releasestatus",
|
||||
"MUSICBRAINZ_ALBUMTYPE": "releasetype",
|
||||
"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",
|
||||
"albumartist": "Album Artist",
|
||||
"remixer": "MixArtist",
|
||||
"website": "Weblink",
|
||||
"discsubtitle": "DiscSubtitle",
|
||||
"bpm": "BPM",
|
||||
"isrc": "ISRC",
|
||||
"catalognumber": "CatalogNumber",
|
||||
"barcode": "Barcode",
|
||||
"encodedby": "EncodedBy",
|
||||
"language": "Language",
|
||||
"movementnumber": "MOVEMENT",
|
||||
"movement": "MOVEMENTNAME",
|
||||
"movementtotal": "MOVEMENTTOTAL",
|
||||
"showmovement": "SHOWMOVEMENT",
|
||||
"releasestatus": "MUSICBRAINZ_ALBUMSTATUS",
|
||||
"releasetype": "MUSICBRAINZ_ALBUMTYPE",
|
||||
"musicbrainz_recordingid": "musicbrainz_trackid",
|
||||
"musicbrainz_trackid": "musicbrainz_releasetrackid",
|
||||
"originalartist": "Original Artist",
|
||||
"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()])
|
||||
__rtranslate = dict([(v.lower(), k) for k, v in __translate.items()])
|
||||
|
||||
def _load(self, filename):
|
||||
log.debug("Loading file %r", filename)
|
||||
@@ -115,7 +115,9 @@ class APEv2File(File):
|
||||
metadata = Metadata()
|
||||
if file.tags:
|
||||
for origname, values in file.tags.items():
|
||||
if origname.lower().startswith("cover art") and values.kind == mutagen.apev2.BINARY:
|
||||
origname = origname.lower()
|
||||
if (values.kind == mutagen.apev2.BINARY
|
||||
and origname.startswith("cover art")):
|
||||
if b'\0' in values.value:
|
||||
descr, data = values.value.split(b'\0', 1)
|
||||
try:
|
||||
@@ -135,32 +137,30 @@ class APEv2File(File):
|
||||
continue
|
||||
for value in values:
|
||||
name = origname
|
||||
if name == "Year":
|
||||
if name == "year":
|
||||
name = "date"
|
||||
value = sanitize_date(value)
|
||||
elif name == "Track":
|
||||
elif name == "track":
|
||||
name = "tracknumber"
|
||||
track = value.split("/")
|
||||
if len(track) > 1:
|
||||
metadata["totaltracks"] = track[1]
|
||||
value = track[0]
|
||||
elif name == "Disc":
|
||||
elif name == "disc":
|
||||
name = "discnumber"
|
||||
disc = value.split("/")
|
||||
if len(disc) > 1:
|
||||
metadata["totaldiscs"] = disc[1]
|
||||
value = disc[0]
|
||||
elif name == 'Performer' or name == 'Comment':
|
||||
name = name.lower() + ':'
|
||||
elif name == 'performer' or name == 'comment':
|
||||
name = name + ':'
|
||||
if value.endswith(')'):
|
||||
start = value.rfind(' (')
|
||||
if start > 0:
|
||||
name += value[start + 2:-1]
|
||||
value = value[:start]
|
||||
elif name in self.__translate:
|
||||
name = self.__translate[name]
|
||||
else:
|
||||
name = name.lower()
|
||||
elif name in self.__rtranslate:
|
||||
name = self.__rtranslate[name]
|
||||
metadata.add(name, value)
|
||||
self._info(metadata, file)
|
||||
return metadata
|
||||
@@ -177,7 +177,8 @@ class APEv2File(File):
|
||||
tags.clear()
|
||||
elif images_to_save:
|
||||
for name, value in tags.items():
|
||||
if name.lower().startswith('cover art') and value.kind == mutagen.apev2.BINARY:
|
||||
if (value.kind == mutagen.apev2.BINARY
|
||||
and name.lower().startswith('cover art')):
|
||||
del tags[name]
|
||||
temp = {}
|
||||
for name, value in metadata.items():
|
||||
@@ -205,7 +206,8 @@ class APEv2File(File):
|
||||
for image in images_to_save:
|
||||
cover_filename = 'Cover Art (Front)'
|
||||
cover_filename += image.extension
|
||||
tags['Cover Art (Front)'] = mutagen.apev2.APEValue(cover_filename.encode('ascii') + b'\0' + image.data, mutagen.apev2.BINARY)
|
||||
tags['Cover Art (Front)'] = mutagen.apev2.APEValue(
|
||||
cover_filename.encode('ascii') + b'\0' + image.data, mutagen.apev2.BINARY)
|
||||
break
|
||||
# can't save more than one item with the same name
|
||||
# (mp3tags does this, but it's against the specs)
|
||||
@@ -243,8 +245,8 @@ class APEv2File(File):
|
||||
return 'Disc'
|
||||
elif name.startswith('performer:') or name.startswith('comment:'):
|
||||
return name.split(':', 1)[0].title()
|
||||
elif name in self.__rtranslate:
|
||||
return self.__rtranslate[name]
|
||||
elif name in self.__translate:
|
||||
return self.__translate[name]
|
||||
else:
|
||||
return name.title()
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ from .common import (
|
||||
TAGS,
|
||||
CommonTests,
|
||||
load_metadata,
|
||||
load_raw,
|
||||
save_metadata,
|
||||
save_raw,
|
||||
skipUnlessTestfile,
|
||||
)
|
||||
@@ -77,6 +79,26 @@ class CommonApeTests:
|
||||
self.assertTrue(self.format.supports_tag('lyrics:foó'))
|
||||
self.assertTrue(self.format.supports_tag('comment:foó'))
|
||||
|
||||
def test_case_insensitive_reading(self):
|
||||
self._read_case_insensitive_tag('artist', 'Artist')
|
||||
self._read_case_insensitive_tag('albumartist', 'Album Artist')
|
||||
self._read_case_insensitive_tag('performer:', 'Performer')
|
||||
self._read_case_insensitive_tag('tracknumber', 'Track')
|
||||
self._read_case_insensitive_tag('discnumber', 'Disc')
|
||||
|
||||
def _read_case_insensitive_tag(self, name, ape_name):
|
||||
upper_ape_name = ape_name.upper()
|
||||
metadata = {
|
||||
upper_ape_name: 'Some value'
|
||||
}
|
||||
save_raw(self.filename, metadata)
|
||||
loaded_metadata = load_metadata(self.filename)
|
||||
self.assertEqual(metadata[upper_ape_name], loaded_metadata[name])
|
||||
save_metadata(self.filename, loaded_metadata)
|
||||
raw_metadata = load_raw(self.filename)
|
||||
self.assertIn(ape_name, raw_metadata.keys())
|
||||
self.assertEqual(metadata[upper_ape_name], raw_metadata[ape_name])
|
||||
|
||||
|
||||
class MonkeysAudioTest(CommonApeTests.ApeTestCase):
|
||||
testfile = 'test.ape'
|
||||
|
||||
Reference in New Issue
Block a user