Mixxx

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

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 1.7.x library upgrade code
00003  *
00004  * Description:
00005  *
00006  * Parse the mixxxtrack.xml file in order to create list of of songs to be
00007  * added to the sqlite database 1.8+ uses
00008  *
00009  * ***********************************************************************/
00010 
00011 #include <QDomDocument>
00012 #include <QDomNodeList>
00013 #include <QDomNode>
00014 #include <QDir>
00015 #include <QFile>
00016 #include <QDebug>
00017 #include "trackinfoobject.h" //needed for importing 1.7.x library
00018 #include "xmlparse.h" //needed for importing 1.7.x library
00019 #include "legacylibraryimporter.h"
00020 
00021 struct LegacyPlaylist
00022 {
00023     QString name;
00024     QList<int> indexes;
00025 };
00026 
00027 void doNothing(TrackInfoObject*) {
00028 
00029 }
00030 
00031 LegacyLibraryImporter::LegacyLibraryImporter(TrackDAO& trackDao,
00032                                              PlaylistDAO& playlistDao) : QObject(),
00033     m_trackDao(trackDao),
00034     m_playlistDao(playlistDao)
00035 {
00036 }
00037 
00039 void LegacyLibraryImporter::import()
00040 {
00041     QString trackXML = QDir::homePath().append("/").append(SETTINGS_PATH).append("mixxxtrack.xml");
00042     QFile file(trackXML);
00043 
00044     QDomDocument doc("TrackList");
00045 
00046     if(!file.open(QIODevice::ReadOnly)) {
00047         //qDebug() << "Could not import legacy 1.7 XML library: " << trackXML;
00048         return;
00049     }
00050 
00051     QString* errorMsg = NULL;
00052     int* errorLine = NULL;
00053     int* errorColumn = NULL;
00054 
00055     qDebug() << "Starting upgrade from 1.7 library...";
00056 
00057     QHash<int, QString> playlistHashTable; //Maps track indices onto track locations
00058     QList<LegacyPlaylist> legacyPlaylists; // <= 1.7 playlists
00059 
00060     if (doc.setContent(&file, false, errorMsg, errorLine, errorColumn)) {
00061 
00062         QDomNodeList playlistList = doc.elementsByTagName("Playlist");
00063         QDomNode playlist;
00064         for (int i = 0; i < playlistList.size(); i++)
00065         {
00066             LegacyPlaylist legPlaylist;
00067             playlist = playlistList.at(i);
00068 
00069             QString name = playlist.firstChildElement("Name").text();
00070 
00071             legPlaylist.name = name;
00072 
00073             //Store the IDs in the hash table so we can map them to track locations later,
00074             //and also store them in-order in a temporary playlist struct.
00075             QDomElement listNode = playlist.firstChildElement("List").toElement();
00076             QDomNodeList trackIDs = listNode.elementsByTagName("Id");
00077             for (int j = 0; j < trackIDs.size(); j++)
00078             {
00079                 int id = trackIDs.at(j).toElement().text().toInt();
00080                 if (!playlistHashTable.contains(id))
00081                     playlistHashTable.insert(id, "");
00082                 legPlaylist.indexes.push_back(id); //Save this track id.
00083             }
00084             //Save this playlist in our list.
00085             legacyPlaylists.push_back(legPlaylist);
00086         }
00087 
00088         QDomNodeList trackList = doc.elementsByTagName("Track");
00089         QDomNode track;
00090 
00091         for (int i = 0; i < trackList.size(); i++) {
00092             //blah, can't figure out how to use an iterator with QDomNodeList
00093             track = trackList.at(i);
00094             TrackInfoObject trackInfo17(track);
00095             //Only add the track to the DB if the file exists on disk,
00096             //because Mixxx <= 1.7 had no logic to deal with detecting deleted
00097             //files.
00098 
00099             if (trackInfo17.exists()) {
00100                 //Create a TrackInfoObject by directly parsing
00101                 //the actual MP3/OGG/whatever because 1.7 didn't parse
00102                 //genre and album tags (so the imported TIO doesn't have
00103                 //those fields).
00104                 emit(progress("Upgrading Mixxx 1.7 Library: " + trackInfo17.getTitle()));
00105 
00106                 // Read the metadata we couldn't support in <1.8 from file.
00107                 QFileInfo fileInfo(trackInfo17.getLocation());
00108                 //Ensure we have the absolute file path stored
00109                 trackInfo17.setLocation(fileInfo.absoluteFilePath());
00110                 TrackInfoObject trackInfoNew(trackInfo17.getLocation());
00111                 trackInfo17.setGenre(trackInfoNew.getGenre());
00112                 trackInfo17.setAlbum(trackInfoNew.getAlbum());
00113                 trackInfo17.setYear(trackInfoNew.getYear());
00114                 trackInfo17.setType(trackInfoNew.getType());
00115                 trackInfo17.setTrackNumber(trackInfoNew.getTrackNumber());
00116                 trackInfo17.setKey(trackInfoNew.getKey());
00117                 trackInfo17.setHeaderParsed(true);
00118 
00119                 // Import the track's saved cue point if it is non-zero.
00120                 float fCuePoint = trackInfo17.getCuePoint();
00121                 if (fCuePoint != 0.0f) {
00122                     Cue* pCue = trackInfo17.addCue();
00123                     pCue->setType(Cue::CUE);
00124                     pCue->setPosition(fCuePoint);
00125                 }
00126 
00127                 // Provide a no-op deleter b/c this Track is on the stack.
00128                 TrackPointer pTrack(&trackInfo17, &doNothing);
00129                 m_trackDao.saveTrack(pTrack);
00130 
00131                 //Check if this track is used in a playlist anywhere. If it is, save the
00132                 //track location. (The "id" of a track in 1.8 is a database index, so it's totally
00133                 //different. Using the track location is the best way for us to identify the song.)
00134                 int id = trackInfo17.getId();
00135                 if (playlistHashTable.contains(id))
00136                     playlistHashTable[id] = trackInfo17.getLocation();
00137             }
00138         }
00139 
00140 
00141         //Create the imported playlists
00142         QListIterator<LegacyPlaylist> it(legacyPlaylists);
00143         LegacyPlaylist current;
00144         while (it.hasNext())
00145         {
00146             current = it.next();
00147             emit(progress("Upgrading Mixxx 1.7 Playlists: " + current.name));
00148 
00149             //Create the playlist with the imported name.
00150             //qDebug() << "Importing playlist:" << current.name;
00151             m_playlistDao.createPlaylist(current.name, false);
00152             int playlistId = m_playlistDao.getPlaylistIdFromName(current.name);
00153 
00154             //For each track ID in the XML...
00155             QList<int> trackIDs = current.indexes;
00156             for (int i = 0; i < trackIDs.size(); i++)
00157             {
00158                 QString trackLocation;
00159                 int id = trackIDs[i];
00160                 //qDebug() << "track ID:" << id;
00161 
00162                 //Try to resolve the (XML's) track ID to a track location.
00163                 if (playlistHashTable.contains(id)) {
00164                     trackLocation = playlistHashTable[id];
00165                     //qDebug() << "Resolved to:" << trackLocation;
00166                 }
00167 
00168                 //Get the database's track ID (NOT the XML's track ID!)
00169                 int dbTrackId = m_trackDao.getTrackId(trackLocation);
00170 
00171                 if (dbTrackId >= 0) {
00172                     //Add it to the database's playlist.
00173                     m_playlistDao.appendTrackToPlaylist(dbTrackId, playlistId);
00174                 }
00175             }
00176         }
00177 
00178         QString upgrade_filename = QDir::homePath().append("/").append(SETTINGS_PATH).append("DBUPGRADED");
00179         //now create stub so that the library is not readded next time program loads
00180         QFile upgradefile(upgrade_filename);
00181         if (!upgradefile.open(QIODevice::WriteOnly | QIODevice::Text))
00182             qDebug() << "Couldn't open" << upgrade_filename << "for writing";
00183         else
00184         {
00185             file.write("",0);
00186             file.close();
00187         }
00188     } else {
00189         qDebug() << errorMsg << " line: " << errorLine << " column: " << errorColumn;
00190     }
00191 
00192     file.close();
00193 }
00194 
00195 
00196 LegacyLibraryImporter::~LegacyLibraryImporter()
00197 {
00198 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines