MediaFile: improve cover art detection

Filter media file images on their type.
Detection is still not deterministic when 0 or multiple image
have type ImageType.front.

Fix #1332.
This commit is contained in:
Bruno Cauet 2015-02-20 12:53:43 +01:00
parent 2dec90de7a
commit a8477264ac
2 changed files with 29 additions and 5 deletions

View file

@ -1246,18 +1246,31 @@ class DateItemField(MediaField):
class CoverArtField(MediaField):
"""A descriptor that provides access to the *raw image data* for the
first image on a file. This is used for backwards compatibility: the
cover image on a file. This is used for backwards compatibility: the
full `ImageListField` provides richer `Image` objects.
When there are multiple images we try to pick the most likely to be a front
cover.
"""
def __init__(self):
pass
def __get__(self, mediafile, _):
try:
return mediafile.images[0].data
except IndexError:
candidates = mediafile.images
if candidates:
return self.guess_cover_image(candidates).data
else:
return None
@staticmethod
def guess_cover_image(candidates):
if len(candidates) == 1:
return candidates[0]
try:
return next(c for c in candidates if c.type == ImageType.front)
except StopIteration:
return candidates[0]
def __set__(self, mediafile, data):
if data:
mediafile.images = [Image(data=data)]

View file

@ -28,7 +28,7 @@ from test import _common
from test._common import unittest
from beets.mediafile import MediaFile, MediaField, Image, \
MP3DescStorageStyle, StorageStyle, MP4StorageStyle, \
ASFStorageStyle, ImageType
ASFStorageStyle, ImageType, CoverArtField
from beets.library import Item
from beets.plugins import BeetsPlugin
@ -161,6 +161,13 @@ class ImageStructureTestMixin(ArtTestMixin):
mediafile = MediaFile(mediafile.path)
self.assertEqual(len(mediafile.images), 0)
def test_guess_cover(self):
mediafile = self._mediafile_fixture('image')
self.assertEqual(len(mediafile.images), 2)
cover = CoverArtField.guess_cover_image(mediafile.images)
self.assertEqual(cover.desc, 'album cover')
self.assertEqual(mediafile.art, cover.data)
def assertExtendedImageAttributes(self, image, **kwargs):
"""Ignore extended image attributes in the base tests.
"""
@ -758,6 +765,10 @@ class MP4Test(ReadWriteTestBase, PartialTestMixin,
with self.assertRaises(ValueError):
mediafile.images = [Image(data=self.tiff_data)]
def test_guess_cover(self):
# There is no metadata associated with images, we pick one at random
pass
class AlacTest(ReadWriteTestBase, unittest.TestCase):
extension = 'alac.m4a'