diff --git a/beets/autotag/__init__.py b/beets/autotag/__init__.py index d2d444fbc..9f76155be 100644 --- a/beets/autotag/__init__.py +++ b/beets/autotag/__init__.py @@ -15,10 +15,10 @@ """Facilities for automatically determining files' correct metadata. """ import os +import logging from beets import library, mediafile from beets.util import sorted_walk -from . import mb # Parts of external interface. from .hooks import AlbumInfo, TrackInfo @@ -26,6 +26,9 @@ from .match import tag_item, tag_album from .match import RECOMMEND_STRONG, RECOMMEND_MEDIUM, RECOMMEND_NONE from .match import STRONG_REC_THRESH, MEDIUM_REC_THRESH, REC_GAP_THRESH +# Global logger. +log = logging.getLogger('beets') + # Additional utilities for the main interface. diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index b6da29a9d..4918ac85f 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -14,6 +14,7 @@ """Glue between metadata sources and the matching logic.""" +from beets import plugins from . import mb # Classes used to represent candidate options. @@ -77,13 +78,46 @@ class TrackInfo(object): # Aggregation of sources. def _album_for_id(album_id): + """Get an album corresponding to a MusicBrainz release ID.""" return mb.album_for_id(album_id) -def _match_album(artist, album, tracks): - return mb.match_album(artist, album, tracks) - def _track_for_id(track_id): + """Get an item for a recording MBID.""" return mb.track_for_id(track_id) -def _match_track(artist, title): - return mb.match_track(artist, title) +def _album_candidates(items, artist, album, va_likely): + """Search for album matches. ``items`` is a list of Item objects + that make up the album. ``artist`` and ``album`` are the respective + names (strings), which may be derived from the item list or may be + entered by the user. ``va_likely`` is a boolean indicating whether + the album is likely to be a "various artists" release. + """ + out = [] + + # Base candidates if we have album and artist to match. + if artist and album: + out.extend(mb.match_album(artist, album, len(items))) + + # Also add VA matches from MusicBrainz where appropriate. + if va_likely and album: + out.extend(mb.match_album(None, album, len(items))) + + # Candidates from plugins. + out.extend(plugins.candidates(items)) + + return out + +def _item_candidates(item, artist, title): + """Search for item matches. ``item`` is the Item to be matched. + ``artist`` and ``title`` are strings and either reflect the item or + are specified by the user. + """ + out = [] + + # MusicBrainz candidates. + out.extend(mb.match_track(artist, title)) + + # Plugin candidates. + out.extend(plugins.item_candidates(item)) + + return out diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 49e245e8a..2aa5cbd24 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -420,23 +420,15 @@ def tag_album(items, timid=False, search_artist=None, search_album=None, search_artist, search_album = cur_artist, cur_album log.debug(u'Search terms: %s - %s' % (search_artist, search_album)) - # Get candidate metadata from search. - if search_artist and search_album: - candidates = hooks._match_album(search_artist, search_album, - len(items)) - candidates = list(candidates) - else: - candidates = [] + # Is this album likely to be a "various artist" release? + va_likely = ((not artist_consensus) or + (search_artist.lower() in VA_ARTISTS) or + any(item.comp for item in items)) + log.debug(u'Album might be VA: %s' % str(va_likely)) - # Possibly add "various artists" search. - if search_album and ((not artist_consensus) or \ - (search_artist.lower() in VA_ARTISTS) or \ - any(item.comp for item in items)): - log.debug(u'Possibly Various Artists; adding matches.') - candidates.extend(hooks._match_album(None, search_album, len(items))) - - # Get candidates from plugins. - candidates.extend(plugins.candidates(items)) + # Get the results from the data sources. + candidates = hooks._album_candidates(items, search_artist, search_album, + va_likely) # Get the distance to each candidate. log.debug(u'Evaluating %i candidates.' % len(candidates)) @@ -486,13 +478,8 @@ def tag_item(item, timid=False, search_artist=None, search_title=None, search_artist, search_title = item.artist, item.title log.debug(u'Item search terms: %s - %s' % (search_artist, search_title)) - # Candidate metadata from search. - for track_info in hooks._match_track(search_artist, search_title): - dist = track_distance(item, track_info, incl_artist=True) - candidates.append((dist, track_info)) - - # Add candidates from plugins. - for track_info in plugins.item_candidates(item): + # Get and evaluate candidate metadata. + for track_info in hooks._item_candidates(item, search_artist, search_title): dist = track_distance(item, track_info, incl_artist=True) candidates.append((dist, track_info))