Пример #1
0
bool XmlStreamParser::moveToNext(QString qName, void (*callback)())
{
    if (atEnd()) {
        return false;
    }

    bool found = false;
    readNextStartElement();
    nextElementDo(callback);

    while ( !(atEnd() || found)) {
        if (_reader->isStartElement()) {
            found = isAtBeginningOf(qName);
            if ( !found) {
                skipCurrentElement();
                readNext();
            }
        } else {
            if ( !readNextStartElement()) {
                break;
            }
            nextElementDo(callback);
        }
    }
    return found;
}
Пример #2
0
bool XmlStreamParser::findNextOf(std::initializer_list<QString> elementList, void (*callback)())
{
    if (atEnd()) {
        return false;
    }

    bool found = false;
    QString startElement = name();
    bool onStartElement = _reader->isStartElement();
    bool hasInnerStartElement = readNextStartElement();
    if ( !onStartElement && !hasInnerStartElement) {
        return false;
    }
    nextElementDo(callback);

    while ( !(atEnd() || found)) {
        if (_reader->isStartElement()) {
            for (QString qName : elementList) {
                found = isAtBeginningOf(qName);
                if (found) {
                    break;
                }
            }
            if ( !found) {
                bool hasNextNestedElement = readNextStartElement();
                bool atEndOfStartElement = name() == startElement;
                if ( !hasNextNestedElement) {
                    if (atEndOfStartElement) {
                        break; // not found;
                    }
                    nextElementDo(callback);
                }
            }
        } else {
            bool hasNextNestedElement = readNextStartElement();
            bool atEndOfStartElement = name() == startElement;
            if ( !hasNextNestedElement) {
                if (atEndOfStartElement) {
                    break; // not found;
                }
                nextElementDo(callback);
            }
        }
    }
    return found;
}
Пример #3
0
void XbelReader::readXBEL(BookmarkNode *parent)
{
    Q_ASSERT(isStartElement() && name() == QLatin1String("xbel"));

    while (readNextStartElement()) {
        if (name() == QLatin1String("folder"))
            readFolder(parent);
        else if (name() == QLatin1String("bookmark"))
            readBookmarkNode(parent);
        else if (name() == QLatin1String("separator"))
            readSeparator(parent);
        else
            skipCurrentElement();
    }
}
Пример #4
0
BookmarkNode *XbelReader::read(QIODevice *device)
{
    BookmarkNode *root = new BookmarkNode(BookmarkNode::Root);
    setDevice(device);
    if (readNextStartElement()) {
        QString version = attributes().value(QLatin1String("version")).toString();
        if (name() == QLatin1String("xbel")
            && (version.isEmpty() || version == QLatin1String("1.0"))) {
            readXBEL(root);
        } else {
            raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
        }
    }
    return root;
}
Пример #5
0
bool DummyReader::isParsable()
{
    bool isparsable = false;
    setDevice( &m_dev );
    if ( !atEnd() ) {
        readNextStartElement();
        if ( isStartElement() ) {
            if ( name() == mTag() ) {
                isparsable=true;
            }
        }
    }
    m_dev.seek( 0 );
    return isparsable;
}
Пример #6
0
void Container::load(QXmlStreamReader &stream)
{
	Option *option;
	List::Container uninitialized(m_items);

	while (readNextStartElement(stream))
		if (option = uninitialized.value(stream.name()))
		{
			option->load(stream);
			uninitialized.remove(&option->id());
		}

	for (List::Container::const_iterator i = uninitialized.constBegin(), end = uninitialized.constEnd(); i != end; ++i)
		(*i)->loadDefault();
}
Пример #7
0
void XbelReader::readBookmarkNode(BookmarkNode *parent)
{
    Q_ASSERT(isStartElement() && name() == QLatin1String("bookmark"));
    BookmarkNode *bookmark = new BookmarkNode(BookmarkNode::Bookmark, parent);
    bookmark->url = attributes().value(QLatin1String("href")).toString();
    while (readNextStartElement()) {
        if (name() == QLatin1String("title"))
            readTitle(bookmark);
        else if (name() == QLatin1String("desc"))
            readDescription(bookmark);
        else
            skipCurrentElement();
    }
    if (bookmark->title.isEmpty())
        bookmark->title = QObject::tr("Unknown title");
}
Пример #8
0
void Container::load()
{
	QFile file(m_storage);

	if (file.open(QFile::ReadOnly))
	{
		QXmlStreamReader stream(&file);

		if (readNextStartElement(stream) && stream.name() == QString::fromLatin1("QFM"))
			load(stream);
		else
			loadDefault();
	}
	else
		loadDefault();
}
Пример #9
0
KEduVocDocument::ErrorCode DummyReader::read(KEduVocDocument &) {
    setDevice( &m_dev );
    if ( !atEnd() ) {
        readNextStartElement();
        if ( isStartElement() ) {
            // kDebug() << "Reading Dummy File is start "<< name() <<" text "<<text();
            if ( name() == mTag() ) {
                readNext();
                readNext();
                //kDebug() << "Reading Dummy File"<<name() << "text" << text();
                if ( isStartElement() ) {
                    m_errorMessage = readElementText();
                    // kDebug() << "Reading Dummy File is " <<name() <<" with "<<m_errorMessage;
                    if ( makeErrorTag( KEduVocDocument::NoError ) == name() )
                        return KEduVocDocument::NoError;
                    if ( makeErrorTag( KEduVocDocument::Unknown ) == name() )
                        return KEduVocDocument::Unknown;
                    if ( makeErrorTag( KEduVocDocument::InvalidXml ) == name() )
                        return KEduVocDocument::InvalidXml;
                    if ( makeErrorTag( KEduVocDocument::FileTypeUnknown ) == name() )
                        return KEduVocDocument::FileTypeUnknown;
                    if ( makeErrorTag( KEduVocDocument::FileCannotWrite ) == name() )
                        return KEduVocDocument::FileCannotWrite;
                    if ( makeErrorTag( KEduVocDocument::FileWriterFailed ) == name() )
                        return KEduVocDocument::FileWriterFailed;
                    if ( makeErrorTag( KEduVocDocument::FileCannotRead ) == name() )
                        return KEduVocDocument::FileCannotRead;
                    if ( makeErrorTag( KEduVocDocument::FileReaderFailed ) == name() )
                        return KEduVocDocument::FileReaderFailed;
                    if ( makeErrorTag( KEduVocDocument::FileDoesNotExist ) == name() )
                        return KEduVocDocument::FileDoesNotExist;
                    if ( makeErrorTag( KEduVocDocument::FileLocked ) == name() )
                        return KEduVocDocument::FileLocked;
                    if ( makeErrorTag( KEduVocDocument::FileCannotLock ) == name() )
                        return KEduVocDocument::FileCannotLock;
                }
            }
        }
    }
    return KEduVocDocument::Unknown;
}
Пример #10
0
void XbelReader::readFolder(BookmarkNode *parent)
{
    Q_ASSERT(isStartElement() && name() == QLatin1String("folder"));

    BookmarkNode *folder = new BookmarkNode(BookmarkNode::Folder, parent);
    folder->expanded = (attributes().value(QLatin1String("folded")) == QLatin1String("no"));

    while (readNextStartElement()) {
        if (name() == QLatin1String("title"))
            readTitle(folder);
        else if (name() == QLatin1String("desc"))
            readDescription(folder);
        else if (name() == QLatin1String("folder"))
            readFolder(folder);
        else if (name() == QLatin1String("bookmark"))
            readBookmarkNode(folder);
        else if (name() == QLatin1String("separator"))
            readSeparator(folder);
        else
            skipCurrentElement();
    }
}
Пример #11
0
void YTFeedReader::readEntry() {
    Video* video = new Video();

    while (!atEnd()) {
        readNext();

        /*
        qDebug() << name();
        QXmlStreamAttribute attribute;
        foreach (attribute, attributes())
            qDebug() << attribute.name() << ":" << attribute.value();
        */

        if (isEndElement() && name() == QLatin1String("entry")) break;
        if (isStartElement()) {

            if (name() == QLatin1String("link")
                    && attributes().value("rel").toString() == QLatin1String("alternate")
                    && attributes().value("type").toString() == QLatin1String("text/html")
                    ) {
                QString webpage = attributes().value("href").toString();
                webpage.remove("&feature=youtube_gdata");
                video->setWebpage(webpage);
            } else if (name() == QLatin1String("author")) {
                while(readNextStartElement())
                    if (name() == QLatin1String("name")) {
                        QString author = readElementText();
                        video->setChannelTitle(author);
                    } else if (name() == QLatin1String("userId")) {
                        QString userId = readElementText();
                        video->setChannelId(userId);
                    } else skipCurrentElement();
            } else if (name() == QLatin1String("published")) {
                video->setPublished(QDateTime::fromString(readElementText(), Qt::ISODate));
            } else if (namespaceUri() == QLatin1String("http://gdata.youtube.com/schemas/2007")
                       && name() == QLatin1String("statistics")) {
                QString viewCount = attributes().value("viewCount").toString();
                video->setViewCount(viewCount.toInt());
            }
            else if (namespaceUri() == QLatin1String("http://search.yahoo.com/mrss/")
                     && name() == QLatin1String("group")) {

                // read media group
                while (!atEnd()) {
                    readNext();
                    if (isEndElement() && name() == QLatin1String("group")) break;
                    if (isStartElement()) {
                        if (name() == QLatin1String("thumbnail")) {
                            // qDebug() << "Thumb: " << attributes().value("url").toString();
                            QStringRef name = attributes().value("yt:name");
                            if (name == QLatin1String("mqdefault"))
                                video->setThumbnailUrl(
                                            attributes().value("url").toString());
                            else if (name == QLatin1String("hqdefault"))
                                video->setMediumThumbnailUrl(
                                            attributes().value("url").toString());
                        }
                        else if (name() == QLatin1String("title")) {
                            QString title = readElementText();
                            // qDebug() << "Title: " << title;
                            video->setTitle(title);
                        }
                        else if (name() == QLatin1String("description")) {
                            QString desc = readElementText();
                            // qDebug() << "Description: " << desc;
                            video->setDescription(desc);
                        }
                        else if (name() == QLatin1String("duration")) {
                            QString duration = attributes().value("seconds").toString();
                            // qDebug() << "Duration: " << duration;
                            video->setDuration(duration.toInt());
                        }
                        else if (name() == QLatin1String("license")) {
                            QString license = readElementText();
                            // qDebug() << "License: " << license;
                            if (license == QLatin1String("cc"))
                                video->setLicense(Video::LicenseCC);
                        }
                    }
                }
            }
        }
    }

    videos.append(video);

}
Пример #12
0
void ITunesFeature::parsePlaylist(QXmlStreamReader &xml, QSqlQuery &query_insert_to_playlists,
                                  QSqlQuery &query_insert_to_playlist_tracks, TreeItem* root) {
    //qDebug() << "Parse Playlist";

    QString playlistname;
    int playlist_id = -1;
    int playlist_position = -1;
    int track_reference = -1;
    //indicates that we haven't found the <
    bool isSystemPlaylist = false;

    QString key;


    //We process and iterate the <dict> tags holding playlist summary information here
    while (!xml.atEnd() && !m_cancelImport) {
        xml.readNext();

        if (xml.isStartElement()) {

            if (xml.name() == "key") {
                QString key = xml.readElementText();
                // The rules are processed in sequence
                // That is, XML is ordered.
                // For iTunes Playlist names are always followed by the ID.
                // Afterwars the playlist entries occur
                if (key == "Name") {
                    readNextStartElement(xml);
                    playlistname = xml.readElementText();
                    continue;
                }
                //When parsing the ID, the playlistname has already been found
                if (key == "Playlist ID") {
                    readNextStartElement(xml);
                    playlist_id = xml.readElementText().toInt();
                    playlist_position = 1;
                    continue;
                }
                //Hide playlists that are system playlists
                if (key == "Master" || key == "Movies" || key == "TV Shows" ||
                    key == "Music" || key == "Books" || key == "Purchased") {
                    isSystemPlaylist = true;
                    continue;
                }

                if (key == "Playlist Items") {
                    //if the playlist is prebuild don't hit the database
                    if (isSystemPlaylist) continue;
                    query_insert_to_playlists.bindValue(":id", playlist_id);
                    query_insert_to_playlists.bindValue(":name", playlistname);

                    bool success = query_insert_to_playlists.exec();
                    if (!success) {
                        qDebug() << "SQL Error in ITunesTableModel.cpp: line" << __LINE__
                                 << " " << query_insert_to_playlists.lastError();
                        return;
                    }
                    //append the playlist to the child model
                    TreeItem *item = new TreeItem(playlistname, playlistname, this, root);
                    root->appendChild(item);

                }
                // When processing playlist entries, playlist name and id have
                // already been processed and persisted
                if (key == "Track ID") {
                    track_reference = -1;

                    readNextStartElement(xml);
                    track_reference = xml.readElementText().toInt();

                    query_insert_to_playlist_tracks.bindValue(":playlist_id", playlist_id);
                    query_insert_to_playlist_tracks.bindValue(":track_id", track_reference);
                    query_insert_to_playlist_tracks.bindValue(":position", playlist_position++);

                    //Insert tracks if we are not in a pre-build playlist
                    if (!isSystemPlaylist && !query_insert_to_playlist_tracks.exec()) {
                        qDebug() << "SQL Error in ITunesFeature.cpp: line" << __LINE__ << " "
                                 << query_insert_to_playlist_tracks.lastError();
                        qDebug() << "trackid" << track_reference;
                        qDebug() << "playlistname; " << playlistname;
                        qDebug() << "-----------------";
                    }
                }
            }
        }
        if (xml.isEndElement()) {
            if (xml.name() == "array") {
                //qDebug() << "exit playlist";
                break;
            }
        }
    }
}
Пример #13
0
void ITunesFeature::parseTrack(QXmlStreamReader &xml, QSqlQuery &query) {
    //qDebug() << "----------------TRACK-----------------";
    int id = -1;
    QString title;
    QString artist;
    QString album;
    QString year;
    QString genre;
    QString location;

    int bpm = 0;
    int bitrate = 0;

    //duration of a track
    int playtime = 0;
    int rating = 0;
    QString comment;
    QString tracknumber;

    while (!xml.atEnd()) {
        xml.readNext();

        if (xml.isStartElement()) {
            if (xml.name() == "key") {
                QString key = xml.readElementText();
                QString content =  "";

                if (readNextStartElement(xml)) {
                    content = xml.readElementText();
                }

                //qDebug() << "Key: " << key << " Content: " << content;

                if (key == "Track ID") {
                    id = content.toInt();
                    continue;
                }
                if (key == "Name") {
                    title = content;
                    continue;
                }
                if (key == "Artist") {
                    artist = content;
                    continue;
                }
                if (key == "Album") {
                    album = content;
                    continue;
                }
                if (key == "Genre") {
                    genre = content;
                    continue;
                }
                if (key == "BPM") {
                    bpm = content.toInt();
                    continue;
                }
                if (key == "Bit Rate") {
                    bitrate =  content.toInt();
                    continue;
                }
                if (key == "Comments") {
                    comment = content;
                    continue;
                }
                if (key == "Total Time") {
                    playtime = (content.toInt() / 1000);
                    continue;
                }
                if (key == "Year") {
                    year = content;
                    continue;
                }
                if (key == "Location") {
                    QByteArray strlocbytes = content.toUtf8();
                    location = QUrl::fromEncoded(strlocbytes).toLocalFile();
                    // Replace first part of location with the mixxx iTunes Root
                    // on systems where iTunes installed it only strips //localhost
                    // on iTunes from foreign systems the mount point is replaced
                    if (!m_dbItunesRoot.isEmpty()) {
                        location.replace(m_dbItunesRoot, m_mixxxItunesRoot);
                    }
                    continue;
                }
                if (key == "Track Number") {
                    tracknumber = content;
                    continue;
                }
                if (key == "Rating") {
                    //value is an integer and ranges from 0 to 100
                    rating = (content.toInt() / 20);
                    continue;
                }
            }
        }
        //exit loop on closing </dict>
        if (xml.isEndElement() && xml.name() == "dict") {
            break;
        }
    }
    // If we reach the end of <dict>
    // Save parsed track to database
    query.bindValue(":id", id);
    query.bindValue(":artist", artist);
    query.bindValue(":title", title);
    query.bindValue(":album", album);
    query.bindValue(":genre", genre);
    query.bindValue(":year", year);
    query.bindValue(":duration", playtime);
    query.bindValue(":location", location);
    query.bindValue(":rating", rating);
    query.bindValue(":comment", comment);
    query.bindValue(":tracknumber", tracknumber);
    query.bindValue(":bpm", bpm);
    query.bindValue(":bitrate", bitrate);

    bool success = query.exec();

    if (!success) {
        qDebug() << "SQL Error in itunesfeature.cpp: line" << __LINE__ << " " << query.lastError();
        return;
    }
}
Пример #14
0
// This method is executed in a separate thread
// via QtConcurrent::run
TreeItem* ITunesFeature::importLibrary() {
    //Give thread a low priority
    QThread* thisThread = QThread::currentThread();
    thisThread->setPriority(QThread::LowestPriority);

    //Delete all table entries of iTunes feature
    ScopedTransaction transaction(m_database);
    clearTable("itunes_playlist_tracks");
    clearTable("itunes_library");
    clearTable("itunes_playlists");
    transaction.commit();

    qDebug() << "ITunesFeature::importLibrary() ";

    transaction.transaction();

    // By default set m_mixxxItunesRoot and m_dbItunesRoot to strip out
    // file://localhost/ from the URL. When we load the user's iTunes XML
    // configuration we may replace this with something based on the detected
    // location of the user's iTunes path but the defaults are necessary in case
    // their iTunes XML does not include the "Music Folder" key.
    m_mixxxItunesRoot = "";
    m_dbItunesRoot = localhost_token();

    //Parse iTunes XML file using SAX (for performance)
    QFile itunes_file(m_dbfile);
    if (!itunes_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Cannot open iTunes music collection";
        return NULL;
    }
    QXmlStreamReader xml(&itunes_file);
    TreeItem* playlist_root = NULL;
    while (!xml.atEnd() && !m_cancelImport) {
        xml.readNext();
        if (xml.isStartElement()) {
            if (xml.name() == "key") {
                QString key = xml.readElementText();
                if (key == "Music Folder") {
                    if (readNextStartElement(xml)) {
                        guessMusicLibraryMountpoint(xml);
                    }
                } else if (key == "Tracks") {
                    parseTracks(xml);
                    playlist_root = parsePlaylists(xml);
                }
            }
        }
    }

    itunes_file.close();

    // Even if an error occured, commit the transaction. The file may have been
    // half-parsed.
    transaction.commit();

    if (xml.hasError()) {
        // do error handling
        qDebug() << "Cannot process iTunes music collection";
        qDebug() << "XML ERROR: " << xml.errorString();
        if (playlist_root)
            delete playlist_root;
        playlist_root = NULL;
    }
    return playlist_root;
}
Пример #15
0
// This method is executed in a separate thread
// via QtConcurrent::run
TreeItem* ITunesFeature::importLibrary() {
    bool isTracksParsed=false;
    bool isMusicFolderLocatedAfterTracks=false;
  
    //Give thread a low priority
    QThread* thisThread = QThread::currentThread();
    thisThread->setPriority(QThread::LowPriority);

    //Delete all table entries of iTunes feature
    ScopedTransaction transaction(m_database);
    clearTable("itunes_playlist_tracks");
    clearTable("itunes_library");
    clearTable("itunes_playlists");
    transaction.commit();

    qDebug() << "ITunesFeature::importLibrary() ";

    transaction.transaction();

    // By default set m_mixxxItunesRoot and m_dbItunesRoot to strip out
    // file://localhost/ from the URL. When we load the user's iTunes XML
    // configuration we may replace this with something based on the detected
    // location of the user's iTunes path but the defaults are necessary in case
    // their iTunes XML does not include the "Music Folder" key.
    m_mixxxItunesRoot = "";
    m_dbItunesRoot = localhost_token();

    //Parse iTunes XML file using SAX (for performance)
    QFile itunes_file(m_dbfile);
    if (!itunes_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        qDebug() << "Cannot open iTunes music collection";
        return NULL;
    }

    QXmlStreamReader xml(&itunes_file);
    TreeItem* playlist_root = NULL;
    while (!xml.atEnd() && !m_cancelImport) {
        xml.readNext();
        if (xml.isStartElement()) {
            if (xml.name() == "key") {
                QString key = xml.readElementText();
                if (key == "Music Folder") {
                    if (isTracksParsed) isMusicFolderLocatedAfterTracks = true;
                    if (readNextStartElement(xml)) {
                        guessMusicLibraryMountpoint(xml);
                    }
                } else if (key == "Tracks") {
                    parseTracks(xml);
                    if (playlist_root != NULL)
                        delete playlist_root;
                    playlist_root = parsePlaylists(xml);
                    isTracksParsed = true;
                }
            }
        }
    }

    itunes_file.close();
    
    if (isMusicFolderLocatedAfterTracks) {
        qDebug() << "Updating iTunes real path from " << m_dbItunesRoot << " to " << m_mixxxItunesRoot;
        // In some iTunes files "Music Folder" XML node is located at the end of file. So, we need to 
        QSqlQuery query(m_database);
        query.prepare("UPDATE itunes_library SET location = replace( location, :itunes_path, :mixxx_path )");
        query.bindValue(":itunes_path", m_dbItunesRoot.replace(localhost_token(), ""));
        query.bindValue(":mixxx_path", m_mixxxItunesRoot);
        bool success = query.exec();

        if (!success) {
            LOG_FAILED_QUERY(query);
        }
    }

    // Even if an error occurred, commit the transaction. The file may have been
    // half-parsed.
    transaction.commit();

    if (xml.hasError()) {
        // do error handling
        qDebug() << "Cannot process iTunes music collection";
        qDebug() << "XML ERROR: " << xml.errorString();
        if (playlist_root)
            delete playlist_root;
        playlist_root = NULL;
    }
    return playlist_root;
}
Пример #16
0
void ITunesFeature::parseTrack(QXmlStreamReader& xml, QSqlQuery& query) {
    //qDebug() << "----------------TRACK-----------------";
    int id = -1;
    QString title;
    QString artist;
    QString album;
    QString album_artist;
    QString year;
    QString genre;
    QString grouping;
    QString location;

    int bpm = 0;
    int bitrate = 0;

    //duration of a track
    int playtime = 0;
    int rating = 0;
    QString comment;
    QString tracknumber;
    QString tracktype;

    while (!xml.atEnd()) {
        xml.readNext();

        if (xml.isStartElement()) {
            if (xml.name() == kKey) {
                QString key = xml.readElementText();

                QString content;
                if (readNextStartElement(xml)) {
                    content = xml.readElementText();
                }

                //qDebug() << "Key: " << key << " Content: " << content;

                if (key == kTrackId) {
                    id = content.toInt();
                    continue;
                }
                if (key == kName) {
                    title = content;
                    continue;
                }
                if (key == kArtist) {
                    artist = content;
                    continue;
                }
                if (key == kAlbum) {
                    album = content;
                    continue;
                }
                if (key == kAlbumArtist) {
                    album_artist = content;
                    continue;
                }
                if (key == kGenre) {
                    genre = content;
                    continue;
                }
                if (key == kGrouping) {
                    grouping = content;
                    continue;
                }
                if (key == kBPM) {
                    bpm = content.toInt();
                    continue;
                }
                if (key == kBitRate) {
                    bitrate =  content.toInt();
                    continue;
                }
                if (key == kComments) {
                    comment = content;
                    continue;
                }
                if (key == kTotalTime) {
                    playtime = (content.toInt() / 1000);
                    continue;
                }
                if (key == kYear) {
                    year = content;
                    continue;
                }
                if (key == kLocation) {
                    QByteArray strlocbytes = content.toUtf8();
                    location = QUrl::fromEncoded(strlocbytes).toLocalFile();
                    // Replace first part of location with the mixxx iTunes Root
                    // on systems where iTunes installed it only strips //localhost
                    // on iTunes from foreign systems the mount point is replaced
                    if (!m_dbItunesRoot.isEmpty()) {
                        location.replace(m_dbItunesRoot, m_mixxxItunesRoot);
                    }
                    continue;
                }
                if (key == kTrackNumber) {
                    tracknumber = content;
                    continue;
                }
                if (key == kRating) {
                    //value is an integer and ranges from 0 to 100
                    rating = (content.toInt() / 20);
                    continue;
                }
                if (key == kTrackType) {
                    tracktype = content;
                    continue;
                }
            }
        }
        //exit loop on closing </dict>
        if (xml.isEndElement() && xml.name() == kDict) {
            break;
        }
    }

    // If file is a remote file from iTunes Match, don't save it to the database.
    // There's no way that mixxx can access it.
    if (tracktype == kRemote) {
        return;
    }

    // If we reach the end of <dict>
    // Save parsed track to database
    query.bindValue(":id", id);
    query.bindValue(":artist", artist);
    query.bindValue(":title", title);
    query.bindValue(":album", album);
    query.bindValue(":album_artist", album_artist);
    query.bindValue(":genre", genre);
    query.bindValue(":grouping", grouping);
    query.bindValue(":year", year);
    query.bindValue(":duration", playtime);
    query.bindValue(":location", location);
    query.bindValue(":rating", rating);
    query.bindValue(":comment", comment);
    query.bindValue(":tracknumber", tracknumber);
    query.bindValue(":bpm", bpm);
    query.bindValue(":bitrate", bitrate);

    bool success = query.exec();

    if (!success) {
        LOG_FAILED_QUERY(query);
        return;
    }
}