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 /***************************************************************************
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. *
16 ***************************************************************************/
18 #include "equalizersetup.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>
30 #include <KIconLoader>
31 #include <KInputDialog> //presets
34 #include <KMessageBox>
35 #include <KStandardDirs> //locate()
37 #include <KWindowSystem>
40 #include <QDomDocument>
41 #include <QDomElement>
47 #include <QPushButton>
48 #include <QTextStream> //presets
52 EqualizerSetup
* EqualizerSetup::s_instance
= 0;
55 EqualizerSetup::EqualizerSetup()
56 : KDialog( Amarok::mainWindow() )
60 showButtonSeparator( false );
66 kapp
->setTopWidget( this );
67 setCaption( KDialog::makeStandardCaption( i18n( "Equalizer" ) ) );
69 // Gives the window a small title bar, and skips a taskbar entry
71 KWindowSystem::setType( winId(), NET::Utility
);
72 KWindowSystem::setState( winId(), NET::SkipTaskbar
);
75 QWidget
* vbox
= new QWidget( this );
76 setMainWidget( vbox
);
77 QVBoxLayout
*vboxLayout
= new QVBoxLayout
;
78 vbox
->setLayout( vboxLayout
);
79 vboxLayout
->setSpacing( KDialog::spacingHint() );
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() ) );
107 connect( m_presetCombo
, SIGNAL( activated(int) ), SLOT( presetChanged(int) ) );
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() );
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
);
139 // BEGIN Band Sliders
140 const char *bandLabels
[] = { "30", "60", "125", "250", "500", "1k", "2k", "4k", "8k", "16k" };
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
] );
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() ) );
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
);
190 updatePresets( AmarokConfig::equalizerPreset() );
192 // make sure to restore the current preamp value
193 m_slider_preamp
->setValue( AmarokConfig::equalizerPreamp() );
196 presetChanged( AmarokConfig::equalizerPreset() );
200 EqualizerSetup::~EqualizerSetup()
207 EqualizerSetup::setActive( bool active
)
209 m_groupBoxSliders
->setChecked( active
);
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();
226 EqualizerSetup::setPreset( QString name
)
228 // Look for the preset id and verify name
229 int i
, count
= m_presetCombo
->count();
231 for( i
= 0; i
< count
; i
++ ) {
232 if ( m_presetCombo
->itemText( i
) == name
) {
239 m_presetCombo
->setCurrentIndex( i
);
240 presetChanged( name
);
244 /////////////////////////////////////////////////////////////////////////////////////
246 /////////////////////////////////////////////////////////////////////////////////////
249 EqualizerSetup::presetsCache() const
251 // returns the playlists stats cache file
252 return Amarok::saveLocation() + "equalizerpresets_save.xml";
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" );
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() );
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" );
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
;
307 EqualizerSetup::savePresets()
309 QFile
file( presetsCache() );
311 if( !file
.open( QIODevice::WriteOnly
) ) return;
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
);
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") )
333 QList
<int> gains
= m_presets
[ title
];
335 QDomElement i
= doc
.createElement("preset");
336 i
.setAttribute( "name", title
);
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
);
351 QTextStream
stream( &file
);
352 stream
.setCodec( "UTF8" );
353 stream
<< "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
354 stream
<< doc
.toString();
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
] ) {
376 foreach( const QString
&key
, presets
.keys() ) {
377 if ( presets
[key
] == currentGains
) {
385 updatePresets( newTitle
);
392 EqualizerSetup::addPreset()
395 const QString title
= KInputDialog::getText( i18n("Add Equalizer Preset"),
396 i18n("Enter preset name:"), i18n("Untitled"), &ok
, this);
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
)
407 // Add the new preset based on the current slider positions
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
);
417 setEqualizerParameters();
422 EqualizerSetup::updatePresets(QString selectTitle
)
424 // Save the selected item
425 if ( selectTitle
.isEmpty() )
426 selectTitle
= m_presetCombo
->currentText();
430 QMap
< QString
, QList
<int> >::Iterator end
= m_presets
.end();
431 for ( QMap
< QString
, QList
<int> >::Iterator it
= m_presets
.begin(); it
!= end
; ++it
)
436 // rebuild preset combobox and look for the previously selected title
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
)
445 if ( *it
== i18n("Manual") )
450 if ( newIndex
== -1 )
451 newIndex
= m_manualPos
;
453 m_presetCombo
->setCurrentIndex( newIndex
);
456 /////////////////////////////////////////////////////////////////////////////////////
458 /////////////////////////////////////////////////////////////////////////////////////
461 EqualizerSetup::presetChanged( int id
) //SLOT
463 presetChanged( m_presetCombo
->itemText(id
) );
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();
482 EqualizerSetup::setEqualizerEnabled( bool active
) //SLOT
484 EngineController::engine()->setEqualizerEnabled( active
);
485 AmarokConfig::setEqualizerEnabled( active
);
488 //this way the developer of the eq doesn't have to cache the eq values
489 setEqualizerParameters();
492 m_equalizerGraph
->update();
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();
512 EqualizerSetup::sliderChanged() //SLOT
514 m_presetCombo
->setCurrentIndex( m_manualPos
);
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"