replaygain: Convert the ad-hoc tag_specific_values to classes

The plugin has loads of indirection and nested functions which make it
really hard to reason about. The larger picture here is that I'd like to make
the code more manageable before reworking the parallelism issues.

In particular, instead of manually implementing an interface using a
function that returns a tuple of function pointers, this commit creates proper
classes. Again, no functionality is changed, this only moves code
around.
This commit is contained in:
wisp3rwind 2021-03-18 15:40:39 +01:00
parent edf2bda1ce
commit ae3e95f9d3

View file

@ -99,10 +99,61 @@ Gain = collections.namedtuple("Gain", "gain peak")
AlbumGain = collections.namedtuple("AlbumGain", "album_gain track_gains")
class Peak(enum.Enum):
none = 0
true = 1
sample = 2
ALL_PEAK_METHODS = ["true", "sample"]
Peak = enum.Enum("Peak", ["none"] + ALL_PEAK_METHODS)
class GainHandler():
def __init__(self, config, peak, log):
self.config = config
self.peak = peak
self._log = log
@property
def target_level(self):
"""This currently needs to reloaded from the config since the tests
modify its value on-the-fly.
"""
return self.config['targetlevel'].as_number()
def store_track_gain(self, item, track_gain):
item.rg_track_gain = track_gain.gain
item.rg_track_peak = track_gain.peak
item.store()
self._log.debug('applied track gain {0} LU, peak {1} of FS',
item.rg_track_gain, item.rg_track_peak)
def store_album_gain(self, item, album_gain):
item.rg_album_gain = album_gain.gain
item.rg_album_peak = album_gain.peak
item.store()
self._log.debug('applied album gain {0} LU, peak {1} of FS',
item.rg_album_gain, item.rg_album_peak)
class R128GainHandler(GainHandler):
def __init__(self, config, log):
# R128_* tags do not store the track/album peak
super().__init__(config, Peak.none, log)
@property
def target_level(self):
"""This currently needs to reloaded from the config since the tests
modify its value on-the-fly.
"""
return self.config['r128_targetlevel'].as_number()
def store_track_gain(self, item, track_gain):
item.r128_track_gain = track_gain.gain
item.store()
self._log.debug('applied r128 track gain {0} LU',
item.r128_track_gain)
def store_album_gain(self, item, album_gain):
item.r128_album_gain = album_gain.gain
item.store()
self._log.debug('applied r128 album gain {0} LU',
item.r128_album_gain)
class Backend:
@ -975,11 +1026,6 @@ class ReplayGainPlugin(BeetsPlugin):
"""Provides ReplayGain analysis.
"""
peak_methods = {
"true": Peak.true,
"sample": Peak.sample,
}
def __init__(self):
super().__init__()
@ -1013,16 +1059,29 @@ class ReplayGainPlugin(BeetsPlugin):
', '.join(BACKENDS.keys())
)
)
peak_method = self.config["peak"].as_str()
if peak_method not in self.peak_methods:
if peak_method not in ALL_PEAK_METHODS:
raise ui.UserError(
"Selected ReplayGain peak method {} is not supported. "
"Please select one of: {}".format(
peak_method,
', '.join(self.peak_methods.keys())
', '.join(ALL_PEAK_METHODS)
)
)
self._peak_method = self.peak_methods[peak_method]
# The key in this dict is the `use_r128` flag.
self.gain_handlers = {
True: R128GainHandler(
self.config,
self._log,
),
False: GainHandler(
self.config,
Peak[peak_method],
self._log,
),
}
# On-import analysis.
if self.config['auto']:
@ -1091,52 +1150,6 @@ class ReplayGainPlugin(BeetsPlugin):
return False
def store_track_gain(self, item, track_gain):
item.rg_track_gain = track_gain.gain
item.rg_track_peak = track_gain.peak
item.store()
self._log.debug('applied track gain {0} LU, peak {1} of FS',
item.rg_track_gain, item.rg_track_peak)
def store_album_gain(self, item, album_gain):
item.rg_album_gain = album_gain.gain
item.rg_album_peak = album_gain.peak
item.store()
self._log.debug('applied album gain {0} LU, peak {1} of FS',
item.rg_album_gain, item.rg_album_peak)
def store_track_r128_gain(self, item, track_gain):
item.r128_track_gain = track_gain.gain
item.store()
self._log.debug('applied r128 track gain {0} LU',
item.r128_track_gain)
def store_album_r128_gain(self, item, album_gain):
item.r128_album_gain = album_gain.gain
item.store()
self._log.debug('applied r128 album gain {0} LU',
item.r128_album_gain)
def tag_specific_values(self, use_r128):
"""Return some tag specific values.
Returns a tuple (store_track_gain, store_album_gain, target_level,
peak_method).
"""
if use_r128:
store_track_gain = self.store_track_r128_gain
store_album_gain = self.store_album_r128_gain
target_level = self.config['r128_targetlevel'].as_number()
peak = Peak.none # R128_* tags do not store the track/album peak
else:
store_track_gain = self.store_track_gain
store_album_gain = self.store_album_gain
target_level = self.config['targetlevel'].as_number()
peak = self._peak_method
return store_track_gain, store_album_gain, target_level, peak
def handle_album(self, album, write, force=False):
"""Compute album and track replay gain store it in all of the
album's items.
@ -1159,8 +1172,7 @@ class ReplayGainPlugin(BeetsPlugin):
self._log.info('analyzing {0}', album)
tag_vals = self.tag_specific_values(use_r128)
store_track_gain, store_album_gain, target_level, peak = tag_vals
handler = self.gain_handlers[use_r128]
discs = {}
if self.per_disc:
@ -1185,8 +1197,8 @@ class ReplayGainPlugin(BeetsPlugin):
)
for item, track_gain in zip(items,
album_gain.track_gains):
store_track_gain(item, track_gain)
store_album_gain(item, album_gain.album_gain)
handler.store_track_gain(item, track_gain)
handler.store_album_gain(item, album_gain.album_gain)
if write:
item.try_write()
self._log.debug('done analyzing {0}', item)
@ -1196,8 +1208,8 @@ class ReplayGainPlugin(BeetsPlugin):
self.backend_instance.compute_album_gain, args=(),
kwds={
"items": list(items),
"target_level": target_level,
"peak": peak
"target_level": handler.target_level,
"peak": handler.peak,
},
callback=_store_album
)
@ -1219,8 +1231,7 @@ class ReplayGainPlugin(BeetsPlugin):
return
use_r128 = self.should_use_r128(item)
tag_vals = self.tag_specific_values(use_r128)
store_track_gain, store_album_gain, target_level, peak = tag_vals
handler = self.gain_handlers[use_r128]
def _store_track(track_gains):
if not track_gains or len(track_gains) != 1:
@ -1232,7 +1243,7 @@ class ReplayGainPlugin(BeetsPlugin):
.format(self.backend_name, item)
)
store_track_gain(item, track_gains[0])
handler.store_track_gain(item, track_gains[0])
if write:
item.try_write()
self._log.debug('done analyzing {0}', item)
@ -1242,8 +1253,8 @@ class ReplayGainPlugin(BeetsPlugin):
self.backend_instance.compute_track_gain, args=(),
kwds={
"items": [item],
"target_level": target_level,
"peak": peak,
"target_level": handler.target_level,
"peak": handler.peak,
},
callback=_store_track
)