Skip to content

Commit 1224d68

Browse files
committed
Rework local cover art handling
Local cover art as a provider doesn't make sense - local cover art is a property of a file, same as tag cover art. Move the handling of local cover art to the File class. TODO: Need to resolve how to configure load ordering of tag cover art vs local cover art. Also, there needs to be a config ui written. In the current state, the local_cover_regex setting is re-used, and a new load_local_cover_art boolean is used to enable the feature. This will probably fix many of the causes of PICARD-1001.
1 parent d5f131d commit 1224d68

File tree

5 files changed

+54
-208
lines changed

5 files changed

+54
-208
lines changed

picard/coverart/image.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,3 +480,6 @@ def __init__(self, filepath, types=None, comment='',
480480
super().__init__(url=url, types=types, comment=comment)
481481
self.support_types = support_types
482482
self.support_multi_types = support_multi_types
483+
path = url.toLocalFile()
484+
with open(path, 'rb') as file:
485+
self.set_data(file.read())

picard/coverart/providers/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from picard.coverart.providers.caa_release_group import (
3636
CoverArtProviderCaaReleaseGroup,
3737
)
38-
from picard.coverart.providers.local import CoverArtProviderLocal
3938
from picard.coverart.providers.provider import ( # noqa: F401 # pylint: disable=unused-import
4039
CoverArtProvider,
4140
ProviderOptions,
@@ -92,7 +91,6 @@ def label(p):
9291

9392

9493
__providers = [
95-
CoverArtProviderLocal,
9694
CoverArtProviderCaa,
9795
CoverArtProviderUrlRelationships,
9896
CoverArtProviderCaaReleaseGroup,

picard/coverart/providers/local.py

Lines changed: 0 additions & 123 deletions
This file was deleted.

picard/file.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@
6363
IS_MACOS,
6464
IS_WIN,
6565
)
66+
from picard.coverart.image import (
67+
CoverArtImageError,
68+
LocalFileCoverArtImage
69+
)
70+
from picard.coverart.utils import CAA_TYPES
6671
from picard.metadata import (
6772
Metadata,
6873
SimMatchTrack,
@@ -240,6 +245,10 @@ def _loading_finished(self, callback, result=None, error=None):
240245
postprocessors = []
241246
if config.setting["guess_tracknumber_and_title"]:
242247
postprocessors.append(self._guess_tracknumber_and_title)
248+
# If no cover art was loaded from file tags, try loading from a local file
249+
# TODO: should this be a preference? should we load from both sources?
250+
if config.setting["load_local_cover_art"] and len(result.images) == 0:
251+
self._load_local_cover_art(result, config)
243252
self._copy_loaded_metadata(result, postprocessors)
244253
# use cached fingerprint from file metadata
245254
if not config.setting["ignore_existing_acoustid_fingerprints"]:
@@ -250,6 +259,48 @@ def _loading_finished(self, callback, result=None, error=None):
250259
self.update()
251260
callback(self)
252261

262+
_types_split_re = re.compile('[^a-z0-9]', re.IGNORECASE)
263+
_known_types = set([t['name'] for t in CAA_TYPES])
264+
_default_types = ['front']
265+
266+
def get_types(self, string):
267+
found = set([x.lower() for x in self._types_split_re.split(string) if x])
268+
return list(found.intersection(self._known_types))
269+
270+
def _load_local_cover_art(self, metadata, config):
271+
log.debug("Attempting to load cover art from local files")
272+
match_re = re.compile(config.setting['local_cover_regex'], re.IGNORECASE)
273+
current_dir = os.path.dirname(self.filename)
274+
for root, dirs, files in os.walk(current_dir):
275+
for filename in files:
276+
m = match_re.search(filename)
277+
if not m:
278+
continue
279+
filepath = os.path.join(current_dir, root, filename)
280+
if not os.path.exists(filepath):
281+
continue
282+
try:
283+
type_from_filename = self.get_types(m.group(1))
284+
except IndexError:
285+
type_from_filename = []
286+
try:
287+
coverartimage = LocalFileCoverArtImage(
288+
filepath,
289+
types=type_from_filename or self._default_types,
290+
support_types=True,
291+
support_multi_types=True
292+
)
293+
294+
log.debug("Loaded local cover art image: %r", coverartimage)
295+
except OSError as exc:
296+
(errnum, errmsg) = exc.args
297+
log.error("Failed to read %r: %s (%d)" %
298+
(filepath, errmsg, errnum))
299+
except (CoverArtImageError) as e:
300+
log.error('Cannot load image from %r: %s' % (filename, e))
301+
else:
302+
metadata.images.append(coverartimage)
303+
253304
def _copy_loaded_metadata(self, metadata, postprocessors=None):
254305
metadata['~length'] = format_time(metadata.length)
255306
if postprocessors:

ui/provider_options_local.ui

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)