8
8
are required to install rsgain and set its path in the plugin settings before use.
9
9
10
10
#### 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.
14
14
15
15
The following file formats are supported:
16
16
30
30
31
31
This plugin is based on the original ReplayGain plugin by Philipp Wolfer and Sophist.
32
32
'''
33
- PLUGIN_VERSION = "1.7.1 "
33
+ PLUGIN_VERSION = "1.8 "
34
34
PLUGIN_API_VERSIONS = ["2.0" ]
35
35
PLUGIN_LICENSE = "GPL-2.0"
36
36
PLUGIN_LICENSE_URL = "https://www.gnu.org/licenses/gpl-2.0.html"
63
63
)
64
64
from picard .album import Album
65
65
from picard .track import Track , NonAlbumTrack
66
+ from picard .file import File
67
+ from picard .cluster import Cluster
66
68
from picard .util import thread
67
69
from picard .ui .options import register_options_page , OptionsPage
68
70
from picard .config import TextOption , BoolOption , IntOption , config
69
71
from picard .ui .itemviews import (BaseAction , register_track_action ,
70
- register_album_action )
72
+ register_album_action , register_cluster_action )
71
73
from picard .plugins .replaygain2 .ui_options_replaygain2 import Ui_ReplayGain2OptionsPage
72
74
73
75
@@ -190,19 +192,25 @@ def update_metadata(metadata, track_result, album_result, is_nat, opus_mode):
190
192
if config .setting ["reference_loudness" ]:
191
193
metadata .set ("replaygain_reference_loudness" , f"{ float (config .setting ['target_loudness' ]):.2f} LUFS" )
192
194
193
- def calculate_replaygain (tracks , options ):
195
+ def calculate_replaygain (input_objs , options ):
194
196
195
197
# Make sure files are of supported type, build file list
196
198
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
+
202
210
if not isinstanceany (file , SUPPORTED_FORMATS ):
203
211
raise Exception (f"ReplayGain 2.0: File '{ file .filename } ' is of unsupported format" )
204
212
files .append (file .filename )
205
- valid_tracks .append (track )
213
+ valid_list .append (obj )
206
214
207
215
call = [config .setting ["rsgain_command" ]] + options + files
208
216
for item in call :
@@ -236,7 +244,7 @@ def calculate_replaygain(tracks, options):
236
244
# Make sure the number of rows in the output is what we expected
237
245
if (len (lines ) !=
238
246
1 # Table header
239
- + len (valid_tracks ) # 1 row per track
247
+ + len (valid_list ) # 1 row per track
240
248
+ 1 if album_tags else 0 ): # Album result
241
249
raise Exception (f"ReplayGain 2.0: Unexpected output from rsgain: { lines } " )
242
250
lines .pop (0 ) # Don't care about the table header
@@ -256,18 +264,23 @@ def calculate_replaygain(tracks, options):
256
264
results .append (result )
257
265
258
266
# 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
263
278
264
- for i , track in enumerate (valid_tracks ):
265
- for file in track .files :
266
279
update_metadata (
267
280
file .metadata ,
268
281
results [i ],
269
282
album_result ,
270
- isinstance (track , NonAlbumTrack ),
283
+ isinstance (item , NonAlbumTrack ),
271
284
opus_mode
272
285
)
273
286
@@ -276,6 +289,38 @@ def isinstanceany(obj, types):
276
289
return any (isinstance (obj , t ) for t in types )
277
290
278
291
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
+
279
324
class ScanTracks (BaseAction ):
280
325
NAME = "Calculate Replay&Gain..."
281
326
@@ -430,4 +475,5 @@ def rsgain_command_browse(self):
430
475
431
476
register_track_action (ScanTracks ())
432
477
register_album_action (ScanAlbums ())
478
+ register_cluster_action (ScanCluster ())
433
479
register_options_page (ReplayGain2OptionsPage )
0 commit comments