diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 3fdc627f4..cedaa3d90 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -182,12 +182,20 @@ def _album_for_id(album_id): return filter(None, candidates) def _track_for_id(track_id): - """Get an item for a recording MBID.""" + """Get an item for a recording ID.""" + candidates = [] + + # From MusicBrainz. try: - return mb.track_for_id(track_id) + candidates.append(mb.track_for_id(track_id)) except mb.MusicBrainzAPIError as exc: exc.log(log) + # From plugins. + candidates.extend(plugins.track_for_id(track_id)) + + return filter(None, candidates) + 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 diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 122066f5e..bcd3d040d 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -544,8 +544,7 @@ def tag_item(item, search_artist=None, search_title=None, trackid = search_id or item.mb_trackid if trackid: log.debug('Searching for track ID: ' + trackid) - track_info = hooks._track_for_id(trackid) - if track_info: + for track_info in hooks._track_for_id(trackid): dist = track_distance(item, track_info, incl_artist=True) candidates[track_info.track_id] = \ hooks.TrackMatch(dist, track_info) diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index c6a1d78d5..9a569c718 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -330,7 +330,6 @@ def _parse_id(s): match = re.search('[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}', s) if match: return match.group() - log.error('Invalid MBID.') def album_for_id(albumid): """Fetches an album by its MusicBrainz ID and returns an AlbumInfo @@ -339,6 +338,7 @@ def album_for_id(albumid): """ albumid = _parse_id(albumid) if not albumid: + log.error('Invalid MBID.') return try: res = musicbrainzngs.get_release_by_id(albumid, @@ -357,6 +357,7 @@ def track_for_id(trackid): """ trackid = _parse_id(trackid) if not trackid: + log.error('Invalid MBID.') return try: res = musicbrainzngs.get_recording_by_id(trackid, TRACK_INCLUDES) diff --git a/beets/plugins.py b/beets/plugins.py index f8d81bfe5..7d49ad3aa 100755 --- a/beets/plugins.py +++ b/beets/plugins.py @@ -102,8 +102,14 @@ class BeetsPlugin(object): return {} def album_for_id(self, album_id): - """Should return an AlbumInfo object or None if no matching release - was found. + """Return an AlbumInfo object or None if no matching release was + found. + """ + return None + + def track_for_id(self, track_id): + """Return a TrackInfo object or None if no matching release was + found. """ return None @@ -282,6 +288,16 @@ def album_for_id(album_id): out.append(res) return out +def track_for_id(track_id): + """Get TrackInfo objects for a given ID string. + """ + out = [] + for plugin in find_plugins(): + res = plugin.track_for_id(track_id) + if res: + out.append(res) + return out + def configure(config): """Sends the configuration object to each plugin.""" for plugin in find_plugins():