diff --git a/picard/file.py b/picard/file.py index 4d05e4afd..847ce6531 100644 --- a/picard/file.py +++ b/picard/file.py @@ -4,7 +4,7 @@ # # Copyright (C) 2004 Robert Kaye # Copyright (C) 2006-2009, 2011-2013, 2017 Lukáš Lalinský -# Copyright (C) 2007-2011, 2015, 2018-2020 Philipp Wolfer +# Copyright (C) 2007-2011, 2015, 2018-2021 Philipp Wolfer # Copyright (C) 2008 Gary van der Merwe # Copyright (C) 2008-2009 Nikolai Prokoschenko # Copyright (C) 2009 Carlin Mangar @@ -157,7 +157,20 @@ class File(QtCore.QObject, Item): return '<%s %r>' % (type(self).__name__, self.base_filename) # pylint: disable=no-self-use - def format_specific_metadata(self, metadata, tag): + def format_specific_metadata(self, metadata, tag, settings=None): + """Can be overridden to customize how a tag is displayed in the UI. + This is useful if a tag saved to the underlying format will differ from + the internal representation in a way that would cause data loss. This is e.g. + the case for some ID3v2.3 tags. + + Args: + metadata: The metadata object to read the tag from + tag: Name of the tag + settings: Dictionary of settings. If not set, config.setting should be used + + Returns: + An array of values for the tag + """ return metadata.getall(tag) def load(self, callback): diff --git a/picard/formats/id3.py b/picard/formats/id3.py index 75fc19ad1..b9c49bda0 100644 --- a/picard/formats/id3.py +++ b/picard/formats/id3.py @@ -3,7 +3,7 @@ # Picard, the next-generation MusicBrainz tagger # # Copyright (C) 2006-2009, 2011-2012 Lukáš Lalinský -# Copyright (C) 2008-2011, 2014, 2018-2020 Philipp Wolfer +# Copyright (C) 2008-2011, 2014, 2018-2021 Philipp Wolfer # Copyright (C) 2009 Carlin Mangar # Copyright (C) 2011-2012 Johannes Weißl # Copyright (C) 2011-2014 Michael Wiencek @@ -650,12 +650,16 @@ class ID3File(File): tags.update_to_v24() tags.save(filename, v2_version=4, v1=v1) - def format_specific_metadata(self, metadata, tag): - config = get_config() - if not config.setting["write_id3v23"]: - return super().format_specific_metadata(metadata, tag) + def format_specific_metadata(self, metadata, tag, settings=None): + if not settings: + config = get_config() + settings = { + "write_id3v23": config.setting["write_id3v23"], + "id3v23_join_with": config.setting["id3v23_join_with"], + } - join_with = config.setting["id3v23_join_with"] + if not settings["write_id3v23"]: + return super().format_specific_metadata(metadata, tag, settings) values = metadata.getall(tag) if not values: @@ -670,6 +674,7 @@ class ID3File(File): # unless it's TIPL or TMCL which can still be multi-valued. if (len(values) > 1 and tag not in ID3File._rtipl_roles and not tag.startswith("performer:")): + join_with = settings["id3v23_join_with"] values = [join_with.join(values)] return values diff --git a/picard/ui/metadatabox.py b/picard/ui/metadatabox.py index b95b568e0..3b925e1c5 100644 --- a/picard/ui/metadatabox.py +++ b/picard/ui/metadatabox.py @@ -585,14 +585,19 @@ class MetadataBox(QtWidgets.QTableWidget): top_tags = config.setting['metadatabox_top_tags'] top_tags_set = set(top_tags) + format_settings = { + "write_id3v23": config.setting["write_id3v23"], + "id3v23_join_with": config.setting["id3v23_join_with"], + } + for file in files: new_metadata = file.metadata orig_metadata = file.orig_metadata tags = set(list(new_metadata.keys()) + list(orig_metadata.keys())) for name in filter(lambda x: not x.startswith("~") and file.supports_tag(x), tags): - new_values = file.format_specific_metadata(new_metadata, name) - orig_values = file.format_specific_metadata(orig_metadata, name) + new_values = file.format_specific_metadata(new_metadata, name, format_settings) + orig_values = file.format_specific_metadata(orig_metadata, name, format_settings) if not clear_existing_tags and not new_values: new_values = list(orig_values or [""]) diff --git a/test/formats/test_id3.py b/test/formats/test_id3.py index 862bf9bfa..86bf6030f 100644 --- a/test/formats/test_id3.py +++ b/test/formats/test_id3.py @@ -668,3 +668,11 @@ class ID3FileTest(PicardTestCase): metadata = self.file.metadata metadata['date'] = '2021-04' self.assertEqual(['2021'], self.file.format_specific_metadata(metadata, 'date')) + + def test_format_specific_metadata_override_settings(self): + settings = { + 'write_id3v23': True, + 'id3v23_join_with': '; ', + } + metadata = self.file.metadata + self.assertEqual(['foo; bar'], self.file.format_specific_metadata(metadata, 'artist', settings))