diff --git a/beetsplug/ftintitle.py b/beetsplug/ftintitle.py index ef9b763cf..dd681a972 100644 --- a/beetsplug/ftintitle.py +++ b/beetsplug/ftintitle.py @@ -108,6 +108,7 @@ class FtInTitlePlugin(plugins.BeetsPlugin): "drop": False, "format": "feat. {}", "keep_in_artist": False, + "preserve_album_artist": True, "custom_words": [], } ) @@ -133,12 +134,19 @@ class FtInTitlePlugin(plugins.BeetsPlugin): self.config.set_args(opts) drop_feat = self.config["drop"].get(bool) keep_in_artist_field = self.config["keep_in_artist"].get(bool) + preserve_album_artist = self.config["preserve_album_artist"].get( + bool + ) custom_words = self.config["custom_words"].get(list) write = ui.should_write() for item in lib.items(args): if self.ft_in_title( - item, drop_feat, keep_in_artist_field, custom_words + item, + drop_feat, + keep_in_artist_field, + preserve_album_artist, + custom_words, ): item.store() if write: @@ -151,11 +159,16 @@ class FtInTitlePlugin(plugins.BeetsPlugin): """Import hook for moving featuring artist automatically.""" drop_feat = self.config["drop"].get(bool) keep_in_artist_field = self.config["keep_in_artist"].get(bool) + preserve_album_artist = self.config["preserve_album_artist"].get(bool) custom_words = self.config["custom_words"].get(list) for item in task.imported_items(): if self.ft_in_title( - item, drop_feat, keep_in_artist_field, custom_words + item, + drop_feat, + keep_in_artist_field, + preserve_album_artist, + custom_words, ): item.store() @@ -204,6 +217,7 @@ class FtInTitlePlugin(plugins.BeetsPlugin): item: Item, drop_feat: bool, keep_in_artist_field: bool, + preserve_album_artist: bool, custom_words: list[str], ) -> bool: """Look for featured artists in the item's artist fields and move @@ -218,7 +232,7 @@ class FtInTitlePlugin(plugins.BeetsPlugin): # Check whether there is a featured artist on this track and the # artist field does not exactly match the album artist field. In # that case, we attempt to move the featured artist to the title. - if albumartist and artist == albumartist: + if preserve_album_artist and albumartist and artist == albumartist: return False _, featured = split_on_feat(artist, custom_words=custom_words) diff --git a/docs/changelog.rst b/docs/changelog.rst index d7383abd3..cce30a284 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -10,7 +10,9 @@ Unreleased New features: - :doc:`plugins/ftintitle`: Added argument for custom feat. words in ftintitle. -- :doc: `/plugins/play`: Added `$playlist` marker to precisely edit the playlist +- :doc:`plugins/ftintitle`: Added argument to skip the processing of artist and + album artist are the same in ftintitle. +- :doc:`plugins/play`: Added `$playlist` marker to precisely edit the playlist filepath into the command calling the player program. Bug fixes: diff --git a/docs/plugins/ftintitle.rst b/docs/plugins/ftintitle.rst index 1a95d03a8..1d2ec5c20 100644 --- a/docs/plugins/ftintitle.rst +++ b/docs/plugins/ftintitle.rst @@ -28,6 +28,8 @@ file. The available options are: - **keep_in_artist**: Keep the featuring X part in the artist field. This can be useful if you still want to be able to search for features in the artist field. Default: ``no``. +- **preserve_album_artist**: If the artist and the album artist are the same, + skip the ftintitle processing. Default: ``yes``. - **custom_words**: List of additional words that will be treated as a marker for artist features. Default: ``[]``. diff --git a/test/plugins/test_ftintitle.py b/test/plugins/test_ftintitle.py index 30b414948..56c82b9d2 100644 --- a/test/plugins/test_ftintitle.py +++ b/test/plugins/test_ftintitle.py @@ -205,6 +205,47 @@ def add_item( ("Alice med Bob", "Song 1"), id="custom-feat-words-keep-in-artists-drop-from-title", ), + # ---- preserve_album_artist variants ---- + pytest.param( + { + "format": "feat. {}", + "preserve_album_artist": True, + }, + ("ftintitle",), + ("Alice feat. Bob", "Song 1", "Alice"), + ("Alice", "Song 1 feat. Bob"), + id="skip-if-artist-and-album-artists-is-the-same-different-match", + ), + pytest.param( + { + "format": "feat. {}", + "preserve_album_artist": False, + }, + ("ftintitle",), + ("Alice feat. Bob", "Song 1", "Alice"), + ("Alice", "Song 1 feat. Bob"), + id="skip-if-artist-and-album-artists-is-the-same-different-match-b", + ), + pytest.param( + { + "format": "feat. {}", + "preserve_album_artist": True, + }, + ("ftintitle",), + ("Alice feat. Bob", "Song 1", "Alice feat. Bob"), + ("Alice feat. Bob", "Song 1"), + id="skip-if-artist-and-album-artists-is-the-same-matching-match", + ), + pytest.param( + { + "format": "feat. {}", + "preserve_album_artist": False, + }, + ("ftintitle",), + ("Alice feat. Bob", "Song 1", "Alice feat. Bob"), + ("Alice", "Song 1 feat. Bob"), + id="skip-if-artist-and-album-artists-is-the-same-matching-match-b", + ), ], ) def test_ftintitle_functional(