mirror of
https://github.com/fergalmoran/picard.git
synced 2026-01-03 15:13:57 +00:00
Merge branch 'master' into list_scripting_support
Conflicts: picard/script.py
This commit is contained in:
1
NEWS.txt
1
NEWS.txt
@@ -1,4 +1,5 @@
|
||||
Version UNRELEASED - 2012-XX-XX
|
||||
* Add %license% tag
|
||||
* Made %writer% available to tagger scripts and plugins with contents of songwriter (PICARD-21)
|
||||
|
||||
Version 0.16 - 2011-10-23
|
||||
|
||||
@@ -7,7 +7,7 @@ PLUGIN_NAME = u"ReplayGain"
|
||||
PLUGIN_AUTHOR = u"Philipp Wolfer"
|
||||
PLUGIN_DESCRIPTION = """Calculate ReplayGain for selected files and albums."""
|
||||
PLUGIN_VERSION = "0.1"
|
||||
PLUGIN_API_VERSIONS = ["0.10", "0.15"]
|
||||
PLUGIN_API_VERSIONS = ["0.10", "0.15", "0.16"]
|
||||
|
||||
|
||||
from PyQt4 import QtCore
|
||||
@@ -17,7 +17,7 @@ from picard.track import Track
|
||||
from picard.file import File
|
||||
from picard.util import encode_filename, decode_filename, partial
|
||||
from picard.ui.options import register_options_page, OptionsPage
|
||||
from picard.config import BoolOption, IntOption, TextOption
|
||||
from picard.config import TextOption
|
||||
from picard.ui.itemviews import (BaseAction, register_file_action,
|
||||
register_album_action)
|
||||
from picard.plugins.replaygain.ui_options_replaygain import Ui_ReplayGainOptionsPage
|
||||
@@ -28,12 +28,13 @@ REPLAYGAIN_COMMANDS = {
|
||||
"Ogg Vorbis": ("replaygain_vorbisgain_command", "replaygain_vorbisgain_options"),
|
||||
"MPEG-1 Audio": ("replaygain_mp3gain_command", "replaygain_mp3gain_options"),
|
||||
"FLAC": ("replaygain_metaflac_command", "replaygain_metaflac_options"),
|
||||
"WavPack": ("replaygain_wvgain_command", "replaygain_wvgain_options"),
|
||||
}
|
||||
|
||||
def calculate_replay_gain_for_files(files, format, tagger):
|
||||
"""Calculates the replay gain for a list of files in album mode."""
|
||||
file_list = ['%s' % encode_filename(f.filename) for f in files]
|
||||
|
||||
|
||||
if REPLAYGAIN_COMMANDS.has_key(format) \
|
||||
and tagger.config.setting[REPLAYGAIN_COMMANDS[format][0]]:
|
||||
command = tagger.config.setting[REPLAYGAIN_COMMANDS[format][0]]
|
||||
@@ -45,7 +46,7 @@ def calculate_replay_gain_for_files(files, format, tagger):
|
||||
|
||||
class ReplayGain(BaseAction):
|
||||
NAME = N_("Calculate replay &gain...")
|
||||
|
||||
|
||||
def _add_file_to_queue(self, file):
|
||||
self.tagger.other_queue.put((
|
||||
partial(self._calculate_replaygain, file),
|
||||
@@ -63,7 +64,7 @@ class ReplayGain(BaseAction):
|
||||
def _calculate_replaygain(self, file):
|
||||
self.tagger.window.set_statusbar_message(N_('Calculating replay gain for "%s"...'), file.filename)
|
||||
calculate_replay_gain_for_files([file], file.NAME, self.tagger)
|
||||
|
||||
|
||||
def _replaygain_callback(self, file, result=None, error=None):
|
||||
if not error:
|
||||
self.tagger.window.set_statusbar_message(N_('Replay gain for "%s" successfully calculated.'), file.filename)
|
||||
@@ -72,7 +73,7 @@ class ReplayGain(BaseAction):
|
||||
|
||||
class AlbumGain(BaseAction):
|
||||
NAME = N_("Calculate album &gain...")
|
||||
|
||||
|
||||
def callback(self, objs):
|
||||
albums = [o for o in objs if isinstance(o, Album)]
|
||||
for album in albums:
|
||||
@@ -80,32 +81,32 @@ class AlbumGain(BaseAction):
|
||||
partial(self._calculate_albumgain, album),
|
||||
partial(self._albumgain_callback, album),
|
||||
QtCore.Qt.NormalEventPriority))
|
||||
|
||||
|
||||
def split_files_by_type(self, files):
|
||||
"""Split the given files by filetype into separate lists."""
|
||||
files_by_format = {}
|
||||
|
||||
|
||||
for file in files:
|
||||
if not files_by_format.has_key(file.NAME):
|
||||
files_by_format[file.NAME] = [file]
|
||||
else:
|
||||
files_by_format[file.NAME].append(file)
|
||||
|
||||
|
||||
return files_by_format
|
||||
|
||||
|
||||
def _calculate_albumgain(self, album):
|
||||
self.tagger.window.set_statusbar_message(N_('Calculating album gain for "%s"...'), album.metadata["album"])
|
||||
filelist = [t.linked_files[0] for t in album.tracks if t.is_linked()]
|
||||
|
||||
|
||||
for format, files in self.split_files_by_type(filelist).iteritems():
|
||||
calculate_replay_gain_for_files(files, format, self.tagger)
|
||||
|
||||
|
||||
def _albumgain_callback(self, album, result=None, error=None):
|
||||
if not error:
|
||||
self.tagger.window.set_statusbar_message(N_('Album gain for "%s" successfully calculated.'), album.metadata["album"])
|
||||
else:
|
||||
self.tagger.window.set_statusbar_message(N_('Could not calculate album gain for "%s".'), album.metadata["album"])
|
||||
|
||||
|
||||
class ReplayGainOptionsPage(OptionsPage):
|
||||
|
||||
NAME = "replaygain"
|
||||
@@ -119,6 +120,8 @@ class ReplayGainOptionsPage(OptionsPage):
|
||||
TextOption("setting", "replaygain_mp3gain_options", "-a"),
|
||||
TextOption("setting", "replaygain_metaflac_command", "metaflac"),
|
||||
TextOption("setting", "replaygain_metaflac_options", "--add-replay-gain"),
|
||||
TextOption("setting", "replaygain_wvgain_command", "wvgain"),
|
||||
TextOption("setting", "replaygain_wvgain_options", "-a")
|
||||
]
|
||||
|
||||
def __init__(self, parent=None):
|
||||
@@ -130,12 +133,14 @@ class ReplayGainOptionsPage(OptionsPage):
|
||||
self.ui.vorbisgain_command.setText(self.config.setting["replaygain_vorbisgain_command"])
|
||||
self.ui.mp3gain_command.setText(self.config.setting["replaygain_mp3gain_command"])
|
||||
self.ui.metaflac_command.setText(self.config.setting["replaygain_metaflac_command"])
|
||||
|
||||
self.ui.wvgain_command.setText(self.config.setting["replaygain_wvgain_command"])
|
||||
|
||||
def save(self):
|
||||
self.config.setting["replaygain_vorbisgain_command"] = unicode(self.ui.vorbisgain_command.text())
|
||||
self.config.setting["replaygain_mp3gain_command"] = unicode(self.ui.mp3gain_command.text())
|
||||
self.config.setting["replaygain_metaflac_command"] = unicode(self.ui.metaflac_command.text())
|
||||
|
||||
self.config.setting["replaygain_wvgain_command"] = unicode(self.ui.wvgain_command.text())
|
||||
|
||||
register_file_action(ReplayGain())
|
||||
register_album_action(AlbumGain())
|
||||
register_options_page(ReplayGainOptionsPage)
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<ui version="4.0" >
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ReplayGainOptionsPage</class>
|
||||
<widget class="QWidget" name="ReplayGainOptionsPage" >
|
||||
<property name="geometry" >
|
||||
<widget class="QWidget" name="ReplayGainOptionsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
@@ -9,82 +10,74 @@
|
||||
<height>317</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="replay_gain" >
|
||||
<property name="title" >
|
||||
<widget class="QGroupBox" name="replay_gain">
|
||||
<property name="title">
|
||||
<string>Replay Gain</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="spacing" >
|
||||
<layout class="QVBoxLayout">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin" >
|
||||
<property name="margin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label" >
|
||||
<property name="text" >
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Path to VorbisGain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="vorbisgain_command" />
|
||||
<widget class="QLineEdit" name="vorbisgain_command"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Path to MP3Gain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="mp3gain_command" />
|
||||
<widget class="QLineEdit" name="mp3gain_command"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Path to metaflac:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="metaflac_command" />
|
||||
<widget class="QLineEdit" name="metaflac_command"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Path to wvgain:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="wvgain_command"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation" >
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" >
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>263</width>
|
||||
<height>21</height>
|
||||
|
||||
@@ -2,57 +2,58 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'options_replaygain.ui'
|
||||
#
|
||||
# Created: Thu Mar 13 23:07:48 2008
|
||||
# by: PyQt4 UI code generator 4.3
|
||||
# Created: Sun Jan 8 13:42:44 2012
|
||||
# by: PyQt4 UI code generator 4.9
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
|
||||
try:
|
||||
_fromUtf8 = QtCore.QString.fromUtf8
|
||||
except AttributeError:
|
||||
_fromUtf8 = lambda s: s
|
||||
|
||||
class Ui_ReplayGainOptionsPage(object):
|
||||
def setupUi(self, ReplayGainOptionsPage):
|
||||
ReplayGainOptionsPage.setObjectName("ReplayGainOptionsPage")
|
||||
ReplayGainOptionsPage.resize(QtCore.QSize(QtCore.QRect(0,0,305,317).size()).expandedTo(ReplayGainOptionsPage.minimumSizeHint()))
|
||||
|
||||
ReplayGainOptionsPage.setObjectName(_fromUtf8("ReplayGainOptionsPage"))
|
||||
ReplayGainOptionsPage.resize(305, 317)
|
||||
self.vboxlayout = QtGui.QVBoxLayout(ReplayGainOptionsPage)
|
||||
self.vboxlayout.setSpacing(6)
|
||||
self.vboxlayout.setMargin(9)
|
||||
self.vboxlayout.setObjectName("vboxlayout")
|
||||
|
||||
self.vboxlayout.setObjectName(_fromUtf8("vboxlayout"))
|
||||
self.replay_gain = QtGui.QGroupBox(ReplayGainOptionsPage)
|
||||
self.replay_gain.setObjectName("replay_gain")
|
||||
|
||||
self.replay_gain.setObjectName(_fromUtf8("replay_gain"))
|
||||
self.vboxlayout1 = QtGui.QVBoxLayout(self.replay_gain)
|
||||
self.vboxlayout1.setSpacing(2)
|
||||
self.vboxlayout1.setMargin(9)
|
||||
self.vboxlayout1.setObjectName("vboxlayout1")
|
||||
|
||||
self.vboxlayout1.setObjectName(_fromUtf8("vboxlayout1"))
|
||||
self.label = QtGui.QLabel(self.replay_gain)
|
||||
self.label.setObjectName("label")
|
||||
self.label.setObjectName(_fromUtf8("label"))
|
||||
self.vboxlayout1.addWidget(self.label)
|
||||
|
||||
self.vorbisgain_command = QtGui.QLineEdit(self.replay_gain)
|
||||
self.vorbisgain_command.setObjectName("vorbisgain_command")
|
||||
self.vorbisgain_command.setObjectName(_fromUtf8("vorbisgain_command"))
|
||||
self.vboxlayout1.addWidget(self.vorbisgain_command)
|
||||
|
||||
self.label_2 = QtGui.QLabel(self.replay_gain)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.label_2.setObjectName(_fromUtf8("label_2"))
|
||||
self.vboxlayout1.addWidget(self.label_2)
|
||||
|
||||
self.mp3gain_command = QtGui.QLineEdit(self.replay_gain)
|
||||
self.mp3gain_command.setObjectName("mp3gain_command")
|
||||
self.mp3gain_command.setObjectName(_fromUtf8("mp3gain_command"))
|
||||
self.vboxlayout1.addWidget(self.mp3gain_command)
|
||||
|
||||
self.label_3 = QtGui.QLabel(self.replay_gain)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.label_3.setObjectName(_fromUtf8("label_3"))
|
||||
self.vboxlayout1.addWidget(self.label_3)
|
||||
|
||||
self.metaflac_command = QtGui.QLineEdit(self.replay_gain)
|
||||
self.metaflac_command.setObjectName("metaflac_command")
|
||||
self.metaflac_command.setObjectName(_fromUtf8("metaflac_command"))
|
||||
self.vboxlayout1.addWidget(self.metaflac_command)
|
||||
self.label_4 = QtGui.QLabel(self.replay_gain)
|
||||
self.label_4.setObjectName(_fromUtf8("label_4"))
|
||||
self.vboxlayout1.addWidget(self.label_4)
|
||||
self.wvgain_command = QtGui.QLineEdit(self.replay_gain)
|
||||
self.wvgain_command.setObjectName(_fromUtf8("wvgain_command"))
|
||||
self.vboxlayout1.addWidget(self.wvgain_command)
|
||||
self.vboxlayout.addWidget(self.replay_gain)
|
||||
|
||||
spacerItem = QtGui.QSpacerItem(263,21,QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Expanding)
|
||||
spacerItem = QtGui.QSpacerItem(263, 21, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
|
||||
self.vboxlayout.addItem(spacerItem)
|
||||
|
||||
self.retranslateUi(ReplayGainOptionsPage)
|
||||
@@ -63,4 +64,5 @@ class Ui_ReplayGainOptionsPage(object):
|
||||
self.label.setText(QtGui.QApplication.translate("ReplayGainOptionsPage", "Path to VorbisGain:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label_2.setText(QtGui.QApplication.translate("ReplayGainOptionsPage", "Path to MP3Gain:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label_3.setText(QtGui.QApplication.translate("ReplayGainOptionsPage", "Path to metaflac:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
self.label_4.setText(QtGui.QApplication.translate("ReplayGainOptionsPage", "Path to wvgain:", None, QtGui.QApplication.UnicodeUTF8))
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ class ID3File(File):
|
||||
elif frameid == 'USLT':
|
||||
name = 'lyrics'
|
||||
if frame.desc:
|
||||
name += frame.desc
|
||||
name += ':%s' % frame.desc
|
||||
metadata.add(name, unicode(frame.text))
|
||||
elif frameid == 'UFID' and frame.owner == 'http://musicbrainz.org':
|
||||
metadata['musicbrainz_trackid'] = unicode(frame.data)
|
||||
|
||||
@@ -221,7 +221,7 @@ class CompatID3(ID3):
|
||||
|
||||
# New frames added in v2.4.
|
||||
for key in ["ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG",
|
||||
"TMOO", "TPRO", "TSST"]:
|
||||
"TMOO", "TPRO"]:
|
||||
if key in self: del(self[key])
|
||||
|
||||
for frame in self.values():
|
||||
|
||||
@@ -25,6 +25,7 @@ import unicodedata
|
||||
from picard.metadata import Metadata
|
||||
from picard.metadata import MULTI_VALUED_JOINER
|
||||
from picard.plugin import ExtensionPoint
|
||||
from inspect import getargspec
|
||||
|
||||
class ScriptError(Exception): pass
|
||||
class ParseError(ScriptError): pass
|
||||
@@ -55,7 +56,23 @@ class ScriptVariable(object):
|
||||
|
||||
class ScriptFunction(object):
|
||||
|
||||
def __init__(self, name, args):
|
||||
def __init__(self, name, args, parser):
|
||||
try:
|
||||
expected_args = parser.functions[name][2]
|
||||
if expected_args and (len(args) not in expected_args):
|
||||
raise ScriptError(
|
||||
"Wrong number of arguments for $%s: Expected %s, got %i at position %i, line %i"
|
||||
% (name,
|
||||
str(expected_args[0])
|
||||
if len(expected_args) == 1
|
||||
else
|
||||
"%i - %i" % (min(expected_args), max(expected_args)),
|
||||
len(args),
|
||||
parser._x,
|
||||
parser._y))
|
||||
except KeyError:
|
||||
raise UnknownFunction("Unknown function '%s'" % name)
|
||||
|
||||
self.name = name
|
||||
self.args = args
|
||||
|
||||
@@ -63,15 +80,12 @@ class ScriptFunction(object):
|
||||
return "<ScriptFunction $%s(%r)>" % (self.name, self.args)
|
||||
|
||||
def eval(self, parser):
|
||||
try:
|
||||
function, eval_args = parser.functions[self.name]
|
||||
if eval_args:
|
||||
args = [arg.eval(parser) for arg in self.args]
|
||||
else:
|
||||
args = self.args
|
||||
return function(parser, *args)
|
||||
except KeyError:
|
||||
raise UnknownFunction("Unknown function '%s'" % self.name)
|
||||
function, eval_args, num_args = parser.functions[self.name]
|
||||
if eval_args:
|
||||
args = [arg.eval(parser) for arg in self.args]
|
||||
else:
|
||||
args = self.args
|
||||
return function(parser, *args)
|
||||
|
||||
|
||||
class ScriptExpression(list):
|
||||
@@ -150,7 +164,7 @@ Grammar:
|
||||
name = self._text[start:self._pos-1]
|
||||
if name not in self.functions:
|
||||
raise UnknownFunction("Unknown function '%s'" % name)
|
||||
return ScriptFunction(name, self.parse_arguments())
|
||||
return ScriptFunction(name, self.parse_arguments(), self)
|
||||
elif ch is None:
|
||||
self.__raise_eof()
|
||||
elif not isidentif(ch):
|
||||
@@ -214,8 +228,8 @@ Grammar:
|
||||
|
||||
def load_functions(self):
|
||||
self.functions = {}
|
||||
for name, function, eval_args in ScriptParser._function_registry:
|
||||
self.functions[name] = (function, eval_args)
|
||||
for name, function, eval_args, num_args in ScriptParser._function_registry:
|
||||
self.functions[name] = (function, eval_args, num_args)
|
||||
|
||||
def parse(self, script, functions=False):
|
||||
"""Parse the script."""
|
||||
@@ -239,22 +253,32 @@ Grammar:
|
||||
return ScriptParser._cache[key].eval(self)
|
||||
|
||||
|
||||
def register_script_function(function, name=None, eval_args=True):
|
||||
def register_script_function(function, name=None, eval_args=True,
|
||||
check_argcount=True):
|
||||
"""Registers a script function. If ``name`` is ``None``,
|
||||
``function.__name__`` will be used.
|
||||
If ``eval_args`` is ``False``, the arguments will not be evaluated before being
|
||||
passed to ``function``.
|
||||
If ``check_argcount`` is ``False`` the number of arguments passed to the
|
||||
function will not be verified."""
|
||||
|
||||
argspec = getargspec(function)
|
||||
argcount = (len(argspec.args) - 1,) # -1 for the parser
|
||||
|
||||
if argspec.defaults is not None:
|
||||
argcount = range(argcount[0] - len(argspec.defaults), argcount[0] + 1)
|
||||
|
||||
if name is None:
|
||||
name = function.__name__
|
||||
ScriptParser._function_registry.register(function.__module__, (name, function, eval_args))
|
||||
ScriptParser._function_registry.register(function.__module__,
|
||||
(name, function, eval_args,
|
||||
argcount if argcount and check_argcount else False)
|
||||
)
|
||||
|
||||
|
||||
def func_if(parser, *args):
|
||||
"""If ``if`` is not empty, it returns ``then``, otherwise it returns
|
||||
``else``."""
|
||||
nargs = len(args)
|
||||
if nargs > 1:
|
||||
if args[0].eval(parser):
|
||||
return args[1].eval(parser)
|
||||
if nargs == 3:
|
||||
return args[2].eval(parser)
|
||||
return ''
|
||||
def func_if(parser, _if, _then, _else=None):
|
||||
"""If ``_if`` is not empty, it returns ``_then``, otherwise it returns
|
||||
``_else``."""
|
||||
return _then if _if else _else if _else else ''
|
||||
|
||||
def func_if2(parser, *args):
|
||||
"""Returns first non empty argument."""
|
||||
@@ -528,9 +552,9 @@ def func_truncate(parser, text, length):
|
||||
length = None
|
||||
return text[:length].rstrip()
|
||||
|
||||
register_script_function(func_if, "if", eval_args=False)
|
||||
register_script_function(func_if2, "if2", eval_args=False)
|
||||
register_script_function(func_noop, "noop", eval_args=False)
|
||||
register_script_function(func_if, "if")
|
||||
register_script_function(func_if2, "if2", eval_args=False, check_argcount=False)
|
||||
register_script_function(func_noop, "noop", eval_args=False, check_argcount=False)
|
||||
register_script_function(func_left, "left")
|
||||
register_script_function(func_right, "right")
|
||||
register_script_function(func_lower, "lower")
|
||||
|
||||
@@ -299,7 +299,7 @@ def translate_from_sortname(name, sortname):
|
||||
parts = [sortname]
|
||||
separator = ""
|
||||
return separator.join(map(_reverse_sortname, parts))
|
||||
return None
|
||||
return name
|
||||
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import unittest
|
||||
from picard.metadata import Metadata
|
||||
from picard.mbxml import track_to_metadata, release_to_metadata
|
||||
from picard.webservice import XmlNode
|
||||
|
||||
class config:
|
||||
setting = {
|
||||
"standardize_tracks": False,
|
||||
"standardize_artists": False,
|
||||
"standardize_releases": False
|
||||
"standardize_releases": False,
|
||||
"translate_artist_names": False
|
||||
}
|
||||
|
||||
class XmlNode(object):
|
||||
|
||||
@@ -85,23 +85,23 @@ class ShortFilenameTest(unittest.TestCase):
|
||||
class TranslateArtistTest(unittest.TestCase):
|
||||
|
||||
def test_latin(self):
|
||||
self.failUnlessEqual(u"Jean Michel Jarre", util.translate_artist(u"Jean Michel Jarre", u"Jarre, Jean Michel"))
|
||||
self.failIfEqual(u"Jarre, Jean Michel", util.translate_artist(u"Jean Michel Jarre", u"Jarre, Jean Michel"))
|
||||
self.failUnlessEqual(u"Jean Michel Jarre", util.translate_from_sortname(u"Jean Michel Jarre", u"Jarre, Jean Michel"))
|
||||
self.failIfEqual(u"Jarre, Jean Michel", util.translate_from_sortname(u"Jean Michel Jarre", u"Jarre, Jean Michel"))
|
||||
|
||||
def test_kanji(self):
|
||||
self.failUnlessEqual(u"Tetsuya Komuro", util.translate_artist(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
self.failIfEqual(u"Komuro, Tetsuya", util.translate_artist(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
self.failIfEqual(u"小室哲哉", util.translate_artist(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
self.failUnlessEqual(u"Tetsuya Komuro", util.translate_from_sortname(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
self.failIfEqual(u"Komuro, Tetsuya", util.translate_from_sortname(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
self.failIfEqual(u"小室哲哉", util.translate_from_sortname(u"小室哲哉", u"Komuro, Tetsuya"))
|
||||
|
||||
def test_kanji2(self):
|
||||
self.failUnlessEqual(u"Ayumi Hamasaki & Keiko", util.translate_artist(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
self.failIfEqual(u"浜崎あゆみ & KEIKO", util.translate_artist(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
self.failIfEqual(u"Hamasaki, Ayumi & Keiko", util.translate_artist(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
self.failUnlessEqual(u"Ayumi Hamasaki & Keiko", util.translate_from_sortname(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
self.failIfEqual(u"浜崎あゆみ & KEIKO", util.translate_from_sortname(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
self.failIfEqual(u"Hamasaki, Ayumi & Keiko", util.translate_from_sortname(u"浜崎あゆみ & KEIKO", u"Hamasaki, Ayumi & Keiko"))
|
||||
|
||||
def test_cyrillic(self):
|
||||
self.failUnlessEqual(U"Pyotr Ilyich Tchaikovsky", util.translate_artist(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
self.failIfEqual(u"Tchaikovsky, Pyotr Ilyich", util.translate_artist(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
self.failIfEqual(u"Пётр Ильич Чайковский", util.translate_artist(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
self.failUnlessEqual(U"Pyotr Ilyich Tchaikovsky", util.translate_from_sortname(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
self.failIfEqual(u"Tchaikovsky, Pyotr Ilyich", util.translate_from_sortname(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
self.failIfEqual(u"Пётр Ильич Чайковский", util.translate_from_sortname(u"Пётр Ильич Чайковский", u"Tchaikovsky, Pyotr Ilyich"))
|
||||
|
||||
|
||||
class FormatTimeTest(unittest.TestCase):
|
||||
|
||||
Reference in New Issue
Block a user