mirror of
https://github.com/fergalmoran/picard.git
synced 2026-01-06 16:44:06 +00:00
Merge pull request #332 from zas/cover_art_pdf
Improve handling of PDF cover art from CAA
This commit is contained in:
@@ -74,21 +74,28 @@ class CoverArt:
|
||||
)
|
||||
try:
|
||||
coverartimage.set_data(data)
|
||||
log.debug("Cover art image downloaded: %r [%s]" %
|
||||
(
|
||||
coverartimage,
|
||||
coverartimage.imageinfo_as_string()
|
||||
if coverartimage.can_be_saved_to_metadata:
|
||||
log.debug("Cover art image downloaded: %r [%s]" %
|
||||
(
|
||||
coverartimage,
|
||||
coverartimage.imageinfo_as_string()
|
||||
)
|
||||
)
|
||||
self.metadata.append_image(coverartimage)
|
||||
for track in self.album._new_tracks:
|
||||
track.metadata.append_image(coverartimage)
|
||||
# If the image already was a front image,
|
||||
# there might still be some other non-CAA front
|
||||
# images in the queue - ignore them.
|
||||
if not self.front_image_found:
|
||||
self.front_image_found = coverartimage.is_front_image()
|
||||
else:
|
||||
log.debug("Thumbnail for cover art image downloaded: %r [%s]" %
|
||||
(
|
||||
coverartimage,
|
||||
coverartimage.imageinfo_as_string()
|
||||
)
|
||||
)
|
||||
)
|
||||
self.metadata.append_image(coverartimage)
|
||||
for track in self.album._new_tracks:
|
||||
track.metadata.append_image(coverartimage)
|
||||
# If the image already was a front image,
|
||||
# there might still be some other non-CAA front
|
||||
# images in the queue - ignore them.
|
||||
if not self.front_image_found:
|
||||
self.front_image_found = coverartimage.is_front_image()
|
||||
|
||||
except CoverArtImageIOError as e:
|
||||
self.album.error_append(unicode(e))
|
||||
self.album._finalize_loading(error=True)
|
||||
@@ -100,7 +107,6 @@ class CoverArt:
|
||||
|
||||
self.download_next_in_queue()
|
||||
|
||||
|
||||
def download_next_in_queue(self):
|
||||
"""Downloads next item in queue.
|
||||
If there are none left, loading of album will be finalized.
|
||||
|
||||
@@ -124,6 +124,11 @@ class CoverArtImage:
|
||||
self.types = types
|
||||
self.comment = comment
|
||||
self.datahash = None
|
||||
# thumbnail is used to link to another CoverArtImage, ie. for PDFs
|
||||
self.thumbnail = None
|
||||
self.can_be_saved_to_tags = True
|
||||
self.can_be_saved_to_disk = True
|
||||
self.can_be_saved_to_metadata = True
|
||||
if data is not None:
|
||||
self.set_data(data)
|
||||
|
||||
@@ -150,6 +155,9 @@ class CoverArtImage:
|
||||
- if `support_types` is False, default to True for any image
|
||||
- if `support_types` is True, default to False for any image
|
||||
"""
|
||||
if not self.can_be_saved_to_metadata:
|
||||
# ignore thumbnails
|
||||
return False
|
||||
if self.is_front is not None:
|
||||
return self.is_front
|
||||
if u'front' in self.types:
|
||||
@@ -246,6 +254,8 @@ class CoverArtImage:
|
||||
:counters: A dictionary mapping filenames to the amount of how many
|
||||
images with that filename were already saved in `dirname`.
|
||||
"""
|
||||
if not self.can_be_saved_to_disk:
|
||||
return
|
||||
if config.setting["caa_image_type_as_filename"]:
|
||||
filename = self.maintype
|
||||
log.debug("Make cover filename from types: %r -> %r",
|
||||
@@ -294,10 +304,13 @@ class CoverArtImage:
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
"""Reads the data from the temporary file created for this image. May
|
||||
raise IOErrors or OSErrors.
|
||||
"""Reads the data from the temporary file created for this image.
|
||||
May raise CoverArtImageIOError
|
||||
"""
|
||||
return self.datahash.data
|
||||
try:
|
||||
return self.datahash.data
|
||||
except (OSError, IOError) as e:
|
||||
raise CoverArtImageIOError(e)
|
||||
|
||||
@property
|
||||
def tempfile_filename(self):
|
||||
@@ -317,12 +330,35 @@ class CoverArtImage:
|
||||
|
||||
class CaaCoverArtImage(CoverArtImage):
|
||||
|
||||
"""Image from Cover Art Archive"""
|
||||
|
||||
support_types = True
|
||||
sourceprefix = u"CAA"
|
||||
|
||||
def __init__(self, url, types=[], is_front=False, comment='', data=None):
|
||||
CoverArtImage.__init__(self, url=url, types=types, comment=comment,
|
||||
data=data)
|
||||
self.is_front = is_front
|
||||
|
||||
|
||||
class CaaThumbnailCoverArtImage(CaaCoverArtImage):
|
||||
|
||||
"""Used for thumbnails of CaaCoverArtImage objects, together with thumbnail
|
||||
property"""
|
||||
|
||||
def __init__(self, url, types=[], is_front=False, comment='', data=None):
|
||||
CaaCoverArtImage.__init__(self, url=url, types=types, comment=comment,
|
||||
data=data)
|
||||
self.is_front = False
|
||||
self.can_be_saved_to_disk = False
|
||||
self.can_be_saved_to_tags = False
|
||||
self.can_be_saved_to_metadata = False
|
||||
|
||||
|
||||
class TagCoverArtImage(CoverArtImage):
|
||||
|
||||
"""Image from file tags"""
|
||||
|
||||
def __init__(self, file, tag=None, types=[], is_front=None,
|
||||
support_types=False, comment='', data=None):
|
||||
CoverArtImage.__init__(self, url=None, types=types, comment=comment,
|
||||
|
||||
@@ -27,7 +27,7 @@ import traceback
|
||||
from picard import config, log
|
||||
from picard.const import CAA_HOST, CAA_PORT
|
||||
from picard.coverartproviders import CoverArtProvider
|
||||
from picard.coverartimage import CaaCoverArtImage
|
||||
from picard.coverartimage import CaaCoverArtImage, CaaThumbnailCoverArtImage
|
||||
|
||||
|
||||
_CAA_THUMBNAIL_SIZE_MAP = {
|
||||
@@ -128,9 +128,16 @@ class CoverArtProviderCaa(CoverArtProvider):
|
||||
except ValueError:
|
||||
self.error("Invalid JSON: %s", http.url().toString())
|
||||
else:
|
||||
imagesize = config.setting["caa_image_size"]
|
||||
thumbsize = _CAA_THUMBNAIL_SIZE_MAP.get(imagesize, None)
|
||||
for image in caa_data["images"]:
|
||||
if config.setting["caa_approved_only"] and not image["approved"]:
|
||||
continue
|
||||
is_pdf = image["image"].endswith('.pdf')
|
||||
if is_pdf and not config.setting["save_images_to_files"]:
|
||||
log.debug("Skipping pdf cover art : %s" %
|
||||
image["image"])
|
||||
continue
|
||||
# if image has no type set, we still want it to match
|
||||
# pseudo type 'unknown'
|
||||
if not image["types"]:
|
||||
@@ -141,23 +148,29 @@ class CoverArtProviderCaa(CoverArtProvider):
|
||||
types = set(image["types"]).intersection(
|
||||
set(self.caa_types))
|
||||
if types:
|
||||
self._queue_from_caa(image)
|
||||
if thumbsize is None or is_pdf:
|
||||
url = image["image"]
|
||||
else:
|
||||
url = image["thumbnails"][thumbsize]
|
||||
coverartimage = CaaCoverArtImage(
|
||||
url,
|
||||
types=image["types"],
|
||||
is_front=image['front'],
|
||||
comment=image["comment"],
|
||||
)
|
||||
if is_pdf:
|
||||
# thumbnail will be used to "display" PDF in info
|
||||
# dialog
|
||||
thumbnail = CaaThumbnailCoverArtImage(
|
||||
url=image["thumbnails"]['small'],
|
||||
types=image["types"],
|
||||
is_front=image['front'],
|
||||
comment=image["comment"],
|
||||
)
|
||||
self.queue_put(thumbnail)
|
||||
coverartimage.thumbnail = thumbnail
|
||||
# PDFs cannot be saved to tags (as 2014/05/29)
|
||||
coverartimage.can_be_saved_to_tags = False
|
||||
self.queue_put(coverartimage)
|
||||
|
||||
self.next_in_queue()
|
||||
|
||||
def _queue_from_caa(self, image):
|
||||
"""Queue images depending on the CAA image size settings."""
|
||||
imagesize = config.setting["caa_image_size"]
|
||||
thumbsize = _CAA_THUMBNAIL_SIZE_MAP.get(imagesize, None)
|
||||
if thumbsize is None:
|
||||
url = image["image"]
|
||||
else:
|
||||
url = image["thumbnails"][thumbsize]
|
||||
coverartimage = CaaCoverArtImage(
|
||||
url,
|
||||
types=image["types"],
|
||||
comment=image["comment"],
|
||||
)
|
||||
# front image indicator from CAA
|
||||
coverartimage.is_front = bool(image['front'])
|
||||
self.queue_put(coverartimage)
|
||||
|
||||
@@ -55,13 +55,14 @@ class Metadata(dict):
|
||||
def images_to_be_saved_to_tags(self):
|
||||
if not config.setting["save_images_to_tags"]:
|
||||
return ()
|
||||
images = [img for img in self.images if img.can_be_saved_to_tags]
|
||||
if config.setting["save_only_front_images_to_tags"]:
|
||||
# FIXME : rename option at some point
|
||||
# Embed only ONE front image
|
||||
for img in self.images:
|
||||
for img in images:
|
||||
if img.is_front_image():
|
||||
return [img]
|
||||
return self.images
|
||||
return images
|
||||
|
||||
def remove_image(self, index):
|
||||
self.images.pop(index)
|
||||
|
||||
@@ -23,6 +23,7 @@ import traceback
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from picard import log
|
||||
from picard.coverartarchive import translate_caa_type
|
||||
from picard.coverartimage import CoverArtImageIOError
|
||||
from picard.util import format_time, encode_filename, bytes2human
|
||||
from picard.ui import PicardDialog
|
||||
from picard.ui.ui_infodialog import Ui_InfoDialog
|
||||
@@ -52,27 +53,36 @@ class InfoDialog(PicardDialog):
|
||||
return
|
||||
|
||||
for image in images:
|
||||
data = None
|
||||
try:
|
||||
data = image.data
|
||||
except (OSError, IOError) as e:
|
||||
if image.thumbnail:
|
||||
try:
|
||||
data = image.thumbnail.data
|
||||
except CoverArtImageIOError as e:
|
||||
log.warning(unicode(e))
|
||||
pass
|
||||
else:
|
||||
data = image.data
|
||||
except CoverArtImageIOError:
|
||||
log.error(traceback.format_exc())
|
||||
continue
|
||||
size = image.datalength
|
||||
item = QtGui.QListWidgetItem()
|
||||
pixmap = QtGui.QPixmap()
|
||||
pixmap.loadFromData(data)
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
item.setIcon(icon)
|
||||
s = u"%s (%s)\n%d x %d\n%s" % (
|
||||
bytes2human.decimal(size),
|
||||
bytes2human.binary(size),
|
||||
pixmap.width(),
|
||||
pixmap.height(),
|
||||
image.types_as_string()
|
||||
)
|
||||
if data is not None:
|
||||
pixmap = QtGui.QPixmap()
|
||||
pixmap.loadFromData(data)
|
||||
icon = QtGui.QIcon(pixmap)
|
||||
item.setIcon(icon)
|
||||
infos = []
|
||||
infos.append(image.types_as_string())
|
||||
if image.comment:
|
||||
s += u"\n%s" % image.comment
|
||||
item.setText(s)
|
||||
infos.append(image.comment)
|
||||
infos.append(u"%s (%s)" %
|
||||
(bytes2human.decimal(image.datalength),
|
||||
bytes2human.binary(image.datalength)))
|
||||
if image.width and image.height:
|
||||
infos.append(u"%d x %d" % (image.width, image.height))
|
||||
infos.append(image.mimetype)
|
||||
item.setText(u"\n".join(infos))
|
||||
item.setToolTip(image.source)
|
||||
self.ui.artwork_list.addItem(item)
|
||||
|
||||
|
||||
@@ -105,6 +105,12 @@ def identify(data):
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# PDF
|
||||
elif data[:4] == '%PDF':
|
||||
h, w = 0, 0
|
||||
mime = 'application/pdf'
|
||||
extension = '.pdf'
|
||||
|
||||
else:
|
||||
raise UnrecognizedFormat('Unrecognized image data')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user