void M3UParser::load() { QTime timeElapsed; timeElapsed.start(); _stop = false; QList<MediaInfo> files; qDebug() << __FUNCTION__ << "Playlist:" << _filename; //See http://regexlib.com/DisplayPatterns.aspx //#EXTM3U static QRegExp rx_extm3u("^#EXTM3U$|^#M3U$"); //#EXTINF:123,Sample title static QRegExp rx_extinf("^#EXTINF:([-+]?\\d+),(.*)$"); //#EXTINF:Sample title static QRegExp rx_extinf_title("^#EXTINF:(.*)$"); //#Just a comment static QRegExp rx_comment("^#.*$"); QFile file(_filename); if (file.open(QIODevice::ReadOnly)) { QString path(QFileInfo(_filename).path()); QTextStream stream(&file); if (isUtf8()) { stream.setCodec("UTF-8"); } else { stream.setCodec(QTextCodec::codecForLocale()); } MediaInfo mediaInfo; while (!stream.atEnd() && !_stop) { //Line of text excluding '\n' QString line(stream.readLine().trimmed()); if (line.isEmpty()) { //Do nothing } else if (rx_extm3u.indexIn(line) != -1) { //#EXTM3U line, ignored } else if (rx_extinf.indexIn(line) != -1) { //#EXTINF line QString length(rx_extinf.cap(1)); if (!length.isEmpty()) { mediaInfo.setLength(length.toInt()); } QString title(rx_extinf.cap(2)); if (!title.isEmpty()) { mediaInfo.insertMetadata(MediaInfo::Title, title); } } else if (rx_extinf_title.indexIn(line) != -1) { QString title(rx_extinf_title.cap(1)); if (!title.isEmpty()) { mediaInfo.insertMetadata(MediaInfo::Title, title); } } else if (rx_comment.indexIn(line) != -1) { //# line, comment, ignored } else { bool isUrl = MediaInfo::isUrl(line); mediaInfo.setUrl(isUrl); if (isUrl) { mediaInfo.setFileName(line); } else { mediaInfo.setFileName(Util::canonicalFilePath(path, line)); } //Add file to the list of files files << mediaInfo; //Clear the MediaInfo for the next 2 lines from the m3u playlist mediaInfo.clear(); if (files.size() > FILES_FOUND_LIMIT) { //Emits the signal every FILES_FOUND_LIMIT files found emit filesFound(files); files.clear(); } } } } file.close(); if (!files.isEmpty()) { //Emits the signal for the remaining files found (< FILES_FOUND_LIMIT) emit filesFound(files); } //Emits the last signal emit finished(timeElapsed.elapsed()); }
void CUEParser::load() { QTime timeElapsed; timeElapsed.start(); _stop = false; QList<MediaInfo> files; qDebug() << __FUNCTION__ << "Playlist:" << _filename; //See http://regexlib.com/DisplayPatterns.aspx //REM GENRE "Alternative rock" //REM GENRE Pop static QRegExp rx_genre("^REM GENRE (.*)$"); //REM DATE 1994 static QRegExp rx_date("^REM DATE (\\d+)$"); //PERFORMER "Weezer" static QRegExp rx_root_performer("^PERFORMER \"(.*)\"$"); //TITLE "Weezer (The Blue Album)" static QRegExp rx_root_title("^TITLE \"(.*)\"$"); //FILE "01. My Name Is Jonas - [Weezer] .wav" WAVE static QRegExp rx_file("^FILE \"(.*)\""); // TRACK 01 AUDIO static QRegExp rx_track("^ TRACK (\\d+)"); // TITLE "No One Else" static QRegExp rx_title("^ TITLE \"(.*)\"$"); // PERFORMER "Weezer" static QRegExp rx_performer("^ PERFORMER \"(.*)\"$"); // INDEX 01 00:00:00 static QRegExp rx_index("^ INDEX 01 (.*)$"); QFile file(_filename); if (file.open(QIODevice::ReadOnly)) { QString path(QFileInfo(_filename).path()); QTextStream stream(&file); MediaInfo mediaInfo; //Root elements QString genre; QString date; QString albumArtist; QString album; /// QString filename; while (!stream.atEnd() && !_stop) { //Line of text, don't use trimmed() //since CUE sheet files contain indentation spaces QString line(stream.readLine()); if (line.isEmpty()) { //Do nothing } else if (rx_genre.indexIn(line) != -1) { genre = rx_genre.cap(1); } else if (rx_date.indexIn(line) != -1) { date = rx_date.cap(1); } else if (rx_root_performer.indexIn(line) != -1) { albumArtist = rx_root_performer.cap(1); } else if (rx_root_title.indexIn(line) != -1) { album = rx_root_title.cap(1); } else if (rx_file.indexIn(line) != -1) { filename = rx_file.cap(1); } else if (rx_track.indexIn(line) != -1) { QString track(rx_track.cap(1)); mediaInfo.insertMetadata(MediaInfo::TrackNumber, track); } else if (rx_title.indexIn(line) != -1) { QString title(rx_title.cap(1)); mediaInfo.insertMetadata(MediaInfo::Title, title); } else if (rx_performer.indexIn(line) != -1) { QString performer(rx_performer.cap(1)); mediaInfo.insertMetadata(MediaInfo::Artist, performer); } else if (rx_index.indexIn(line) != -1) { QString index(rx_index.cap(1)); mediaInfo.setCueStartIndex(index); if (!files.isEmpty()) { //Now we know the CUE end index from the previous media files.last().setCueEndIndex(index); } mediaInfo.insertMetadata(MediaInfo::Genre, genre); mediaInfo.insertMetadata(MediaInfo::Year, date); mediaInfo.insertMetadata(MediaInfo::AlbumArtist, albumArtist); mediaInfo.insertMetadata(MediaInfo::Album, album); bool isUrl = MediaInfo::isUrl(filename); mediaInfo.setUrl(isUrl); if (isUrl) { mediaInfo.setFileName(filename); } else { mediaInfo.setFileName(Util::canonicalFilePath(path, filename)); } if (!mediaInfo.fileName().isEmpty()) { //Add file to the list of files files << mediaInfo; //Clear the MediaInfo for the next lines mediaInfo.clear(); if (files.size() > FILES_FOUND_LIMIT) { //Emits the signal every FILES_FOUND_LIMIT files found emit filesFound(files); files.clear(); } } } else { //Syntax error } } } file.close(); if (!files.isEmpty()) { //Emits the signal for the remaining files found (< FILES_FOUND_LIMIT) emit filesFound(files); } //Emits the last signal emit finished(timeElapsed.elapsed()); }
void XSPFParser::readTrack(QXmlStreamReader & xml, MediaInfo & mediaInfo) const { while (!xml.atEnd() && !_stop) { xml.readNext(); QString element(xml.name().toString()); if (xml.isStartElement()) { //Filename if (element == XSPF_LOCATION) { QUrl url = QUrl::fromEncoded(xml.readElementText().toUtf8()); QString location(url.toString()); bool isUrl = MediaInfo::isUrl(location); mediaInfo.setUrl(isUrl); if (isUrl) { mediaInfo.setFileName(location); } else { QString path(QFileInfo(_filename).path()); mediaInfo.setFileName(Util::canonicalFilePath(path, location)); } } //Unique ID else if (element == XSPF_IDENTIFIER) { QString identifier(xml.readElementText()); //FIXME not implemented yet } //Artist else if (element == XSPF_CREATOR) { QString creator(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::Artist, creator); } //Album else if (element == XSPF_ALBUM) { QString album(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::Album, album); } //Track number else if (element == XSPF_TRACKNUM) { QString trackNum(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::TrackNumber, trackNum); } //Title else if (element == XSPF_TITLE) { QString title(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::Title, title); } //Comment else if (element == XSPF_ANNOTATION) { QString annotation(xml.readElementText()); if (mediaInfo.metadataValue(MediaInfo::Title).isEmpty()) { //Some people didn't understand how XSPF works //and confused annotation with title mediaInfo.insertMetadata(MediaInfo::Title, annotation); } mediaInfo.insertMetadata(MediaInfo::Comment, annotation); } //Length else if (element == XSPF_DURATION) { int duration = xml.readElementText().toInt(); //XSPF gives us the duration in milliseconds //Let's convert it to seconds mediaInfo.setLength(duration / 1000); } //Album art URL else if (element == XSPF_IMAGE) { QString image(xml.readElementText()); //FIXME not implemented yet //mediaInfo.insertMetadata(MediaInfo::AlbumArt, image); } //URL of the original web page else if (element == XSPF_INFO) { QString info(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::URL, info); } //Meta else if (element == XSPF_META) { //These tags are specific to foobar2000 XSPF plugin QXmlStreamAttributes attributes = xml.attributes(); //Date if (attributes.hasAttribute(XSPF_FOOBAR2000_DATE)) { QString date(attributes.value(XSPF_FOOBAR2000_DATE).toString()); mediaInfo.insertMetadata(MediaInfo::Year, date); } //Genre else if (attributes.hasAttribute(XSPF_FOOBAR2000_GENRE)) { QString genre(attributes.value(XSPF_FOOBAR2000_GENRE).toString()); mediaInfo.insertMetadata(MediaInfo::Genre, genre); } } else if (element == XSPF_EXTENSION) { QString xspfNamespace(xml.attributes().value(XSPF_APPLICATION).toString()); if (xspfNamespace == XSPF_QUARKPLAYER_NAMESPACE) { while (!xml.atEnd() && !_stop) { xml.readNext(); QString extensionElement(xml.name().toString()); if (xml.isStartElement()) { if (extensionElement == XSPF_QUARKPLAYER_CUE_START_INDEX) { QString cueStartIndex(xml.readElementText()); mediaInfo.setCueStartIndex(cueStartIndex); } else if (extensionElement == XSPF_QUARKPLAYER_CUE_END_INDEX) { QString cueEndIndex(xml.readElementText()); mediaInfo.setCueEndIndex(cueEndIndex); } else if (extensionElement == XSPF_QUARKPLAYER_YEAR) { QString year(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::Year, year); } else if (extensionElement == XSPF_QUARKPLAYER_GENRE) { QString genre(xml.readElementText()); mediaInfo.insertMetadata(MediaInfo::Genre, genre); } } if (xml.isEndElement()) { if (extensionElement == XSPF_EXTENSION) { break; } } } } } } if (xml.isEndElement()) { if (element == XSPF_TRACK) { return; } } } }