Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/library/trackcollection.cpp

Go to the documentation of this file.
00001 #include <QtCore>
00002 #include <QtGui>
00003 #include <QtSql>
00004 #include <QtDebug>
00005 
00006 #include "trackcollection.h"
00007 
00008 #include "defs.h"
00009 #include "library/librarytablemodel.h"
00010 #include "library/schemamanager.h"
00011 #include "soundsourceproxy.h"
00012 #include "trackinfoobject.h"
00013 #include "xmlparse.h"
00014 
00015 TrackCollection::TrackCollection(ConfigObject<ConfigValue>* pConfig)
00016         : m_pConfig(pConfig),
00017           m_db(QSqlDatabase::addDatabase("QSQLITE")), // defaultConnection
00018           m_cueDao(m_db),
00019           m_playlistDao(m_db),
00020           m_crateDao(m_db),
00021           m_trackDao(m_db, m_cueDao, m_playlistDao, m_crateDao, pConfig),
00022           m_supportedFileExtensionsRegex(
00023               SoundSourceProxy::supportedFileExtensionsRegex(),
00024               Qt::CaseInsensitive) {
00025     bCancelLibraryScan = false;
00026     qDebug() << "Available QtSQL drivers:" << QSqlDatabase::drivers();
00027 
00028     m_db.setHostName("localhost");
00029     m_db.setDatabaseName(MIXXX_DB_PATH);
00030     m_db.setUserName("mixxx");
00031     m_db.setPassword("mixxx");
00032     bool ok = m_db.open();
00033     qDebug() << __FILE__ << "DB status:" << ok;
00034     if (m_db.lastError().isValid()) {
00035         qDebug() << "Error loading database:" << m_db.lastError();
00036     }
00037     // Check for tables and create them if missing
00038     if (!checkForTables()) {
00039         // TODO(XXX) something a little more elegant
00040         exit(-1);
00041     }
00042 }
00043 
00044 TrackCollection::~TrackCollection() {
00045     qDebug() << "~TrackCollection()";
00046     // Save all tracks that haven't been saved yet.
00047     m_trackDao.saveDirtyTracks();
00048     // TODO(XXX) Maybe fold saveDirtyTracks into TrackDAO::finish now that it
00049     // exists? -- rryan 10/2010
00050     m_trackDao.finish();
00051 
00052     Q_ASSERT(!m_db.rollback()); //Rollback any uncommitted transaction
00053     //The above is an ASSERT because there should never be an outstanding
00054     //transaction when this code is called. If there is, it means we probably
00055     //aren't committing a transaction somewhere that should be.
00056     m_db.close();
00057 }
00058 
00059 bool TrackCollection::checkForTables() {
00060     if (!m_db.open()) {
00061         QMessageBox::critical(0, tr("Cannot open database"),
00062                               tr("Unable to establish a database connection.\n"
00063                                  "Mixxx requires QT with SQLite support. Please read "
00064                                  "the Qt SQL driver documentation for information on how "
00065                                  "to build it.\n\n"
00066                                  "Click OK to exit."), QMessageBox::Ok);
00067         return false;
00068     }
00069 
00070     int requiredSchemaVersion = 13;
00071     if (!SchemaManager::upgradeToSchemaVersion(m_pConfig, m_db,
00072                                                requiredSchemaVersion)) {
00073         QMessageBox::warning(0, tr("Cannot upgrade database schema"),
00074                              tr("Unable to upgrade your database schema to version %1.\n"
00075                                 "Your mixxx.db file may be corrupt.\n"
00076                                 "Try renaming it and restarting Mixxx.\n\n"
00077                                 "Click OK to exit.").arg(requiredSchemaVersion),
00078                              QMessageBox::Ok);
00079         return false;
00080     }
00081 
00082     m_trackDao.initialize();
00083     m_playlistDao.initialize();
00084     m_crateDao.initialize();
00085     m_cueDao.initialize();
00086 
00087     return true;
00088 }
00089 
00090 QSqlDatabase& TrackCollection::getDatabase() {
00091     return m_db;
00092 }
00093 
00098 bool TrackCollection::importDirectory(QString directory, TrackDAO &trackDao,
00099                                       QList<TrackInfoObject*>& tracksToAdd) {
00100     //qDebug() << "TrackCollection::importDirectory(" << directory<< ")";
00101 
00102     emit(startedLoading());
00103     QFileInfoList files;
00104 
00105     //Check to make sure the path exists.
00106     QDir dir(directory);
00107     if (dir.exists()) {
00108         files = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
00109     } else {
00110         qDebug() << "Error: Import path does not exist." << directory;
00111         return true;
00112     }
00113 
00114     //The directory exists, so get a list of the contents of the directory and go through it.
00115     QList<QFileInfo>::iterator it = files.begin();
00116     while (it != files.end()) {
00117         QFileInfo file = *it; //TODO: THIS IS SLOW!
00118         it++;
00119 
00120         //If a flag was raised telling us to cancel the library scan then stop.
00121         m_libraryScanMutex.lock();
00122         bool cancel = bCancelLibraryScan;
00123         m_libraryScanMutex.unlock();
00124         if (cancel) {
00125             return false;
00126         }
00127 
00128         QString absoluteFilePath = file.absoluteFilePath();
00129         QString fileName = file.fileName();
00130 
00131         if (fileName.count(m_supportedFileExtensionsRegex)) {
00132             //If the track is in the database, mark it as existing. This code gets exectuted
00133             //when other files in the same directory have changed (the directory hash has changed).
00134             trackDao.markTrackLocationAsVerified(absoluteFilePath);
00135 
00136             // If the file already exists in the database, continue and go on to
00137             // the next file.
00138 
00139             // If the file doesn't already exist in the database, then add
00140             // it. If it does exist in the database, then it is either in the
00141             // user's library OR the user has "removed" the track via
00142             // "Right-Click -> Remove". These tracks stay in the library, but
00143             // their mixxx_deleted column is 1.
00144             if (!trackDao.trackExistsInDatabase(absoluteFilePath))
00145             {
00146                 //qDebug() << "Loading" << file.fileName();
00147                 emit(progressLoading(fileName));
00148 
00149                 // addTrack uses this QFileInfo instead of making a new one now.
00150                 //trackDao.addTrack(file);
00151                 TrackInfoObject* pTrack = new TrackInfoObject(file.absoluteFilePath());
00152                 tracksToAdd.append(pTrack);
00153             }
00154         } else {
00155             //qDebug() << "Skipping" << file.fileName() <<
00156             //    "because it did not match thesupported audio files filter:" <<
00157         }
00158     }
00159     emit(finishedLoading());
00160     return true;
00161 }
00162 
00163 void TrackCollection::slotCancelLibraryScan() {
00164     m_libraryScanMutex.lock();
00165     bCancelLibraryScan = 1;
00166     m_libraryScanMutex.unlock();
00167 }
00168 
00169 void TrackCollection::resetLibaryCancellation() {
00170     m_libraryScanMutex.lock();
00171     bCancelLibraryScan = 0;
00172     m_libraryScanMutex.unlock();
00173 }
00174 
00175 CrateDAO& TrackCollection::getCrateDAO() {
00176     return m_crateDao;
00177 }
00178 
00179 TrackDAO& TrackCollection::getTrackDAO() {
00180     return m_trackDao;
00181 }
00182 
00183 PlaylistDAO& TrackCollection::getPlaylistDAO() {
00184     return m_playlistDao;
00185 }
00186 
00187 QSharedPointer<BaseTrackCache> TrackCollection::getTrackSource(
00188     const QString name) {
00189     return m_trackSources.value(name, QSharedPointer<BaseTrackCache>());
00190 }
00191 
00192 void TrackCollection::addTrackSource(
00193     const QString name, QSharedPointer<BaseTrackCache> trackSource) {
00194     Q_ASSERT(!m_trackSources.contains(name));
00195     m_trackSources[name] = trackSource;
00196 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines