Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/dlgprefbpm.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           dlgprefbpm.cpp  -  description
00003                              -------------------
00004     begin                : Thu Jun 7 2007
00005     copyright            : (C) 2007 by John Sully
00006     email                : jsully@scs.ryerson.ca
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 *                                                                         *
00011 *   This program is free software; you can redistribute it and/or modify  *
00012 *   it under the terms of the GNU General Public License as published by  *
00013 *   the Free Software Foundation; either version 2 of the License, or     *
00014 *   (at your option) any later version.                                   *
00015 *                                                                         *
00016 ***************************************************************************/
00017 
00018 #include <qlineedit.h>
00019 #include <qfiledialog.h>
00020 #include <qwidget.h>
00021 #include <qspinbox.h>
00022 #include <qcheckbox.h>
00023 #include <qlabel.h>
00024 #include <qstring.h>
00025 #include <qpushbutton.h>
00026 #include <QtCore>
00027 #include <QMessageBox>
00028 
00029 #include "dlgprefbpm.h"
00030 #include "dlgbpmscheme.h"
00031 #include "bpm/bpmscheme.h"
00032 #include "xmlparse.h"
00033 
00034 #define CONFIG_KEY "[BPM]"
00035 
00036 DlgPrefBpm::DlgPrefBpm(QWidget * parent, ConfigObject<ConfigValue> * _config) : QWidget(parent), Ui::DlgPrefBPMDlg()
00037 {
00038     config = _config;
00039 
00040     setupUi(this);
00041 
00042     // Connection
00043     connect(chkDetectOnImport,      SIGNAL(stateChanged(int)), this, SLOT(slotSetBpmDetectOnImport(int)));
00044     connect(chkWriteID3,            SIGNAL(stateChanged(int)), this, SLOT(slotSetWriteID3Tag(int)));
00045     connect(chkEnableBpmDetection,  SIGNAL(stateChanged(int)), this, SLOT(slotSetBpmEnabled(int)));
00046     connect(chkAboveRange,          SIGNAL(stateChanged(int)), this, SLOT(slotSetAboveRange(int)));
00047 
00048     // TODO: Move this over the the scheme dialog
00049 
00050     connect(btnAdd,        SIGNAL(pressed()),         this, SLOT(slotAddBpmScheme()));
00051     connect(btnEdit,       SIGNAL(pressed()),         this, SLOT(slotEditBpmScheme()));
00052     connect(btnDelete,     SIGNAL(pressed()),         this, SLOT(slotDeleteBpmScheme()));
00053     connect(btnDefault,    SIGNAL(pressed()),         this, SLOT(slotDefaultBpmScheme()));
00054 
00055 
00056     // Determine if the config value has already been set. If not, default to enabled
00057     QString sBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"));
00058     if(sBpmEnabled.isNull() || sBpmEnabled.isEmpty())
00059     {
00060         config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(1));
00061     }
00062 
00063     // Set default value for analyze mode check box
00064     int iBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled")).toInt();
00065     if (iBpmEnabled)
00066         chkEnableBpmDetection->setChecked(true);
00067     else
00068         chkEnableBpmDetection->setChecked(false);
00069 
00070     int iBpmAboveRange = config->getValueString(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled")).toInt();
00071     if (iBpmAboveRange)
00072         chkAboveRange->setChecked(true);
00073     else
00074         chkAboveRange->setChecked(false);
00075 
00076     // Set default value for detect BPM on import check box
00077     int iDetectBpmOnImport = config->getValueString(ConfigKey(CONFIG_KEY,"DetectBPMOnImport")).toInt();
00078     if (iDetectBpmOnImport)
00079         chkDetectOnImport->setChecked(true);
00080     else
00081         chkDetectOnImport->setChecked(false);
00082 
00083     // Set default value for write ID3 tag check box
00084     int iWriteID3Tag = config->getValueString(ConfigKey(CONFIG_KEY,"WriteID3Tag")).toInt();
00085     if (iWriteID3Tag)
00086         chkWriteID3->setChecked(true);
00087     else
00088         chkWriteID3->setChecked(false);
00089 
00090     chkWriteID3->setEnabled(false);
00091     chkDetectOnImport->setEnabled(false);
00092 
00093     // Load the BPM schemes
00094     loadBpmSchemes();
00095     populateBpmSchemeList();
00096 
00097     updateBpmEnabled();
00098 
00099 
00100     //Load BPM Range Values
00101     /*int iRangeStart = config->getValueString(ConfigKey("[BPM]","BPMRangeStart")).toInt();
00102     if(iRangeStart > 0 && iRangeStart <= 220)
00103         spinBoxBPMRangeStart->setValue(iRangeStart);
00104     else
00105         spinBoxBPMRangeStart->setValue(60);
00106 
00107     int iRangeEnd = config->getValueString(ConfigKey("[BPM]","BPMRangeEnd")).toInt();
00108     if(iRangeEnd > 0 && iRangeEnd <=220)
00109         spinBoxBPMRangeEnd->setValue(iRangeEnd);
00110     else
00111         spinBoxBPMRangeEnd->setValue(180);*/
00112 
00113 }
00114 
00115 DlgPrefBpm::~DlgPrefBpm()
00116 {
00117     saveBpmSchemes();
00118 
00119     while (!m_BpmSchemes.isEmpty())
00120     {
00121         delete m_BpmSchemes.takeFirst();
00122     }
00123 }
00124 
00125 void DlgPrefBpm::slotSetBpmDetectOnImport(int)
00126 {
00127     if (chkDetectOnImport->isChecked())
00128         config->set(ConfigKey(CONFIG_KEY,"DetectBPMOnImport"), ConfigValue(1));
00129     else
00130         config->set(ConfigKey(CONFIG_KEY,"DetectBPMOnImport"), ConfigValue(0));
00131 }
00132 
00133 void DlgPrefBpm::slotSetWriteID3Tag(int)
00134 {
00135     if (chkWriteID3->isChecked())
00136         config->set(ConfigKey(CONFIG_KEY,"WriteID3Tag"), ConfigValue(1));
00137     else
00138         config->set(ConfigKey(CONFIG_KEY,"WriteID3Tag"), ConfigValue(0));
00139 }
00140 
00141 void DlgPrefBpm::slotSetBpmEnabled(int)
00142 {
00143     if (chkEnableBpmDetection->isChecked())
00144         config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(1));
00145     else
00146         config->set(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled"), ConfigValue(0));
00147 
00148     updateBpmEnabled();
00149 
00150 }
00151 
00152 void DlgPrefBpm::slotSetAboveRange(int) {
00153     if (chkAboveRange->isChecked())
00154         config->set(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled"), ConfigValue(1));
00155     else
00156         config->set(ConfigKey(CONFIG_KEY,"BPMAboveRangeEnabled"), ConfigValue(0));
00157 }
00158 
00159 void DlgPrefBpm::slotSetBpmRangeStart(int begin)
00160 {
00161     //config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(begin));
00162 }
00163 
00164 void DlgPrefBpm::slotSetBpmRangeEnd(int end)
00165 {
00166     //config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(end));
00167 }
00168 
00169 void DlgPrefBpm::slotEditBpmScheme()
00170 {
00171     int row = lstSchemes->currentRow();
00172 
00173     if(row > -1)
00174     {
00175         BpmScheme *schemeToEdit = m_BpmSchemes.at(row);
00176         QString oldname = schemeToEdit->getName();
00177 
00178         // Open the BPM scheme dialog to edit
00179         DlgBpmScheme* SchemeEdit = new DlgBpmScheme(schemeToEdit);
00180         SchemeEdit->setModal(true);
00181         SchemeEdit->exec();
00182 
00183         QListWidgetItem *item = lstSchemes->item(row);
00184         item->setText(schemeToEdit->getName());
00185 
00186         if(oldname == config->getValueString(ConfigKey("[BPM]","DefaultScheme")))
00187         {
00188             config->set(ConfigKey("[BPM]","DefaultScheme"), schemeToEdit->getName());
00189         }
00190     }
00191 }
00192 
00193 void DlgPrefBpm::slotAddBpmScheme()
00194 {
00195     BpmScheme *schemeToAdd = NULL;
00196 
00197     // Open the BPM scheme dialog to add
00198     DlgBpmScheme* SchemeEdit = new DlgBpmScheme(schemeToAdd);
00199     SchemeEdit->setModal(true);
00200 
00201     if(SchemeEdit->exec() == QDialog::Accepted)
00202     {
00203         if(schemeToAdd)
00204         {
00205             m_BpmSchemes.push_back(schemeToAdd);
00206             QListWidgetItem *addScheme = new QListWidgetItem(lstSchemes);
00207             addScheme->setText(schemeToAdd->getName());
00208         }
00209     }
00210     else
00211     {
00212         delete schemeToAdd;
00213     }
00214 
00215 
00216 }
00217 
00218 void DlgPrefBpm::slotDeleteBpmScheme()
00219 {
00220     int row = lstSchemes->currentRow();
00221 
00222     if(row > -1)
00223     {
00224         qDebug() << "Removing Bpm Scheme at position " << row;
00225         delete lstSchemes->takeItem(row);
00226         m_BpmSchemes.removeAt(row);
00227     }
00228 }
00229 
00230 void DlgPrefBpm::slotDefaultBpmScheme()
00231 {
00232     int row = lstSchemes->currentRow();
00233 
00234     if(row > -1)
00235     {
00236         BpmScheme* scheme = m_BpmSchemes.at(row);
00237 
00238         config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(scheme->getMaxBpm()));
00239         config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(scheme->getMinBpm()));
00240         config->set(ConfigKey("[BPM]","AnalyzeEntireSong"),ConfigValue(scheme->getAnalyzeEntireSong()));
00241         config->set(ConfigKey("[BPM]","DefaultScheme"), scheme->getName());
00242 
00243         clearListIcons();
00244 
00245         QListWidgetItem *item = lstSchemes->item(row);
00246         item->setIcon(QIcon(":/images/preferences/ic_preferences_bpmdetect.png"));
00247     }
00248 }
00249 
00250 void DlgPrefBpm::clearListIcons()
00251 {
00252     for(int i=0; i < lstSchemes->count(); ++i)
00253     {
00254         lstSchemes->item(i)->setIcon(QIcon(""));
00255     }
00256 }
00257 
00258 void DlgPrefBpm::slotApply()
00259 {
00260     saveBpmSchemes();
00261 }
00262 
00263 void DlgPrefBpm::slotUpdate()
00264 {
00265 }
00266 
00267 void DlgPrefBpm::updateBpmEnabled()
00268 {
00269     int iBpmEnabled = config->getValueString(ConfigKey(CONFIG_KEY,"BPMDetectionEnabled")).toInt();
00270     if (iBpmEnabled)
00271     {
00272         chkDetectOnImport->setEnabled(true);
00273         chkWriteID3->setEnabled(true);
00274         chkAboveRange->setEnabled(true);
00275         grpBpmSchemes->setEnabled(true);
00276     }
00277     else
00278     {
00279         chkDetectOnImport->setEnabled(false);
00280         chkWriteID3->setEnabled(false);
00281         chkAboveRange->setEnabled(false);
00282         grpBpmSchemes->setEnabled(false);
00283     }
00284 
00285     // These are not implemented yet, so don't enable them
00286     chkDetectOnImport->setEnabled(false);
00287     chkWriteID3->setEnabled(false);
00288 
00289 }
00290 
00291 void DlgPrefBpm::loadBpmSchemes()
00292 {
00293     // Verify path for xml track file.
00294     QString schemeFileName = config->getValueString(ConfigKey("[BPM]","SchemeFile"));
00295     if (schemeFileName.trimmed().isEmpty() | !QFile(schemeFileName).exists() ) {
00296         schemeFileName = QDir::homePath().append("/").append(SETTINGS_PATH).append(BPMSCHEME_FILE);
00297         qDebug() << "BPM Scheme File ConfigKey not set or file missing... setting to"<< schemeFileName;
00298         config->set(ConfigKey("[BPM]","SchemeFile"), schemeFileName);
00299         config->Save();
00300     }
00301 
00302     QString location(config->getValueString(ConfigKey("[BPM]","SchemeFile")));
00303     qDebug() << "BpmSchemes::readXML" << location;
00304 
00305     // Open XML file
00306     QFile file(location);
00307 
00308     // Check if we can open the file
00309     if (!file.exists())
00310     {
00311         qDebug() << "BPM Scheme:" << location <<  "does not exist.";
00312         file.close();
00313         return;
00314     }
00315 
00316     if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
00317         qDebug() << "BPM Scheme:" << location <<  "can't open file for reading.";
00318         return;
00319     }
00320 
00321     QByteArray fileData = file.readAll();
00322     QByteArray badHeader = QByteArray("<?xml version=\"1.0\" encoding=\"UTF-16\"?>");
00323     QByteArray goodHeader = QByteArray("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
00324 
00325     // We've been writing UTF-16 as the encoding forever but actually writing
00326     // the file in UTF-8 (well, latin1 actually). Qt seems to have started
00327     // caring recently. Manually fix the header if we are dealing with an old
00328     // file.
00329     fileData.replace(badHeader, goodHeader);
00330 
00331     QDomDocument domXML("Mixxx_BPM_Scheme_List");
00332 
00333 
00334 
00335     // Check if there is a parsing problem
00336     QString error_msg;
00337     int error_line;
00338     int error_column;
00339     if (!domXML.setContent(fileData, &error_msg, &error_line, &error_column))
00340     {
00341         qDebug() << "BPM Scheme Parse error in" << location;
00342         qDebug() << "Doctype:" << domXML.doctype().name();
00343         qDebug() << error_msg << "on line" << error_line << ", column" << error_column;
00344         file.close();
00345         return;
00346     }
00347 
00348     file.close();
00349 
00350     // Get the root element
00351     QDomElement elementRoot = domXML.documentElement();
00352 
00353     // Get version
00354     //int version = XmlParse::selectNodeInt(elementRoot, "Version");
00355 
00356     // Get all the BPM schemes written in the xml file:
00357     QDomNode node = XmlParse::selectNode(elementRoot, "Schemes").firstChild();
00358     BpmScheme* bpmScheme; //Current BPM Scheme
00359     while (!node.isNull())
00360     {
00361         if (node.isElement() && node.nodeName()=="Scheme")
00362         {
00363             bpmScheme = new BpmScheme();
00364             //Create the playlists internally.
00365             //If the playlist is "Library" or "Play Queue", insert it into
00366             //a special spot in the list of playlists.
00367             bpmScheme->setName(XmlParse::selectNodeQString(node, "Name"));
00368             bpmScheme->setMinBpm(XmlParse::selectNodeQString(node, "MinBpm").toInt());
00369             bpmScheme->setMaxBpm(XmlParse::selectNodeQString(node, "MaxBpm").toInt());
00370             bpmScheme->setAnalyzeEntireSong((bool)XmlParse::selectNodeQString(node,
00371                                                         "AnalyzeEntireSong").toInt());
00372             bpmScheme->setComment(XmlParse::selectNodeQString(node, "Comment"));
00373 
00374             m_BpmSchemes.push_back(bpmScheme);
00375         }
00376 
00377         node = node.nextSibling();
00378     }
00379 
00380     if(m_BpmSchemes.size() == 0)
00381     {
00382         BpmScheme *scheme = new BpmScheme("Default", 70, 140, false);
00383         m_BpmSchemes.push_back(scheme);
00384         config->set(ConfigKey("[BPM]","DefaultScheme"), QString("Default"));
00385         config->set(ConfigKey("[BPM]","BPMRangeEnd"),ConfigValue(scheme->getMaxBpm()));
00386         config->set(ConfigKey("[BPM]","BPMRangeStart"),ConfigValue(scheme->getMinBpm()));
00387         config->set(ConfigKey("[BPM]","AnalyzeEntireSong"),ConfigValue(scheme->getAnalyzeEntireSong()));
00388     }
00389 }
00390 
00391 void DlgPrefBpm::saveBpmSchemes()
00392 {
00393     QString location(config->getValueString(ConfigKey("[BPM]","SchemeFile")));
00394 
00395     // Create the xml document:
00396     QDomDocument domXML( "Mixxx_BPM_Scheme_List" );
00397 
00398     // Ensure UTF16 encoding
00399     domXML.appendChild(domXML.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\""));
00400 
00401     // Set the document type
00402     QDomElement elementRoot = domXML.createElement( "Mixxx_BPM_Scheme_List" );
00403     domXML.appendChild(elementRoot);
00404 
00405     // Add version information:
00406     //XmlParse::addElement(domXML, elementRoot, "Version", QString("%1").arg(TRACK_VERSION));
00407 
00408     // Write playlists
00409     QDomElement schemesroot = domXML.createElement("Schemes");
00410 
00411     QListIterator<BpmScheme*> it(m_BpmSchemes);
00412     BpmScheme* current;
00413     while (it.hasNext())
00414     {
00415         current = it.next();
00416 
00417         QDomElement elementNew = domXML.createElement("Scheme");
00418         current->writeXML(domXML, elementNew);
00419         schemesroot.appendChild(elementNew);
00420 
00421     }
00422     elementRoot.appendChild(schemesroot);
00423 
00424     // Open the file:
00425     QFile opmlFile(location);
00426     if (!opmlFile.open(QIODevice::WriteOnly))
00427     {
00428         QMessageBox::critical(0,
00429                               tr("Error"),
00430                               tr("Cannot open file %1").arg(location));
00431         return;
00432     }
00433     // QByteArray encoded in UTF-8
00434     QByteArray ba = domXML.toByteArray();
00435     opmlFile.write(ba.constData(), ba.size());
00436     opmlFile.close();
00437 }
00438 
00439 void DlgPrefBpm::populateBpmSchemeList()
00440 {
00441     QString defaultscheme = config->getValueString(ConfigKey("[BPM]","DefaultScheme"));
00442 
00443     for(int i=0; i < m_BpmSchemes.size(); ++i)
00444     {
00445         QListWidgetItem* scheme = new QListWidgetItem(lstSchemes);
00446         scheme->setText(m_BpmSchemes.at(i)->getName());
00447         if(m_BpmSchemes.at(i)->getName() == defaultscheme)
00448         {
00449             scheme->setIcon(QIcon(":/images/preferences/ic_preferences_bpmdetect.png"));
00450         }
00451     }
00452 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines