mirror of
https://github.com/beetbox/beets.git
synced 2025-12-25 01:53:31 +01:00
Implement ImageListField for MP4
This commit is contained in:
parent
63def728dc
commit
c435fd7446
3 changed files with 22 additions and 55 deletions
|
|
@ -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
BIN
test/rsrc/image.m4a
Normal file
Binary file not shown.
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue