PLUGIN_NAME = 'MusicBee Compatibility'
PLUGIN_AUTHOR = 'Volker Zell (and Sophist)'
PLUGIN_DESCRIPTION = '''
Provide MusicBee compatible tags.
Note 1: The tags used by this plugin are only populated when you have
checked Options / Metadata / Use track relationships.
Note 2: You may wish to use this with the Copy to Comment plugin,
to which previous comment tag functionality has been moved.
Note 3: Info copied includes ALL Performers, as well as the
Composer, Producer, Mixer etc.
MusicBee: MusicBrainz tag: MusicBrainz source: Display Artist DISPLAY ARTIST artist Artists:Artist artist artists (or split of artist if not existing) Artists:Guest GUEST ARTIST taken from artist or title tags after feat./featuring/(feat./(featuring Artists:Performer PERFORMER performer:* Musician Credits List TMCL performer:* Involved People List IPLS 'Arranger', 'Engineer', 'Producer', 'Mixer', 'DJMixer', 'Remixer', 'Conductor' Comment comment: All the above Misc MISC 'CatalogNumber', 'Barcode', 'ASIN', 'ReleaseType', 'ReleaseStatus', 'ReleaseCountry'Note 4: I use the following additional entry in CustomTagConfig.xml for MusicBee
‹Tag id="Misc" id3v23="TXXX/MISC" id3v24="TXXX/MISC" wma="Misc" vorbisComments="Misc" mpeg="Misc" ape2="Misc" /›and a couple of Virtual Columns with the following structure (because I ran out of the 16 custom columns) to access the MISC entries:
Catalognumber = $Replace($First($Split(‹Misc›,Catalognumber:,2)),",",;)''' PLUGIN_VERSION = "0.7" PLUGIN_API_VERSIONS = ["0.15.0", "0.15.1", "0.16.0", "1.0.0", "1.1.0", "1.2.0", "1.3.0"] import re from picard import log from picard.metadata import register_track_metadata_processor class MusicBeeCompatibility: re_artist_split = re.compile(r",\s*|\s+&\s+|\s+and\s+|\s+feat[.:]\s+|\s+featuring\s+").split re_featured_split = re.compile(r"\s+\(?feat[.:]\s+|\s+featuring\s+").split def musicbee_compatibility(self, album, metadata, *args): self.re_artist_split = MusicBeeCompatibility.re_artist_split self.re_featured_split = MusicBeeCompatibility.re_featured_split self.populate_performers(metadata) self.populate_artist(metadata) self.populate_tipl(metadata) self.populate_misc(metadata) def populate_performers(self, metadata): performers = [] for name in [name for name in metadata if name.startswith('performer:')]: self.txxx_add(metadata, 'TMCL', name[10:].title(), name, '; ') performers += dict.get(metadata, name) metadata["PERFORMER"] = " \x00".join(set(performers)) def populate_artist(self, metadata): if 'artists' in metadata: artists = dict.get(metadata, "artists") elif 'artist' in metadata: artists = self.re_artist_split(metadata['artist']) else: return guests = [] if 'artist' in metadata: guest = self.re_featured_split(metadata['artist'], 1)[1:] if guest: guests += self.re_artist_split(guest[0].rstrip(')')) if 'title' in metadata: guest = self.re_featured_split(metadata['title'], 1)[1:] if guest: guests += self.re_artist_split(guest[0].rstrip(')')) artists = [x for x in artists if x not in guests] metadata["DISPLAY ARTIST"] = metadata["artist"] metadata["artist"] = " \x00".join(artists) metadata["GUEST ARTIST"] = " \x00".join(guests) def populate_tipl(self, metadata): for name in ['Arranger', 'Engineer', 'Producer', 'Mixer', 'DJMixer']: if name.lower() in metadata: metadata[name] = " \x00".join(dict.get(metadata, name.lower())) for name in ['Arranger', 'Engineer', 'Producer', 'Mixer', 'DJMixer', 'Remixer', 'Conductor']: self.txxx_add(metadata, 'IPLS', name, name, '; ') def populate_misc(self, metadata): for name in ['CatalogNumber', 'Barcode', 'ASIN', 'ReleaseType', 'ReleaseStatus', 'ReleaseCountry']: self.txxx_add(metadata, 'MISC', name, name, '; ') def txxx_add(self, metadata, tagname, label, name, joiner): name = name.lower() if not name in metadata: return tag = dict.get(metadata, name) value = ', '.join(tag) if label: label += ': ' if tagname in metadata: metadata[tagname] += joiner + label + value else: metadata[tagname] = label + value try: from picard.plugin import PluginPriority register_track_metadata_processor( MusicBeeCompatibility().musicbee_compatibility, priority=PluginPriority.LOW ) except ImportError: log.warning( "Running %r plugin on this Picard version may not work as you expect. " "This plugin should be run after other plugins and if it runs before " "some changes to metadata may be incorrect.", PLUGIN_NAME ) register_track_metadata_processor(MusicBeeCompatibility().musicbee_compatibility)