From a8477264ac7452187f0cb14b9fa6470543c11fd0 Mon Sep 17 00:00:00 2001 From: Bruno Cauet Date: Fri, 20 Feb 2015 12:53:43 +0100 Subject: [PATCH] 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. --- beets/mediafile.py | 21 +++++++++++++++++---- test/test_mediafile.py | 13 ++++++++++++- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/beets/mediafile.py b/beets/mediafile.py index 6c5d0a2c2..22899dee0 100644 --- a/beets/mediafile.py +++ b/beets/mediafile.py @@ -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)] diff --git a/test/test_mediafile.py b/test/test_mediafile.py index 717364128..cd149e7e4 100644 --- a/test/test_mediafile.py +++ b/test/test_mediafile.py @@ -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'