beets/beetsplug/coverart.py
2014-08-14 11:06:55 +02:00

118 lines
4.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# This file is part of beets.
# Copyright 2014, Thomas Scholtes.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
COVERTYPE = enum([
'front',
'back',
# TODO extend. The ID3v2 types [1] might be a good starting point,
# but I find them a bit convoluted. MusicBrainz [2] is also a good
# source.
#
# [1]: http://en.wikipedia.org/wiki/ID3#ID3v2_Embedded_Image_Extension
# [2]: http://musicbrainz.org/doc/Cover_Art/Types
], name='COVERTYPE')
"""Enumeration of known types of cover art.
The string representation is stored in the 'covertype' metadata field of
an attachment.
"""
class CoverArtPlugin(BeetsPlugin):
"""Registers ``coverart`` attachment type and command.
"""
def attachment_commands(self):
return [CoverArtCommand]
def attachment_discover(self, path):
# FIXME mock code, simpler to check file extension
mime_type = get_mime_type_from_file(path)
if mime_type.startswith('image/'):
return 'coverart'
def attachment_collect(self, type, path):
if type != 'coverart':
return
# FIXME mock code
metadata = {}
if basename(path).startwith('front'):
metadata['covertype'] = 'front'
elif basenmae(path).startswith('back'):
metadata['covertype'] = 'back'
width, height = get_image_resolution(path)
metadata['width'] = width
metadata['height'] = width
metadata['mime'] = get_mime_type_from_file(path)
return metadata
class CoverArtCommand(AttachmentCommand):
name = 'coverart'
# This is set by beets when instantiating the command
factory = None
def add_arguments(self):
# TODO add options and arguments through the ArgumentParser
# interface.
raise NotImplementedError
def run(self, argv, options):
"""Dispatch invocation to ``attach()`` or ``list()``.
"""
album_query = query_from_args(argv)
if options.attach:
# -a option creates attachments
self.attach(album_query, path=options.attach,
covertype=options.type, local=options.local)
else:
# list covers of a particular type
self.list(album_query, covertype=options.type)
def attach(self, query, path, covertype=None, local=False):
"""Attaches ``path`` as coverart to all albums matching ``query``.
:param covertype: Set the covertype of the attachment.
:param local: If true, path is relative to each albums directory.
"""
# TODO implement `embed` option to write images to tags. Since
# the `MediaFile` class doesn't support multiple images at the
# moment we have to implement it there first.
for album in albums_from_query(query):
if local:
localpath = join(album.path, path)
else:
localpath = path
attachment = self.factory.create_from_type(localpath,
entity=album, type='coverart')
if covertype:
attachment.meta['covertype'] = covertype
attachment.move(cover_art_destination(attachment))
attachment.store()
def list(query, covertype=None):
"""Print list of coverart attached to albums matching ``query``.
:param covertype: Restrict the list to coverart of this type.
"""
for attachment in self.factory.find(TypeQuery('coverart'), query):
if covertype is None:
print_attachment(attachment)
elif attachment.meta['covertype'] == covertype:
print_attachment(attachment)