Browse the code

 

Differences between 236 and 237 on /.
Number of edited files: 2 (1 added, 0 deleted and 1 modified)
Revision 237

About 2 months and 11 days ago.

* Added an initial (and incomplete) support of ReplayGain analysis-tagging (references #57)
Added file(s) Deleted file(s) Modified file(s)

 

Old New Code
18
18
from gettext import gettext as _
19
19
from gi.repository.Gtk import (Label, Switch, ListBoxRow, Box, Orientation,
20
20
                               ComboBox, CellRendererText, Frame, ListStore,
21
 
                               Settings, Popover, ScrolledWindow, ShadowType)
 
21
                               Settings, Popover, ScrolledWindow, ShadowType,
 
22
                               Button, Separator, Spinner)
22
23
from gi.repository.Pango import WrapMode
 
24
from gi.repository.Gdk import threads_enter, threads_leave
 
25
from gi.repository.GObject import idle_add
 
26
from threading import Thread
23
27

                                        
 
28
from media.replaygain import ReplayGain
24
29
from common.config import ConfigLoader
25
30
config = ConfigLoader()
26
31

                                        
31
36

                                        
32
37
    def on_open_config(self, wdg):
33
38
        popup = Popover.new(self.config_button)
34
 
        popup.set_size_request(400, 380)
 
39
        popup.set_size_request(400, 420)
35
40
        contentbox = Box.new(Orientation.VERTICAL, 5)
36
41
        config_wdw = ScrolledWindow(expand=False)
37
42
        config_wdw.add(contentbox)
133
138

                                        
134
139
        # Widgets for replaygain
135
140
        frame = Frame(label='')
136
 
        frame.get_label_widget().set_markup('<b>' + _('ReplayGain') + '</b>')
 
141
        frame.get_label_widget().set_markup('<b>' + _('Normalize loudness') + '</b>')
137
142
        frame.set_shadow_type(ShadowType.NONE)
138
143
        frame.set_margin_top(10)
139
144
        contentbox.add(frame)
146
151
        frame.add(framebox)
147
152

                                        
148
153
        lbl = Label(xalign=0)
149
 
        lbl.set_markup('<small>' + _('Normalize loudness (avoids the common problem of having to manually adjust volume levels between tracks).') + '</small>')
 
154
        lbl.set_markup('<small>' + _('ReplayGain loudness normalization avoids the common problem of having to manually adjust volume levels between tracks.') + '</small>')
150
155
        lbl.set_line_wrap_mode(WrapMode.WORD)
151
156
        lbl.set_line_wrap(True)
152
157
        framebox.add(lbl)
191
196
        switch.connect('notify::active', self.on_switch, 'Player', 'replaygain',
192
197
                       mode_combo)
193
198

                                        
 
199
        rgain = ReplayGain()
 
200

                                    
 
201
        hbox = Box(orientation=Orientation.HORIZONTAL, spacing=5)
 
202
        framebox.add(hbox)
 
203
        check_btn = Button(_('Analyze'))
 
204
        check_btn.connect('clicked', self.on_replaygain_analysis, hbox, rgain)
 
205
        hbox.pack_start(check_btn, False, False, 0)
 
206

                                    
 
207
        sep = Separator()
 
208
        hbox.pack_start(sep, False, False, 0)
 
209

                                    
 
210
        if rgain.has_missing_replaygain_utils():
 
211
            check_btn.set_sensitive(False)
 
212
            lbl = Label(xalign=0)
 
213
            lbl.set_markup('<small>' + _('⚠ Missing packages.') + '</small>')
 
214
            lbl.set_line_wrap_mode(WrapMode.WORD)
 
215
            lbl.set_property('tooltip-text', _('You have to install the following packages: metaflac, vorbisgain, mp3gain.'))
 
216
            lbl.set_line_wrap(True)
 
217
            hbox.pack_start(lbl, True, True, 0)
 
218
            lbl.show()
 
219

                                    
 
220

                                    
 
221

                                    
 
222

                                    
 
223

                                    
194
224
        popup.show_all()
195
225

                                        
196
226

                                        
 
227
    def on_replaygain_analysis(self, widget, hbox, rgain):
 
228
        threads_enter()
 
229

                                    
 
230
        idle_add(widget.set_sensitive, False)
 
231
        spinner = Spinner()
 
232
        idle_add(spinner.start)
 
233
        idle_add(hbox.pack_start, spinner, False, False, 0)
 
234
        lbl = Label(xalign=0)
 
235
        idle_add(lbl.set_markup, '<small>' + _('Checking files… Please wait.') + '</small>')
 
236
        idle_add(lbl.set_line_wrap_mode, WrapMode.WORD)
 
237
        idle_add(lbl.set_line_wrap, True)
 
238
        idle_add(hbox.pack_start, lbl, True, True, 0)
 
239
        spinner.show()
 
240
        lbl.show()
 
241

                                    
 
242
        def launch():
 
243
            albums_to_process, albums_format = rgain.check_albums_needing_process(config.config['Explorer']['folder'])
 
244
            total = len(albums_to_process)
 
245
            if total > 0:
 
246
                idle_add(lbl.set_markup, '<small>' + _('Processing %(count)d albums… Time for a coffee!' % {'count': total}) + '</small>')
 
247

                                    
 
248
                for album in albums_to_process:
 
249
                    rgain.process_album(album, albums_format)
 
250
                    if total > 0:
 
251
                        total -= 1
 
252
                        idle_add(lbl.set_markup, '<small>' + _('Processing %(count)d albums… Time for a coffee!' % {'count': total}) + '</small>')
 
253

                                    
 
254
            idle_add(spinner.hide)
 
255
            idle_add(lbl.set_markup, '<small>' + _('✔ Files are ready. Listen up!') + '</small>')
 
256
            idle_add(widget.set_sensitive, True)
 
257

                                    
 
258
        thread = Thread(group=None, target=launch,
 
259
                        name='replaygain', args=())
 
260
        thread.start()
 
261

                                    
 
262
        threads_leave()
 
263

                                    
 
264

                                    
 
265

                                    
197
266
    def on_darkmode_activate(self, widget, event):
198
267
        state = widget.get_active()
199
268

                                        
200
269