mirror of
https://github.com/beetbox/beets.git
synced 2025-12-06 08:39:17 +01:00
Add custom_tags_only mode for mbpseudo plugin
This commit is contained in:
parent
cb758988ed
commit
040b2dd940
3 changed files with 163 additions and 10 deletions
|
|
@ -20,6 +20,7 @@ import traceback
|
|||
from copy import deepcopy
|
||||
from typing import TYPE_CHECKING, Any, Iterable, Sequence
|
||||
|
||||
import mediafile
|
||||
import musicbrainzngs
|
||||
from typing_extensions import override
|
||||
|
||||
|
|
@ -49,10 +50,49 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
|
|||
|
||||
self._release_getter = musicbrainzngs.get_release_by_id
|
||||
|
||||
self.config.add({"scripts": []})
|
||||
self.config.add(
|
||||
{
|
||||
"scripts": [],
|
||||
"custom_tags_only": False,
|
||||
"album_custom_tags": {
|
||||
"album_transl": "album",
|
||||
"album_artist_transl": "artist",
|
||||
},
|
||||
"track_custom_tags": {
|
||||
"title_transl": "title",
|
||||
"artist_transl": "artist",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
self._scripts = self.config["scripts"].as_str_seq()
|
||||
self._log.debug("Desired scripts: {0}", self._scripts)
|
||||
|
||||
album_custom_tags = self.config["album_custom_tags"].get().keys()
|
||||
track_custom_tags = self.config["track_custom_tags"].get().keys()
|
||||
self._log.debug(
|
||||
"Custom tags for albums and tracks: {0} + {1}",
|
||||
album_custom_tags,
|
||||
track_custom_tags,
|
||||
)
|
||||
for custom_tag in album_custom_tags | track_custom_tags:
|
||||
if not isinstance(custom_tag, str):
|
||||
continue
|
||||
|
||||
media_field = mediafile.MediaField(
|
||||
mediafile.MP3DescStorageStyle(custom_tag),
|
||||
mediafile.MP4StorageStyle(
|
||||
f"----:com.apple.iTunes:{custom_tag}"
|
||||
),
|
||||
mediafile.StorageStyle(custom_tag),
|
||||
mediafile.ASFStorageStyle(custom_tag),
|
||||
)
|
||||
try:
|
||||
self.add_media_field(custom_tag, media_field)
|
||||
except ValueError:
|
||||
# ignore errors due to duplicates
|
||||
pass
|
||||
|
||||
self.register_listener("pluginload", self._on_plugins_loaded)
|
||||
self.register_listener("album_matched", self._adjust_final_album_match)
|
||||
|
||||
|
|
@ -107,6 +147,11 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
|
|||
pseudo_release = super().album_info(
|
||||
raw_pseudo_release["release"]
|
||||
)
|
||||
|
||||
if self.config["custom_tags_only"].get(bool):
|
||||
self._add_custom_tags(official_release, pseudo_release)
|
||||
return official_release
|
||||
else:
|
||||
return PseudoAlbumInfo(
|
||||
pseudo_release=_merge_pseudo_and_actual_album(
|
||||
pseudo_release, official_release
|
||||
|
|
@ -167,6 +212,23 @@ class MusicBrainzPseudoReleasePlugin(MusicBrainzPlugin):
|
|||
else:
|
||||
return None
|
||||
|
||||
def _add_custom_tags(
|
||||
self,
|
||||
official_release: AlbumInfo,
|
||||
pseudo_release: AlbumInfo,
|
||||
):
|
||||
for tag_key, pseudo_key in (
|
||||
self.config["album_custom_tags"].get().items()
|
||||
):
|
||||
official_release[tag_key] = pseudo_release[pseudo_key]
|
||||
|
||||
track_custom_tags = self.config["track_custom_tags"].get().items()
|
||||
for track, pseudo_track in zip(
|
||||
official_release.tracks, pseudo_release.tracks
|
||||
):
|
||||
for tag_key, pseudo_key in track_custom_tags:
|
||||
track[tag_key] = pseudo_track[pseudo_key]
|
||||
|
||||
def _adjust_final_album_match(self, match: AlbumMatch):
|
||||
album_info = match.info
|
||||
if isinstance(album_info, PseudoAlbumInfo):
|
||||
|
|
|
|||
|
|
@ -23,13 +23,18 @@ Since this plugin first searches for official releases from MusicBrainz, all
|
|||
options from the `musicbrainz` plugin's :ref:`musicbrainz-config` are supported,
|
||||
but they must be specified under `mbpseudo` in the configuration file.
|
||||
Additionally, the configuration expects an array of scripts that are desired for
|
||||
the pseudo-releases. Therefore, the minimum configuration for this plugin looks
|
||||
like this:
|
||||
the pseudo-releases. For ``artist`` in particular, keep in mind that even
|
||||
pseudo-releases might specify it with the original script, so you should also
|
||||
configure import :ref:`languages` to give artist aliases more priority.
|
||||
Therefore, the minimum configuration for this plugin looks like this:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
plugins: mbpseudo # remove musicbrainz
|
||||
|
||||
import:
|
||||
languages: en
|
||||
|
||||
mbpseudo:
|
||||
scripts:
|
||||
- Latn
|
||||
|
|
@ -37,7 +42,7 @@ like this:
|
|||
Note that the `search_limit` configuration applies to the initial search for
|
||||
official releases, and that the `data_source` in the database will be
|
||||
"MusicBrainz". Nevertheless, `data_source_mismatch_penalty` must also be
|
||||
specified under `mbpseudo` (see also
|
||||
specified under `mbpseudo` if desired (see also
|
||||
:ref:`metadata-source-plugin-configuration`). An example with multiple data
|
||||
sources may look like this:
|
||||
|
||||
|
|
@ -45,6 +50,9 @@ sources may look like this:
|
|||
|
||||
plugins: mbpseudo deezer
|
||||
|
||||
import:
|
||||
languages: en
|
||||
|
||||
mbpseudo:
|
||||
data_source_mismatch_penalty: 0
|
||||
scripts:
|
||||
|
|
@ -52,3 +60,44 @@ sources may look like this:
|
|||
|
||||
deezer:
|
||||
data_source_mismatch_penalty: 0.2
|
||||
|
||||
By default, the data from the pseudo-release will be used to create a proposal
|
||||
that is independent from the official release and sets all properties in its
|
||||
metadata. It's possible to change the configuration so that some information
|
||||
from the pseudo-release is instead added as custom tags, keeping the metadata
|
||||
from the official release:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
mbpseudo:
|
||||
# other config not shown
|
||||
custom_tags_only: yes
|
||||
|
||||
The default custom tags with this configuration are specified as mappings where
|
||||
the keys define the tag names and the values define the pseudo-release property
|
||||
that will be used to set the tag's value:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
mbpseudo:
|
||||
album_custom_tags:
|
||||
album_transl: album
|
||||
album_artist_transl: artist
|
||||
track_custom_tags:
|
||||
title_transl: title
|
||||
artist_transl: artist
|
||||
|
||||
Note that the information for each set of custom tags corresponds to different
|
||||
metadata levels (album or track level), which is why ``artist`` appears twice
|
||||
even though it effectively references album artist and track artist
|
||||
respectively.
|
||||
|
||||
If you want to modify any mapping under ``album_custom_tags`` or
|
||||
``track_custom_tags``, you must specify *everything* for that set of tags in
|
||||
your configuration file because any customization replaces the whole dictionary
|
||||
of mappings for that level.
|
||||
|
||||
.. note::
|
||||
|
||||
These custom tags are also added to the music files, not only to the
|
||||
database.
|
||||
|
|
|
|||
|
|
@ -223,3 +223,45 @@ class TestMBPseudoPlugin(PluginMixin):
|
|||
assert match.info.data_source == "MusicBrainz"
|
||||
assert match.info.album_id == "pseudo"
|
||||
assert match.info.album == "In Bloom"
|
||||
|
||||
|
||||
class TestMBPseudoPluginCustomTagsOnly(PluginMixin):
|
||||
plugin = "mbpseudo"
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def mbpseudo_plugin(self) -> MusicBrainzPseudoReleasePlugin:
|
||||
self.config["import"]["languages"] = ["en", "jp"]
|
||||
self.config[self.plugin]["scripts"] = ["Latn"]
|
||||
self.config[self.plugin]["custom_tags_only"] = True
|
||||
return MusicBrainzPseudoReleasePlugin()
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def official_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
||||
info_json = (rsrc_dir / "official_release.json").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
return json.loads(info_json)
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def pseudo_release(self, rsrc_dir: pathlib.Path) -> JSONDict:
|
||||
info_json = (rsrc_dir / "pseudo_release.json").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
return json.loads(info_json)
|
||||
|
||||
def test_custom_tags(
|
||||
self,
|
||||
mbpseudo_plugin: MusicBrainzPseudoReleasePlugin,
|
||||
official_release: JSONDict,
|
||||
pseudo_release: JSONDict,
|
||||
):
|
||||
mbpseudo_plugin._release_getter = (
|
||||
lambda album_id, includes: pseudo_release
|
||||
)
|
||||
album_info = mbpseudo_plugin.album_info(official_release["release"])
|
||||
assert not isinstance(album_info, PseudoAlbumInfo)
|
||||
assert album_info.data_source == "MusicBrainzPseudoRelease"
|
||||
assert album_info["album_transl"] == "In Bloom"
|
||||
assert album_info["album_artist_transl"] == "Lilas Ikuta"
|
||||
assert album_info.tracks[0]["title_transl"] == "In Bloom"
|
||||
assert album_info.tracks[0]["artist_transl"] == "Lilas Ikuta"
|
||||
|
|
|
|||
Loading…
Reference in a new issue