add mp3 and ogg torrent url info to JamendoAlbum
[amarok.git] / src / equalizersetup.cpp
blobe5d6f637f06b4f7373ee6158a7e9571b458b2c28
1 /***************************************************************************
2 Setup dialog for the equalizer
4 (c) 2004 Mark Kretschmann <markey@web.de>
5 (c) 2005 Seb Ruiz <ruiz@kde.org>
6 (c) 2005 Markus Brueffer <markus@brueffer.de>
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18 #include "equalizersetup.h"
20 #include "amarok.h"
21 #include "amarokconfig.h"
22 #include "enginebase.h"
23 #include "enginecontroller.h"
24 #include "equalizergraph.h"
25 #include "equalizerpresetmanager.h"
26 #include "widgets/sliderwidget.h"
28 #include <KApplication>
29 #include <KComboBox>
30 #include <KIconLoader>
31 #include <KInputDialog> //presets
32 #include <KLocale>
33 #include <KMenu>
34 #include <KMessageBox>
35 #include <KStandardDirs> //locate()
36 #include <KVBox>
37 #include <KWindowSystem>
39 #include <QCheckBox>
40 #include <QDomDocument>
41 #include <QDomElement>
42 #include <QDomNode>
43 #include <QFile>
44 #include <QGroupBox>
45 #include <QLabel>
46 #include <QLayout>
47 #include <QPushButton>
48 #include <QTextStream> //presets
49 #include <QToolTip>
52 EqualizerSetup* EqualizerSetup::s_instance = 0;
55 EqualizerSetup::EqualizerSetup()
56 : KDialog( Amarok::mainWindow() )
58 setModal( false );
59 setButtons( Ok );
60 showButtonSeparator( false );
62 using Amarok::Slider;
64 s_instance = this;
66 kapp->setTopWidget( this );
67 setCaption( KDialog::makeStandardCaption( i18n( "Equalizer" ) ) );
69 // Gives the window a small title bar, and skips a taskbar entry
70 #ifdef Q_WS_X11
71 KWindowSystem::setType( winId(), NET::Utility );
72 KWindowSystem::setState( winId(), NET::SkipTaskbar );
73 #endif
75 QWidget* vbox = new QWidget( this );
76 setMainWidget( vbox );
77 QVBoxLayout *vboxLayout = new QVBoxLayout;
78 vbox->setLayout( vboxLayout );
79 vboxLayout->setSpacing( KDialog::spacingHint() );
81 // BEGIN Presets
82 QWidget* presetBox = new QWidget( vbox );
83 vboxLayout->addWidget( presetBox );
84 QHBoxLayout *presetLayout = new QHBoxLayout;
85 presetLayout->setSpacing( KDialog::spacingHint() );
86 presetBox->setLayout( presetLayout );
88 presetLayout->addWidget( new QLabel( i18n("Presets:") ) );
90 m_presetCombo = new KComboBox;
91 presetLayout->addWidget( m_presetCombo );
92 m_presetCombo->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ) );
94 QPushButton* presetAdd = new QPushButton;
95 presetLayout->addWidget( presetAdd );
96 presetAdd->setIcon( KIcon( Amarok::icon( "add_playlist" ) ) );
97 presetAdd->setToolTip( i18n("Add new preset") );
98 connect( presetAdd, SIGNAL( clicked() ), SLOT( addPreset() ) );
100 QPushButton* presetConf = new QPushButton;
101 presetLayout->addWidget( presetConf );
102 presetConf->setIcon( KIcon( Amarok::icon( "configure" ) ) );
103 presetConf->setToolTip( i18n("Manage presets") );
104 connect( presetConf, SIGNAL( clicked() ), SLOT( editPresets() ) );
106 loadPresets();
107 connect( m_presetCombo, SIGNAL( activated(int) ), SLOT( presetChanged(int) ) );
108 // END Presets
110 // BEGIN GroupBox
111 m_groupBoxSliders = new QGroupBox( vbox );
112 vboxLayout->addWidget( m_groupBoxSliders );
113 m_groupBoxSliders->setTitle( i18n("Enable Equalizer") );
114 m_groupBoxSliders->setCheckable( true );
115 m_groupBoxSliders->setChecked( AmarokConfig::equalizerEnabled() );
116 connect( m_groupBoxSliders, SIGNAL( toggled( bool ) ), SLOT( setEqualizerEnabled( bool ) ) );
117 QVBoxLayout *v = new QVBoxLayout( m_groupBoxSliders );
119 // Helper widget for layouting inside the groupbox
120 QWidget* slidersLayoutWidget = new QWidget( m_groupBoxSliders );
121 v->addWidget( slidersLayoutWidget );
122 slidersLayoutWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
123 QGridLayout* slidersGridLayout = new QGridLayout( slidersLayoutWidget );
124 slidersGridLayout->setSpacing( KDialog::spacingHint() );
125 // END GroupBox
127 // BEGIN Preamp slider
128 m_slider_preamp = new Slider( Qt::Vertical, slidersLayoutWidget, 100 );
129 m_slider_preamp->setMinimum( -100 );
130 m_slider_preamp->setTickPosition( QSlider::TicksRight );
131 m_slider_preamp->setTickInterval( 100 );
132 connect( m_slider_preamp, SIGNAL( valueChanged( int ) ), SLOT( setEqualizerParameters() ) );
133 slidersGridLayout->addMultiCellWidget(m_slider_preamp, 0, 0, 0, 1, Qt::AlignHCenter );
135 QLabel* preampLabel = new QLabel( i18n("Pre-amp"), slidersLayoutWidget );
136 slidersGridLayout->addMultiCellWidget(preampLabel, 1, 1 , 0, 1, Qt::AlignHCenter );
137 // END
139 // BEGIN Band Sliders
140 const char *bandLabels[] = { "30", "60", "125", "250", "500", "1k", "2k", "4k", "8k", "16k" };
142 int minWidth = 0;
143 QFontMetrics fm = fontMetrics(); //apparently it's an expensive call
144 for ( int i = 0; i < 10; i++ ) {
145 int w = fm.width( bandLabels[i] );
146 if ( w > minWidth )
147 minWidth = w;
150 for ( int i = 0; i < 10; i++ ) {
151 Slider *slider = new Slider( Qt::Vertical, slidersLayoutWidget );
152 QLabel *label = new QLabel( slidersLayoutWidget );
153 label->setText( bandLabels[i] );
155 slider->setMinimum( -100 );
156 slider->setMaximum( +100 );
157 slider->setMinimumWidth( minWidth );
158 slidersGridLayout->addMultiCellWidget(slider, 0, 0, 2 * i + 2, 2 * i + 3, Qt::AlignHCenter );
159 slidersGridLayout->addMultiCellWidget(label, 1, 1, 2 * i + 2, 2 * i + 3, Qt::AlignHCenter );
160 m_bandSliders.append( slider );
162 connect( slider, SIGNAL( valueChanged( int ) ), SLOT( setEqualizerParameters() ) );
163 connect( slider, SIGNAL( valueChanged( int ) ), SLOT( sliderChanged() ) );
165 // END
167 // BEGIN Equalizer Graph Widget
168 QGroupBox* graphGBox = new QGroupBox();
169 vboxLayout->addWidget( graphGBox );
170 QHBoxLayout* h = new QHBoxLayout( graphGBox );
172 KVBox* graphVBox = new KVBox();
173 h->addWidget( graphVBox );
174 QLabel* graphLabel1 = new QLabel(graphVBox);
175 graphLabel1->setText("+20 db");
176 QLabel* graphLabel2 = new QLabel(graphVBox);
177 graphLabel2->setText("0 db");
178 QLabel* graphLabel3 = new QLabel(graphVBox);
179 graphLabel3->setText("-20 db");
180 graphLabel1->setAlignment( Qt::AlignRight | Qt::AlignTop );
181 graphLabel2->setAlignment( Qt::AlignRight | Qt::AlignVCenter );
182 graphLabel3->setAlignment( Qt::AlignRight | Qt::AlignBottom );
184 m_equalizerGraph = new EqualizerGraph( graphGBox );
185 h->addWidget( m_equalizerGraph );
186 m_equalizerGraph->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
187 // END Graph Widget
189 // Fill the combobox
190 updatePresets( AmarokConfig::equalizerPreset() );
192 // make sure to restore the current preamp value
193 m_slider_preamp->setValue( AmarokConfig::equalizerPreamp() );
195 // Init sliders
196 presetChanged( AmarokConfig::equalizerPreset() );
200 EqualizerSetup::~EqualizerSetup()
202 savePresets();
203 s_instance = 0;
206 void
207 EqualizerSetup::setActive( bool active )
209 m_groupBoxSliders->setChecked( active );
212 void
213 EqualizerSetup::setBands( int preamp, QList<int> gains )
215 m_slider_preamp->setValue( preamp );
217 // Note: As a side effect, this automatically switches the
218 // preset to 'Manual', which is by intention
219 for ( int i = 0; i < m_bandSliders.count(); i++ )
220 m_bandSliders.at(i)->setValue( gains.at(i) );
222 setEqualizerParameters();
225 void
226 EqualizerSetup::setPreset( QString name )
228 // Look for the preset id and verify name
229 int i, count = m_presetCombo->count();
230 bool found = false;
231 for( i = 0; i < count; i++ ) {
232 if ( m_presetCombo->itemText( i ) == name ) {
233 found = true;
234 break;
238 if ( found ) {
239 m_presetCombo->setCurrentIndex( i );
240 presetChanged( name );
244 /////////////////////////////////////////////////////////////////////////////////////
245 // EQUALIZER PRESETS
246 /////////////////////////////////////////////////////////////////////////////////////
248 QString
249 EqualizerSetup::presetsCache() const
251 // returns the playlists stats cache file
252 return Amarok::saveLocation() + "equalizerpresets_save.xml";
256 void
257 EqualizerSetup::loadPresets()
259 // Create predefined presets 'Zero' and 'Manual'
260 QList<int> zeroGains;
261 zeroGains << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0 << 0;
262 m_presets[ i18n("Manual") ] = zeroGains;
263 m_presets[ i18n("Zero") ] = zeroGains;
265 QFile file( presetsCache() );
266 if ( !file.exists() )
267 file.setFileName( KStandardDirs::locate( "data", "amarok/data/equalizer_presets.xml" ) );
269 QTextStream stream( &file );
270 stream.setCodec( "UTF8" );
272 QDomDocument d;
274 if( !file.open( QIODevice::ReadOnly ) || !d.setContent( stream.readAll() ) ) {
275 // Everything went wrong, so at least provide the two predefined presets
276 updatePresets( AmarokConfig::equalizerPreset() );
277 return;
280 QDomNode n = d.namedItem( "equalizerpresets" ).namedItem("preset");
282 for( ; !n.isNull(); n = n.nextSibling() )
284 QDomElement e = n.toElement();
285 QString title = e.attribute( "name" );
287 QList<int> gains;
288 gains << e.namedItem( "b0" ).toElement().text().toInt();
289 gains << e.namedItem( "b1" ).toElement().text().toInt();
290 gains << e.namedItem( "b2" ).toElement().text().toInt();
291 gains << e.namedItem( "b3" ).toElement().text().toInt();
292 gains << e.namedItem( "b4" ).toElement().text().toInt();
293 gains << e.namedItem( "b5" ).toElement().text().toInt();
294 gains << e.namedItem( "b6" ).toElement().text().toInt();
295 gains << e.namedItem( "b7" ).toElement().text().toInt();
296 gains << e.namedItem( "b8" ).toElement().text().toInt();
297 gains << e.namedItem( "b9" ).toElement().text().toInt();
299 m_presets[ title ] = gains;
302 file.close();
306 void
307 EqualizerSetup::savePresets()
309 QFile file( presetsCache() );
311 if( !file.open( QIODevice::WriteOnly ) ) return;
313 QDomDocument doc;
314 QDomElement e = doc.createElement("equalizerpresets");
315 e.setAttribute( "product", "Amarok" );
316 e.setAttribute( "version", APP_VERSION );
317 e.setAttribute( "formatversion", "1.1" );
319 doc.appendChild( e );
321 QStringList info;
322 info << "b0" << "b1" << "b2" << "b3" << "b4"
323 << "b5" << "b6" << "b7" << "b8" << "b9";
325 for( int x = 0; x < m_presets.count(); x++ )
327 const QString title = m_presetCombo->itemText( x );
329 // don't save the 'Zero' preset
330 if ( title == i18n("Zero") )
331 continue;
333 QList<int> gains = m_presets[ title ];
335 QDomElement i = doc.createElement("preset");
336 i.setAttribute( "name", title );
338 QDomElement attr;
339 QDomText t;
340 for( int y=0; y < info.count(); y++ )
342 attr = doc.createElement( info[y] );
343 t = doc.createTextNode( QString::number( gains.first() ) );
344 attr.appendChild( t );
345 i.appendChild( attr );
346 gains.pop_front();
348 e.appendChild( i );
351 QTextStream stream( &file );
352 stream.setCodec( "UTF8" );
353 stream << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
354 stream << doc.toString();
355 file.close();
358 void
359 EqualizerSetup::editPresets()
361 EqualizerPresetManager * editor = new EqualizerPresetManager(this);
362 editor->setPresets(m_presets);
364 if ( editor->exec() ) {
365 QMap< QString, QList<int> > presets = editor->presets();
367 QString currentTitle = m_presetCombo->currentText();
368 QList<int> currentGains= m_presets[ currentTitle ];
370 QString newTitle = currentTitle;
372 // Check if the selected item was renamed
373 if ( presets.find( currentTitle ) == presets.end() || currentGains != presets[ currentTitle ] ) {
375 // Find the new name
376 foreach( QString key, presets.keys() ) {
377 if ( presets[key] == currentGains ) {
378 newTitle = key;
379 break;
384 m_presets = presets;
385 updatePresets( newTitle );
388 delete editor;
391 void
392 EqualizerSetup::addPreset()
394 bool ok;
395 const QString title = KInputDialog::getText( i18n("Add Equalizer Preset"),
396 i18n("Enter preset name:"), i18n("Untitled"), &ok, this);
398 if (ok) {
399 // Check if the new preset title exists
400 if ( m_presets.find( title ) != m_presets.end() ) {
401 int button = KMessageBox::warningYesNo( this, i18n( "A preset with the name %1 already exists. Overwrite?", title ) );
403 if ( button != KMessageBox::Yes )
404 return;
407 // Add the new preset based on the current slider positions
408 QList <int> gains;
409 for ( int i = 0; i < m_bandSliders.count(); i++ )
410 gains += m_bandSliders.at( i )->value();
411 m_presets[ title ] = gains;
413 // Rebuild the combobox
414 updatePresets(title);
416 // Save
417 setEqualizerParameters();
421 void
422 EqualizerSetup::updatePresets(QString selectTitle)
424 // Save the selected item
425 if ( selectTitle.isEmpty() )
426 selectTitle = m_presetCombo->currentText();
428 // Sort titles
429 QStringList titles;
430 QMap< QString, QList<int> >::Iterator end = m_presets.end();
431 for ( QMap< QString, QList<int> >::Iterator it = m_presets.begin(); it != end; ++it )
432 titles << it.key();
434 titles.sort();
436 // rebuild preset combobox and look for the previously selected title
437 int i = 0;
438 int newIndex = -1;
439 m_presetCombo->clear();
440 QStringList::Iterator titlesEnd = titles.end();
441 for ( QStringList::Iterator it = titles.begin(); it != titlesEnd; ++it ) {
442 m_presetCombo->addItem( *it );
443 if ( *it == selectTitle )
444 newIndex = i;
445 if ( *it == i18n("Manual") )
446 m_manualPos = i;
447 i++;
450 if ( newIndex == -1 )
451 newIndex = m_manualPos;
453 m_presetCombo->setCurrentIndex( newIndex );
456 /////////////////////////////////////////////////////////////////////////////////////
457 // PRIVATE SLOTS
458 /////////////////////////////////////////////////////////////////////////////////////
460 void
461 EqualizerSetup::presetChanged( int id ) //SLOT
463 presetChanged( m_presetCombo->itemText(id) );
466 void
467 EqualizerSetup::presetChanged( QString title ) //SLOT
469 const QList<int> gains = m_presets[ title ];
471 for ( int i = 0; i < m_bandSliders.count(); i++ ) {
472 // Block signals to prevent unwanted setting to 'Manual'
473 m_bandSliders.at(i)->blockSignals(true);
474 m_bandSliders.at(i)->setValue( gains.at(i) );
475 m_bandSliders.at(i)->blockSignals(false);
478 setEqualizerParameters();
481 void
482 EqualizerSetup::setEqualizerEnabled( bool active ) //SLOT
484 EngineController::engine()->setEqualizerEnabled( active );
485 AmarokConfig::setEqualizerEnabled( active );
487 if( active )
488 //this way the developer of the eq doesn't have to cache the eq values
489 setEqualizerParameters();
490 else
491 // zero the graph
492 m_equalizerGraph->update();
496 void
497 EqualizerSetup::setEqualizerParameters() //SLOT
499 AmarokConfig::setEqualizerPreamp( m_slider_preamp->value() );
500 AmarokConfig::setEqualizerPreset( m_presetCombo->currentText() );
501 AmarokConfig::setEqualizerGains ( m_presets[ m_presetCombo->currentText() ] );
503 // Transfer values to the engine if the EQ is enabled
504 if ( AmarokConfig::equalizerEnabled() )
505 EngineController::engine()->setEqualizerParameters( m_slider_preamp->value(), m_presets[ m_presetCombo->currentText() ] );
507 m_equalizerGraph->update();
511 void
512 EqualizerSetup::sliderChanged() //SLOT
514 m_presetCombo->setCurrentIndex( m_manualPos );
516 QList<int> gains;
517 for ( int i = 0; i < m_bandSliders.count(); i++ )
518 gains += m_bandSliders.at( i )->value();
520 m_presets[ i18n("Manual") ] = gains;
523 #include "equalizersetup.moc"