Skip to content

Commit acb303a

Browse files
emersonrpphw
authored andcommitted
Add support for calculating ReplayGain on unidentified clusters
This commit allows unidentified clusters in the "left pane" to be run through the plugin and have their ReplayGain calculated. Previously the plugin could only be used on identified tracks and albums in the "right pane." With this commit, one or more clusters can be scanned as albums, and the album and track ReplayGain added to the files. There is no change to the existing / previous functionality for identified albums and tracks.
1 parent a6dfcda commit acb303a

File tree

1 file changed

+66
-20
lines changed

1 file changed

+66
-20
lines changed

plugins/replaygain2/__init__.py

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
are required to install rsgain and set its path in the plugin settings before use.
99
1010
#### Usage
11-
Select one or more tracks or albums, then right click and select Plugin->Calculate ReplayGain. The plugin
12-
will calculate ReplayGain information for the selected items and display the results in the metadata
13-
window. Click the save button to write the tags to file.
11+
Select one or more tracks, albums, or clusters then right click and select Plugin->Calculate ReplayGain.
12+
The plugin will calculate ReplayGain information for the selected items and display the results in the
13+
metadata window. Click the save button to write the tags to file.
1414
1515
The following file formats are supported:
1616
@@ -30,7 +30,7 @@
3030
3131
This plugin is based on the original ReplayGain plugin by Philipp Wolfer and Sophist.
3232
'''
33-
PLUGIN_VERSION = "1.7.1"
33+
PLUGIN_VERSION = "1.8"
3434
PLUGIN_API_VERSIONS = ["2.0"]
3535
PLUGIN_LICENSE = "GPL-2.0"
3636
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html"
@@ -63,11 +63,13 @@
6363
)
6464
from picard.album import Album
6565
from picard.track import Track, NonAlbumTrack
66+
from picard.file import File
67+
from picard.cluster import Cluster
6668
from picard.util import thread
6769
from picard.ui.options import register_options_page, OptionsPage
6870
from picard.config import TextOption, BoolOption, IntOption, config
6971
from picard.ui.itemviews import (BaseAction, register_track_action,
70-
register_album_action)
72+
register_album_action, register_cluster_action)
7173
from picard.plugins.replaygain2.ui_options_replaygain2 import Ui_ReplayGain2OptionsPage
7274

7375

@@ -190,19 +192,25 @@ def update_metadata(metadata, track_result, album_result, is_nat, opus_mode):
190192
if config.setting["reference_loudness"]:
191193
metadata.set("replaygain_reference_loudness", f"{float(config.setting['target_loudness']):.2f} LUFS")
192194

193-
def calculate_replaygain(tracks, options):
195+
def calculate_replaygain(input_objs, options):
194196

195197
# Make sure files are of supported type, build file list
196198
files = list()
197-
valid_tracks = list()
198-
for track in tracks:
199-
if not track.files:
200-
continue
201-
file = track.files[0]
199+
valid_list = list()
200+
for obj in input_objs:
201+
if isinstance(obj, Track):
202+
if not obj.files:
203+
continue
204+
file = obj.files[0]
205+
elif isinstance(obj, File):
206+
file = obj
207+
else:
208+
raise Exception(f"ReplayGain 2.0: Object {obj} is not a Track or File")
209+
202210
if not isinstanceany(file, SUPPORTED_FORMATS):
203211
raise Exception(f"ReplayGain 2.0: File '{file.filename}' is of unsupported format")
204212
files.append(file.filename)
205-
valid_tracks.append(track)
213+
valid_list.append(obj)
206214

207215
call = [config.setting["rsgain_command"]] + options + files
208216
for item in call:
@@ -236,7 +244,7 @@ def calculate_replaygain(tracks, options):
236244
# Make sure the number of rows in the output is what we expected
237245
if (len(lines) !=
238246
1 # Table header
239-
+ len(valid_tracks) # 1 row per track
247+
+ len(valid_list) # 1 row per track
240248
+ 1 if album_tags else 0): # Album result
241249
raise Exception(f"ReplayGain 2.0: Unexpected output from rsgain: {lines}")
242250
lines.pop(0) # Don't care about the table header
@@ -256,18 +264,23 @@ def calculate_replaygain(tracks, options):
256264
results.append(result)
257265

258266
# Update track metadata with results
259-
if isinstance(file, OggOpusFile):
260-
opus_mode = config.setting["opus_mode"]
261-
else:
262-
opus_mode = OpusMode.STANDARD
267+
for i, item in enumerate(valid_list):
268+
if isinstance(item, Track):
269+
filelist = item.files
270+
else: # is a file
271+
filelist = [item]
272+
273+
for file in filelist:
274+
if isinstance(file, OggOpusFile):
275+
opus_mode = config.setting["opus_mode"]
276+
else:
277+
opus_mode = OpusMode.STANDARD
263278

264-
for i, track in enumerate(valid_tracks):
265-
for file in track.files:
266279
update_metadata(
267280
file.metadata,
268281
results[i],
269282
album_result,
270-
isinstance(track, NonAlbumTrack),
283+
isinstance(item, NonAlbumTrack),
271284
opus_mode
272285
)
273286

@@ -276,6 +289,38 @@ def isinstanceany(obj, types):
276289
return any(isinstance(obj, t) for t in types)
277290

278291

292+
class ScanCluster(BaseAction):
293+
NAME = "Calculate Cluster Replay&Gain as Album..."
294+
295+
def callback(self, objs):
296+
if not rsgain_found(self.config.setting["rsgain_command"], self.tagger.window):
297+
return
298+
clusters = list(filter(lambda o: isinstance(o, Cluster), objs))
299+
300+
self.options = build_options(self.config)
301+
num_clusters = len(clusters)
302+
if num_clusters == 1:
303+
self.tagger.window.set_statusbar_message(
304+
'Calculating ReplayGain for %s...', clusters[0].metadata['album']
305+
)
306+
else:
307+
self.tagger.window.set_statusbar_message(
308+
'Calculating ReplayGain for %i clusters...', num_clusters
309+
)
310+
for cluster in clusters:
311+
thread.run_task(
312+
partial(calculate_replaygain, cluster.files, self.options),
313+
partial(self._replaygain_callback, cluster.files)
314+
)
315+
316+
def _replaygain_callback(self, files, result=None, error=None):
317+
if error is None:
318+
for file in files:
319+
file.update()
320+
self.tagger.window.set_statusbar_message('ReplayGain successfully calculated.')
321+
else:
322+
self.tagger.window.set_statusbar_message('Could not calculate ReplayGain.')
323+
279324
class ScanTracks(BaseAction):
280325
NAME = "Calculate Replay&Gain..."
281326

@@ -430,4 +475,5 @@ def rsgain_command_browse(self):
430475

431476
register_track_action(ScanTracks())
432477
register_album_action(ScanAlbums())
478+
register_cluster_action(ScanCluster())
433479
register_options_page(ReplayGain2OptionsPage)

0 commit comments

Comments
 (0)