1 /*
2  * Copyright (C) 2010-2011 Carl Hetherington <carl@carlh.net>
3  * Copyright (C) 2016 Paul Davis <paul@linuxaudiosystems.com>
4  * Copyright (C) 2016 Robin Gareus <robin@gareus.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <gtkmm/table.h>
22 #include <gtkmm/label.h>
23 #include <gtkmm/spinbutton.h>
24 #include <gtkmm/radiobutton.h>
25 #include <gtkmm/stock.h>
26 #include <gtkmm/progressbar.h>
27 #include "normalize_dialog.h"
28 #include "pbd/i18n.h"
29 
30 using namespace Gtk;
31 
32 double NormalizeDialog::_last_normalization_value = 0;
33 double NormalizeDialog::_last_rms_target_value = -9;
34 bool NormalizeDialog::_last_normalize_individually = true;
35 bool NormalizeDialog::_last_constrain_rms = false;
36 
NormalizeDialog(bool more_than_one)37 NormalizeDialog::NormalizeDialog (bool more_than_one)
38 	: ArdourDialog (more_than_one ? _("Normalize regions") : _("Normalize region"))
39 	, _normalize_individually (0)
40 {
41 	get_vbox()->set_spacing (12);
42 
43 	Table* tbl = manage (new Table);
44 	tbl->set_spacings (6);
45 	tbl->set_border_width (6);
46 
47 	_spin_peak = manage (new SpinButton (0.2, 2));
48 	_spin_peak->set_range (-112, 0);
49 	_spin_peak->set_increments (0.1, 1);
50 	_spin_peak->set_value (_last_normalization_value);
51 	_spin_peak->set_activates_default ();
52 
53 	_constrain_rms = manage (new CheckButton (_("Constrain RMS to:")));
54 	_constrain_rms->set_active (_last_constrain_rms);
55 	_spin_rms = manage (new SpinButton (0.2, 2));
56 	_spin_rms->set_range (-112, 0);
57 	_spin_rms->set_increments (0.1, 1);
58 	_spin_rms->set_value (_last_rms_target_value);
59 
60 	tbl->attach (*manage (new Label (_("Normalize to:"), ALIGN_END)), 0, 1, 0, 1, FILL, SHRINK);
61 	tbl->attach (*_spin_peak, 1, 2, 0, 1, SHRINK, SHRINK);
62 	tbl->attach (*manage (new Label (_("dBFS"))), 2, 3, 0, 1, SHRINK, SHRINK);
63 
64 	tbl->attach (*_constrain_rms, 0, 1, 1, 2, SHRINK, SHRINK);
65 	tbl->attach (*_spin_rms, 1, 2, 1, 2, SHRINK, SHRINK);
66 	tbl->attach (*manage (new Label (_("dBFS"))), 2, 3, 1, 2, SHRINK, SHRINK);
67 
68 	get_vbox()->pack_start (*tbl);
69 
70 	if (more_than_one) {
71 		RadioButtonGroup group;
72 		VBox* vbox = manage (new VBox);
73 
74 		_normalize_individually = manage (new RadioButton (group, _("Normalize each region using its own peak value")));
75 		vbox->pack_start (*_normalize_individually);
76 		RadioButton* b = manage (new RadioButton (group, _("Normalize each region using the peak value of all regions")));
77 		vbox->pack_start (*b);
78 
79 		_normalize_individually->set_active (_last_normalize_individually);
80 		b->set_active (!_last_normalize_individually);
81 
82 		get_vbox()->pack_start (*vbox);
83 	}
84 
85 	_progress_bar = manage (new ProgressBar);
86 	get_vbox()->pack_start (*_progress_bar);
87 
88 	update_sensitivity ();
89 	show_all ();
90 	_progress_bar->hide ();
91 
92 	add_button (Stock::CANCEL, RESPONSE_CANCEL);
93 	add_button (_("Normalize"), RESPONSE_ACCEPT);
94 	set_default_response (RESPONSE_ACCEPT);
95 
96 	_constrain_rms->signal_toggled ().connect (sigc::mem_fun (*this, &NormalizeDialog::update_sensitivity));
97 	signal_response().connect (sigc::mem_fun (*this, &NormalizeDialog::button_clicked));
98 }
99 
100 void
update_sensitivity()101 NormalizeDialog::update_sensitivity ()
102 {
103 	_spin_rms->set_sensitive (constrain_rms ());
104 }
105 
106 bool
normalize_individually() const107 NormalizeDialog::normalize_individually () const
108 {
109 	if (_normalize_individually == 0) {
110 		return true;
111 	}
112 
113 	return _normalize_individually->get_active ();
114 }
115 
116 bool
constrain_rms() const117 NormalizeDialog::constrain_rms () const
118 {
119 	return _constrain_rms->get_active ();
120 }
121 
122 double
target_peak() const123 NormalizeDialog::target_peak () const
124 {
125 	return _spin_peak->get_value ();
126 }
127 
128 double
target_rms() const129 NormalizeDialog::target_rms () const
130 {
131 	return _spin_rms->get_value ();
132 }
133 
134 void
update_progress_gui(float p)135 NormalizeDialog::update_progress_gui (float p)
136 {
137 	/* Normalization is run inside the GUI thread, so we can directly
138 	 * update the progress bar when notified about progress.
139 	 */
140 	_progress_bar->show ();
141 	_progress_bar->set_fraction (p);
142 }
143 
144 int
run()145 NormalizeDialog::run ()
146 {
147 	int const r = ArdourDialog::run ();
148 	_last_normalization_value = target_peak ();
149 	_last_rms_target_value = target_rms ();
150 	_last_constrain_rms = constrain_rms ();
151 	if (_normalize_individually) {
152 		_last_normalize_individually = _normalize_individually->get_active ();
153 	}
154 	return r;
155 }
156 
157 void
button_clicked(int r)158 NormalizeDialog::button_clicked (int r)
159 {
160 	if (r == RESPONSE_CANCEL) {
161 		cancel ();
162 	}
163 }
164