diff --git a/beets/autotag/hooks.py b/beets/autotag/hooks.py index 212975182..d1f9e17bc 100644 --- a/beets/autotag/hooks.py +++ b/beets/autotag/hooks.py @@ -23,6 +23,7 @@ from typing import TYPE_CHECKING, Any, TypeVar from typing_extensions import Self +from beets import plugins from beets.util import cached_classproperty from beets.util.deprecation import deprecate_for_maintainers @@ -282,6 +283,10 @@ class AlbumMatch(Match): extra_items: list[Item] extra_tracks: list[TrackInfo] + def __post_init__(self) -> None: + """Notify listeners when an album candidate has been matched.""" + plugins.send("album_matched", match=self) + @property def item_info_pairs(self) -> list[tuple[Item, TrackInfo]]: return list(self.mapping.items()) diff --git a/beets/autotag/match.py b/beets/autotag/match.py index 53ed11186..d99369c01 100644 --- a/beets/autotag/match.py +++ b/beets/autotag/match.py @@ -24,7 +24,7 @@ from typing import TYPE_CHECKING, NamedTuple, TypeVar import lap import numpy as np -from beets import config, logging, metadata_plugins, plugins +from beets import config, logging, metadata_plugins from beets.autotag import AlbumMatch, TrackMatch, hooks from beets.util import get_most_common_tags @@ -275,8 +275,6 @@ def tag_album( log.debug("Searching for album IDs: {}", ", ".join(search_ids)) for _info in metadata_plugins.albums_for_ids(search_ids): _add_candidate(items, candidates, _info) - if opt_candidate := candidates.get(_info.identifier): - plugins.send("album_matched", match=opt_candidate) # Use existing metadata or text search. else: @@ -285,8 +283,6 @@ def tag_album( likelies["mb_albumid"], consensus["mb_albumid"] ): _add_candidate(items, candidates, info) - for candidate in candidates.values(): - plugins.send("album_matched", match=candidate) rec = _recommendation(list(candidates.values())) log.debug("Album ID match recommendation is {}", rec) @@ -321,8 +317,6 @@ def tag_album( items, search_artist, search_name, va_likely ): _add_candidate(items, candidates, matched_candidate) - if opt_candidate := candidates.get(matched_candidate.identifier): - plugins.send("album_matched", match=opt_candidate) log.debug("Evaluating {} candidates.", len(candidates)) # Sort and get the recommendation. diff --git a/docs/dev/plugins/events.rst b/docs/dev/plugins/events.rst index aaab9ccd7..ace7b9387 100644 --- a/docs/dev/plugins/events.rst +++ b/docs/dev/plugins/events.rst @@ -180,10 +180,9 @@ registration process in this case: ``album_matched`` :Parameters: ``match`` (``AlbumMatch``) - :Description: Called after ``Item`` objects from a folder that's being - imported have been matched to an ``AlbumInfo`` and the corresponding - distance has been calculated. Missing and extra tracks, if any, are - included in the match. + :Description: Called each time an ``AlbumMatch`` candidate is created while + importing. This applies to both ID-driven and text-search matching. + Missing and extra tracks, if any, are included in the match. ``before_choose_candidate`` :Parameters: ``task`` (|ImportTask|), ``session`` (|ImportSession|)