1 /***************************************************************************
2  *   Copyright (C) 2011-2021 by Ilya Kotov                                 *
3  *   forkotov02@ya.ru                                                      *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20 
21 #include <QGridLayout>
22 #include <QVBoxLayout>
23 #include <QHBoxLayout>
24 #include <QSlider>
25 #include <QCheckBox>
26 #include <QPushButton>
27 #include <QComboBox>
28 #include <QLabel>
29 #include <QPainter>
30 #include <QDialogButtonBox>
31 #include <QSettings>
32 #include <QMessageBox>
33 #include <QDir>
34 #include <qmmp/qmmpsettings.h>
35 #include "equalizer.h"
36 
37 #if QT_VERSION < QT_VERSION_CHECK(5, 11, 0)
38 #define horizontalAdvance width
39 #endif
40 
Equalizer(QWidget * parent)41 Equalizer::Equalizer(QWidget *parent) : QDialog(parent)
42 {
43     setWindowTitle(tr("Equalizer"));
44 
45     m_layout = new QVBoxLayout(this);
46     setLayout(m_layout);
47     m_layout->setSpacing(5);
48     m_layout->setMargin(5);
49 
50     QHBoxLayout *buttonsLayout = new QHBoxLayout;
51     buttonsLayout->setSpacing(5);
52     m_enabled = new QCheckBox(tr("Enable equalizer"), this);
53     buttonsLayout->addWidget(m_enabled);
54 
55     buttonsLayout->addSpacerItem(new QSpacerItem(30, 0, QSizePolicy::Fixed, QSizePolicy::Fixed));
56 
57     QLabel *label = new QLabel(this);
58     label->setText(tr("Preset:"));
59     buttonsLayout->addWidget(label);
60 
61     m_presetComboBox = new QComboBox(this);
62     m_presetComboBox->setEditable(true);
63     connect(m_presetComboBox, SIGNAL(activated(int)), SLOT(loadPreset(int)));
64     buttonsLayout->addWidget(m_presetComboBox);
65 
66     QPushButton *saveButton = new QPushButton(tr("Save"), this);
67     connect(saveButton, SIGNAL(pressed()), SLOT(savePreset()));
68     buttonsLayout->addWidget(saveButton);
69 
70     QPushButton *deleteButton = new QPushButton(tr("Delete"), this);
71     connect(deleteButton, SIGNAL(pressed()), SLOT(deletePreset()));
72     buttonsLayout->addWidget(deleteButton);
73 
74     QPushButton *reset = new QPushButton(tr("Reset"), this);
75     connect(reset, SIGNAL(clicked()), SLOT(resetSettings()));
76     buttonsLayout->addWidget(reset);
77 
78     QDialogButtonBox *dialogButtons = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, this);
79     dialogButtons->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
80     connect(dialogButtons, SIGNAL(rejected()), SLOT(reject()));
81     buttonsLayout->addWidget(dialogButtons);
82 
83     QGridLayout *slidersLayout = new QGridLayout;
84     slidersLayout->setSpacing(5);
85 
86     QStringList names;
87     names << tr("Preamp") << "25" << "40" << "63" << "100" << "160" << "250"
88            << "400" << "630" << "1k" << "1,6k" << "2,5k"
89            << "4k" << "6,3k" << "10k" << "16k";
90 
91     for(int i = 0; i < 16; ++i)
92     {
93         QSlider *slider = new QSlider(this);
94         slider->setRange(-20, 20);
95         slider->setTickPosition(QSlider::TicksLeft);
96         slider->setTickInterval(10);
97         QLabel *eqLabel = new QLabel(this);
98         eqLabel->setFrameShape(QFrame::Box);
99         eqLabel->setText(names.at(i));
100         slidersLayout->addWidget(slider, 1, i, Qt::AlignHCenter);
101         slidersLayout->addWidget(eqLabel, 2, i, Qt::AlignHCenter);
102 
103         QLabel *label2 = new QLabel(this);
104         label2->setText(tr("%1dB").arg(0));
105         label2->setFrameShape(QFrame::Box);
106         label2->setMinimumWidth(fontMetrics().horizontalAdvance(tr("+%1dB").arg(20)) + 5);
107         label2->setAlignment(Qt::AlignCenter);
108         slidersLayout->addWidget(label2, 0, i, Qt::AlignHCenter);
109         connect(slider, SIGNAL(valueChanged(int)), SLOT(updateLabel()));
110         m_sliders << slider;
111         m_labels << label2;
112     }
113     m_layout->addItem(slidersLayout);
114     m_layout->addItem(buttonsLayout);
115     setMinimumHeight(300);
116     for(const QSlider *slider : qAsConst(m_sliders))
117     {
118         connect(slider, SIGNAL(valueChanged(int)), SLOT(applySettings()));
119     }
120     connect(m_enabled, SIGNAL(clicked()), SLOT(applySettings()));
121     readSettigs();
122     loadPresets();
123 }
124 
~Equalizer()125 Equalizer::~Equalizer()
126 {
127     savePresets();
128     qDeleteAll(m_presets);
129     m_presets.clear();
130 }
131 
readSettigs()132 void Equalizer::readSettigs()
133 {
134     EqSettings settings = QmmpSettings::instance()->eqSettings();
135     m_enabled->setChecked(settings.isEnabled());
136     m_sliders.at(0)->setValue(settings.preamp());
137     for(int i = 0; i < EqSettings::EQ_BANDS_15; ++i)
138     {
139         m_sliders.at(i+1)->setValue(settings.gain(i));
140     }
141 }
142 
loadPresets()143 void Equalizer::loadPresets()
144 {
145     m_presetComboBox->clear();
146     //equalizer presets
147     QString preset_path = Qmmp::configDir() + "/eq15.preset";
148     if(!QFile::exists(preset_path))
149         preset_path = ":/qsui/eq15.preset";
150     QSettings eq_preset (preset_path, QSettings::IniFormat);
151     int i = 0;
152     while(eq_preset.contains("Presets/Preset"+QString("%1").arg(++i)))
153     {
154         QString name = eq_preset.value(QString("Presets/Preset%1").arg(i), tr("preset")).toString();
155         EQPreset *preset = new EQPreset();
156         //preset->setText(name);
157         eq_preset.beginGroup(name);
158         for (int j = 0; j < EqSettings::EQ_BANDS_15; ++j)
159         {
160             preset->setGain(j,eq_preset.value(QString("Band%1").arg(j), 0).toDouble());
161         }
162         preset->setPreamp(eq_preset.value("Preamp",0).toDouble());
163         m_presets.append(preset);
164         m_presetComboBox->addItem(name);
165         eq_preset.endGroup();
166     }
167     m_presetComboBox->clearEditText();
168 }
169 
applySettings()170 void Equalizer::applySettings()
171 {
172     EqSettings settings = QmmpSettings::instance()->eqSettings();
173     settings.setPreamp(m_sliders.at(0)->value());
174     settings.setEnabled(m_enabled->isChecked());
175     for(int i = 0; i < EqSettings::EQ_BANDS_15; ++i)
176     {
177         settings.setGain(i, m_sliders.at(i+1)->value());
178     }
179     QmmpSettings::instance()->setEqSettings(settings);
180 }
181 
resetSettings()182 void Equalizer::resetSettings()
183 {
184     for(QSlider *slider : qAsConst(m_sliders))
185     {
186         slider->setValue(0);
187     }
188     applySettings();
189     m_presetComboBox->setCurrentIndex(-1);
190 }
191 
updateLabel()192 void Equalizer::updateLabel()
193 {
194     QSlider *slider = qobject_cast<QSlider *>(sender());
195     int index = m_sliders.indexOf(slider);
196     if(index < 0)
197         return;
198     if(slider->value() > 0)
199         m_labels[index]->setText(tr("+%1dB").arg(slider->value()));
200     else
201         m_labels[index]->setText(tr("%1dB").arg(slider->value()));
202 }
203 
loadPreset(int index)204 void Equalizer::loadPreset(int index)
205 {
206     EQPreset *preset = m_presets.at(index);
207     m_sliders.at(0)->setValue(preset->preamp());
208     for(int i = 0; i < EqSettings::EQ_BANDS_15; ++i)
209     {
210         m_sliders.at(i+1)->setValue(preset->gain(i));
211     }
212     applySettings();
213 }
214 
savePreset()215 void Equalizer::savePreset()
216 {
217     QString name = m_presetComboBox->currentText();
218     if(name.isEmpty())
219         return;
220 
221     int index = m_presetComboBox->findText(name);
222     if(index != -1)
223     {
224         if(QMessageBox::question(this, tr("Overwrite Request"),
225                                  tr("Preset '%1' already exists. Overwrite?").arg(name),
226                                  QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
227             return;
228         m_presets[index]->setPreamp(m_sliders.at(0)->value());
229         for(int i = 0; i < EqSettings::EQ_BANDS_15; ++i)
230         {
231             m_presets[index]->setGain(i, m_sliders.at(i+1)->value());
232         }
233     }
234     else
235     {
236         m_presetComboBox->addItem(name);
237         EQPreset *preset = new EQPreset();
238         preset->setPreamp(m_sliders.at(0)->value());
239         for(int i = 0; i < EqSettings::EQ_BANDS_15; ++i)
240         {
241             preset->setGain(i, m_sliders.at(i+1)->value());
242         }
243         m_presets.append(preset);
244     }
245     m_presetComboBox->clearEditText();
246 }
247 
savePresets()248 void Equalizer::savePresets()
249 {
250     QSettings eq_preset (Qmmp::configDir() + "/eq15.preset", QSettings::IniFormat);
251     eq_preset.clear ();
252     for (int i = 0; i < m_presets.size(); ++i)
253     {
254         eq_preset.setValue(QString("Presets/Preset%1").arg(i+1), m_presetComboBox->itemText(i));
255         eq_preset.beginGroup(m_presetComboBox->itemText(i));
256         for (int j = 0; j < EqSettings::EQ_BANDS_15; ++j)
257         {
258             eq_preset.setValue(QString("Band%1").arg(j),m_presets.at(i)->gain(j));
259         }
260         eq_preset.setValue("Preamp",m_presets.at(i)->preamp());
261         eq_preset.endGroup();
262     }
263 }
264 
deletePreset()265 void Equalizer::deletePreset()
266 {
267     QString name = m_presetComboBox->currentText();
268     if(name.isEmpty())
269         return;
270 
271     int index = m_presetComboBox->findText(name);
272     if(index != -1)
273     {
274         m_presetComboBox->removeItem(index);
275         delete m_presets.takeAt(index);
276     }
277     m_presetComboBox->clearEditText();
278 }
279