Implement ImageListField for MP4

This commit is contained in:
Thomas Scholtes 2014-03-09 12:44:47 +01:00
parent 63def728dc
commit c435fd7446
3 changed files with 22 additions and 55 deletions

View file

@ -495,28 +495,16 @@ class MP4ImageStorageStyle(MP4ListStorageStyle):
def __init__(self, **kwargs):
super(MP4ImageStorageStyle, self).__init__(key='covr', **kwargs)
self.as_type = str
def store(self, mutagen_file, images):
covers = [self._mp4_cover(image) for image in images]
mutagen_file['covr'] = covers
def get_list(self, mutagen_file):
return [TagImage(data) for data in self.fetch(mutagen_file)]
@classmethod
def _mp4_cover(cls, data):
"""Make ``MP4Cover`` tag from image data.
Returns instance of ``mutagen.mp4.MP4Cover`` with correct cover
format.
"""
kind = imghdr.what(None, h=data)
if kind == 'png':
def serialize(self, image):
if image.mime_type == 'image/png':
kind = mutagen.mp4.MP4Cover.FORMAT_PNG
elif kind == 'jpeg':
elif image.mime_type == 'image/jpeg':
kind = mutagen.mp4.MP4Cover.FORMAT_JPEG
else:
raise ValueError('MP4 only supports PNG and JPEG images')
return mutagen.mp4.MP4Cover(data, kind)
return mutagen.mp4.MP4Cover(image.data, kind)
class MP3StorageStyle(StorageStyle):
@ -950,45 +938,20 @@ class DateItemField(MediaField):
class CoverArtField(MediaField):
"""A descriptor providing access to a file's embedded album art.
Holds a bytestring reflecting the image data. The image should
either be a JPEG or a PNG for cross-format compatibility. It's
probably a bad idea to use anything but these two formats.
"""
# TODO make this into shim when ImageField is implemented for all
# formats.
def __init__(self):
super(CoverArtField, self).__init__(
MP3ImageStorageStyle(),
MP4ImageStorageStyle(),
ASFImageStorageStyle(),
VorbisImageStorageStyle(),
FlacImageStorageStyle(),
out_type=str,
)
pass
def __get__(self, mediafile, _):
if mediafile.type in ['mp3', 'flac', 'asf'] + VorbisImageStorageStyle.formats:
try:
return mediafile.images[0].data
except IndexError:
return None
for style in self.styles(mediafile):
return style.get(mediafile.mgfile)
try:
return mediafile.images[0].data
except IndexError:
return None
def __set__(self, mediafile, data):
if mediafile.type in ['mp3', 'flac', 'asf'] + VorbisImageStorageStyle.formats:
if data:
mediafile.images = [TagImage(data=data)]
else:
mediafile.images = []
return
if data is not None:
if not isinstance(data, str):
raise ValueError('value must be a byte string or None')
for style in self.styles(mediafile):
style.set(mediafile.mgfile, data)
if data:
mediafile.images = [TagImage(data=data)]
else:
mediafile.images = []
class ImageListField(MediaField):

BIN
test/rsrc/image.m4a Normal file

Binary file not shown.

View file

@ -117,8 +117,11 @@ class ImageStructureTestMixin(object):
self.assertEqual(len(mediafile.images), 3)
# WMA does not preserve the order, so we have to work around this
image = filter(lambda i: i.desc == 'the composer',
mediafile.images)[0]
try:
image = filter(lambda i: i.desc == 'the composer',
mediafile.images)[0]
except IndexError:
image = None
self.assertExtendedImageAttributes(image,
desc='the composer', type=TagImage.TYPES.composer)
@ -564,7 +567,8 @@ class MP3Test(ReadWriteTestBase, PartialTestMixin,
'channels': 1,
}
class MP4Test(ReadWriteTestBase, PartialTestMixin,
GenreListTestMixin, unittest.TestCase):
GenreListTestMixin, ImageStructureTestMixin,
unittest.TestCase):
extension = 'm4a'
audio_properties = {
'length': 1.0,