forked from metabrainz/picard-plugins
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from metabrainz/1.0
Update from original
- Loading branch information
Showing
5 changed files
with
371 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,4 @@ | ||
language: python | ||
python: | ||
- "2.6" | ||
- "2.7" | ||
# - "3.2" | ||
- "3.3" | ||
- "3.4" | ||
script: python test.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
plugins/abbreviate_artistsort2/abbreviate_artistsort2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
#!/usr/bin/env python2 | ||
# -*- coding: utf-8 -*- | ||
|
||
# This is the Abbreviate Artist plugin for MusicBrainz Picard. | ||
# Copyright (C) 2013-2017 Sophist | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU General Public License | ||
# as published by the Free Software Foundation; either version 2 | ||
# of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
# GNU General Public License for more details. | ||
|
||
PLUGIN_NAME = u"Abbreviate Artist-Sort v2" | ||
PLUGIN_AUTHOR = u"Sophist" | ||
PLUGIN_DESCRIPTION = u''' | ||
Abbreviate Artist-Sort and Album-Artist-Sort Tags. | ||
e.g. "Vivaldi, Antonio" becomes "Vivaldi A" | ||
This is particularly useful for classical albums that can have a long list of artists. | ||
This version of the plugin differs from version 1 as it modifies the relevant metadata | ||
in place (rather than copying it into new variables. | ||
''' | ||
PLUGIN_VERSION = "1.0" | ||
PLUGIN_API_VERSIONS = ["1.4"] | ||
PLUGIN_LICENSE = "GPL-2.0" | ||
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html" | ||
|
||
import re, unicodedata | ||
|
||
artist_tags = [ | ||
('artistsort', '~artists_sort', '~unabbrev_artistsort', '~unabbrev_artists_sort'), | ||
('albumartistsort', '~albumartists_sort', '~unabbrev_albumartistsort', '~unabbrev_albumartists_sort'), | ||
] | ||
|
||
def abbreviate_name(artist): | ||
if u"," not in artist: | ||
return artist | ||
surname, forenames = artist.split(u",", 1) | ||
return surname + u" " + "".join([x[0] for x in re.split(ur"\W+", forenames.strip())]) | ||
|
||
def string_cleanup(string, locale="utf-8"): | ||
if not string: | ||
return u"" | ||
if not isinstance(string, unicode): | ||
string = string.decode(locale) | ||
# Replace with normalised unicode string | ||
return unicodedata.normalize("NFKC", string) | ||
|
||
def abbreviate_artist(artist, locale="utf-8"): | ||
"""Title-case a string using a less destructive method than str.title.""" | ||
return abbreviate_name(string_cleanup(artist, locale)) | ||
|
||
assert "Bach JS" == abbreviate_artist("Bach, Johann Sebastian") | ||
assert "The Beatles" == abbreviate_artist("The Beatles") | ||
|
||
def abbreviate_artistsort(text, artists, abbrev_artists): | ||
""" | ||
Use the array of artists and the joined string | ||
to identify artists to make title case | ||
and the join strings to leave as-is. | ||
""" | ||
find = u"^(" + ur")(\s*\S+\s*)(".join((map(re.escape, map(string_cleanup,artists)))) + u")(.*$)" | ||
replace = "".join([ur"%s\%d" % (a, x*2 + 2) for x, a in enumerate(abbrev_artists)]) | ||
result = re.sub(find, replace, string_cleanup(text), re.UNICODE) | ||
return result | ||
|
||
assert "Bach JS; London Symphony Orchestra" == abbreviate_artistsort( | ||
"Bach, Johann Sebastian; London Symphony Orchestra", | ||
["Bach, Johann Sebastian", "London Symphony Orchestra"], | ||
["Bach JS", "London Symphony Orchestra"], | ||
) | ||
|
||
# Put this here so that above unit tests can run standalone before getting an import error | ||
from picard import log | ||
from picard.metadata import ( | ||
register_track_metadata_processor, | ||
register_album_metadata_processor, | ||
) | ||
|
||
def abbrev_artistsort_metadata(tagger, metadata, release, track=None): | ||
for artist_string, artists_list, original_artist, original_artists in artist_tags: | ||
if artist_string in metadata and artists_list in metadata: | ||
artists = metadata.getall(artists_list) | ||
artist = metadata.getall(artist_string) | ||
abbrev_artists = map(abbreviate_artist, artists) | ||
abbrev_artist = [abbreviate_artistsort(x, artists, abbrev_artists) for x in artist] | ||
if artists != abbrev_artists and artist != abbrev_artist: | ||
log.debug("AbbrevArtistSort2: Abbreviated %s from %r to %r", artists_list, artists, abbrev_artists) | ||
metadata[original_artists] = artists | ||
metadata[artists_list] = abbrev_artists | ||
log.debug("AbbrevArtistSort2: Abbreviated %s from %r to %r", artist_string, artist, abbrev_artist) | ||
metadata[original_artist] = artist | ||
metadata[artist_string] = abbrev_artist | ||
elif artists != abbrev_artists or artist != abbrev_artist: | ||
if artists != abbrev_artists: | ||
log.warning("AbbrevArtistSort2: %s abbreviated, %s wasn't", artists_list, artist_string) | ||
else: | ||
log.warning("AbbrevArtistSort2: %s abbreviated, %s wasn't", artist_string, artists_list) | ||
|
||
register_track_metadata_processor(abbrev_artistsort_metadata) | ||
register_album_metadata_processor(abbrev_artistsort_metadata) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
PLUGIN_NAME = 'AlbumArtist Extension' | ||
PLUGIN_AUTHOR = 'Bob Swift (rdswift)' | ||
PLUGIN_DESCRIPTION = ''' | ||
This plugin provides standardized, credited and sorted artist information | ||
for the album artist. This is useful when your tagging or renaming scripts | ||
require both the standardized artist name and the credited artist name, or | ||
more detailed information about the album artists. | ||
<br /><br /> | ||
The information is provided in the following variables: | ||
<ul> | ||
<li>_aaeStdAlbumArtists = The standardized version of the album artists. | ||
<li>_aaeCredAlbumArtists = The credited version of the album artists. | ||
<li>_aaeSortAlbumArtists = The sorted version of the album artists. | ||
<li>_aaeStdPrimaryAlbumArtist = The standardized version of the first | ||
(primary) album artist. | ||
<li>_aaeCredPrimaryAlbumArtist = The credited version of the first (primary) | ||
album artist. | ||
<li>_aaeSortPrimaryAlbumArtist = The sorted version of the first (primary) | ||
album artist. | ||
<li>_aaeAlbumArtistCount = The number of artists comprising the album artist. | ||
</ul> | ||
PLEASE NOTE: Tagger scripts are required to make use of these hidden | ||
variables. | ||
''' | ||
|
||
PLUGIN_VERSION = "0.5" | ||
PLUGIN_API_VERSIONS = ["1.4"] | ||
PLUGIN_LICENSE = "GPL-2.0 or later" | ||
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html" | ||
|
||
from picard import config, log | ||
from picard.metadata import register_album_metadata_processor | ||
from picard.plugin import PluginPriority | ||
|
||
class AlbumArtistStdName: | ||
|
||
@staticmethod | ||
def add_artist_std_name(album, album_metadata, releaseXmlNode): | ||
albumid = releaseXmlNode.id | ||
# Test for valid XML node for the release | ||
if 'artist_credit' in releaseXmlNode.children: | ||
# Initialize variables to default values | ||
credArtist = "" | ||
stdArtist = "" | ||
sortArtist = "" | ||
aCount = 0 | ||
# Get the current lists of _albumartists and _albumartists_sort | ||
metaAlbumArtists = dict.get(album_metadata,"~albumartists") | ||
metaAlbumArtists_Sort = dict.get(album_metadata,"~albumartists_sort") | ||
# The 'name_credit' child should always be there. | ||
# This check is to avoid a runtime error if it doesn't exist for some reason. | ||
if 'name_credit' in releaseXmlNode.artist_credit[0].children: | ||
for ncredit in releaseXmlNode.artist_credit[0].name_credit: | ||
# Initialize temporary variables for each loop. | ||
tempStdName = "" | ||
tempCredName = "" | ||
tempSortName = "" | ||
tempPhrase = "" | ||
# Check if there is a 'joinphrase' specified. | ||
if 'joinphrase' in ncredit.attribs: | ||
tempPhrase = ncredit.joinphrase | ||
# Set the credit name from the AlbumArtist list if the | ||
# 'Use standardized artist name' option is not checked | ||
# in Picard, otherwise use the XML information. | ||
if config.setting["standardize_artists"]: | ||
# Check if there is a 'name' specified. This will be the | ||
# credited name. | ||
if 'name' in ncredit.children: | ||
tempCredName = ncredit.name[0].text | ||
else: | ||
tempCredName = metaAlbumArtists[aCount] | ||
# The 'artist' child should always be there. | ||
# This check is to avoid a runtime error if it doesn't | ||
# exist for some reason. | ||
if 'artist' in ncredit.children: | ||
# The 'name' child should always be there. | ||
# This check is to avoid a runtime error if it | ||
# doesn't exist for some reason. | ||
if 'name' in ncredit.artist[0].children: | ||
# Set the standardized name from the AlbumArtist | ||
# list if the 'Use standardized artist name' | ||
# option is checked in Picard, otherwise use the | ||
# XML information. | ||
tempStdName = metaAlbumArtists[aCount] if config.setting["standardize_artists"] else ncredit.artist[0].name[0].text | ||
stdArtist += tempStdName + tempPhrase | ||
tCredName = tempCredName if len(tempCredName) > 0 else tempStdName | ||
credArtist += tCredName + tempPhrase | ||
if aCount < 1: | ||
album_metadata["~aaeStdPrimaryAlbumArtist"] = tempStdName | ||
album_metadata["~aaeCredPrimaryAlbumArtist"] = tCredName | ||
else: | ||
log.error("%s: %r: Missing artist 'name' in XML contents: %s", | ||
PLUGIN_NAME, albumid, releaseXmlNode) | ||
# Get the artist sort name from the | ||
# _albumartists_sort list | ||
tempSortName = metaAlbumArtists_Sort[aCount] | ||
sortArtist += tempSortName + tempPhrase | ||
if aCount < 1: | ||
album_metadata["~aaeSortPrimaryAlbumArtist"] = tempSortName | ||
else: | ||
log.error("%s: %r: Missing 'artist' in XML contents: %s", | ||
PLUGIN_NAME, albumid, releaseXmlNode) | ||
aCount += 1 | ||
else: | ||
log.error("%s: %r: Missing 'name_credit' in XML contents: %s", | ||
PLUGIN_NAME, albumid, releaseXmlNode) | ||
if len(stdArtist) > 0: | ||
album_metadata["~aaeStdAlbumArtists"] = stdArtist | ||
if len(credArtist) > 0: | ||
album_metadata["~aaeCredAlbumArtists"] = credArtist | ||
if len(sortArtist) > 0: | ||
album_metadata["~aaeSortAlbumArtists"] = sortArtist | ||
if aCount > 0: | ||
album_metadata["~aaeAlbumArtistCount"] = aCount | ||
else: | ||
log.error("%s: %r: Error reading XML contents: %s", | ||
PLUGIN_NAME, albumid, releaseXmlNode) | ||
return None | ||
|
||
# Register the plugin to run at a LOW priority so that other plugins that | ||
# modify the contents of the _albumartists and _albumartists_sort lists can | ||
# complete their processing and this plugin is working with the latest | ||
# updated data. | ||
register_album_metadata_processor(AlbumArtistStdName().add_artist_std_name, priority=PluginPriority.LOW) |
Oops, something went wrong.