diff --git a/LameXP.vcproj b/LameXP.vcproj
index 9baffc63..5dd430cf 100644
--- a/LameXP.vcproj
+++ b/LameXP.vcproj
@@ -470,6 +470,10 @@
RelativePath=".\src\Model_Settings.cpp"
>
+
+
@@ -1322,6 +1326,10 @@
RelativePath=".\src\Model_Settings.h"
>
+
+
diff --git a/src/PlaylistImporter.cpp b/src/PlaylistImporter.cpp
new file mode 100644
index 00000000..96b3bc7e
--- /dev/null
+++ b/src/PlaylistImporter.cpp
@@ -0,0 +1,281 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2011 LoRd_MuldeR
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#include "PlaylistImporter.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+//Un-escape XML characters
+static const struct
+{
+ char *escape;
+ char *output;
+}
+g_xmlEscapeSequence[] =
+{
+ {"&", "&"},
+ {"<", "<"},
+ {">", ">"},
+ {"'", "'"},
+ {" ", " "},
+ {""", "\""},
+ {NULL, NULL}
+};
+
+////////////////////////////////////////////////////////////
+// Public Functions
+////////////////////////////////////////////////////////////
+
+bool PlaylistImporter::importPlaylist(QStringList &fileList, const QString &playlistFile)
+{
+ QFileInfo file(playlistFile);
+ QDir baseDir(file.canonicalPath());
+
+ QDir rootDir(baseDir);
+ while(rootDir.cdUp());
+
+ //Sanity check
+ if(file.size() < 3 || file.size() > 512000)
+ {
+ return false;
+ }
+
+ //Detect playlist type
+ playlist_t playlistType = isPlaylist(file.canonicalFilePath());
+
+ //Exit if not a playlist
+ if(playlistType == notPlaylist)
+ {
+ return false;
+ }
+
+ QFile data(playlistFile);
+
+ //Open file for reading
+ if(!data.open(QIODevice::ReadOnly))
+ {
+ return false;
+ }
+
+ //Parse playlist depending on type
+ switch(playlistType)
+ {
+ case m3uPlaylist:
+ return parsePlaylist_m3u(data, fileList, baseDir, rootDir);
+ break;
+ case plsPlaylist:
+ return parsePlaylist_pls(data, fileList, baseDir, rootDir);
+ break;
+ case wplPlaylist:
+ return parsePlaylist_wpl(data, fileList, baseDir, rootDir);
+ break;
+ default:
+ return false;
+ break;
+ }
+}
+
+////////////////////////////////////////////////////////////
+// Private Functions
+////////////////////////////////////////////////////////////
+
+PlaylistImporter::playlist_t PlaylistImporter::isPlaylist(const QString &fileName)
+{
+ QFileInfo file (fileName);
+
+ if(file.suffix().compare("m3u", Qt::CaseInsensitive) == 0 || file.suffix().compare("m3u8", Qt::CaseInsensitive) == 0)
+ {
+ return m3uPlaylist;
+ }
+ else if(file.suffix().compare("pls", Qt::CaseInsensitive) == 0)
+ {
+ return plsPlaylist;
+ }
+ else if(file.suffix().compare("asx", Qt::CaseInsensitive) == 0 || file.suffix().compare("wpl", Qt::CaseInsensitive) == 0)
+ {
+ return wplPlaylist;
+ }
+ else
+ {
+ return notPlaylist;
+ }
+}
+
+bool PlaylistImporter::parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
+{
+ QByteArray line = data.readLine();
+
+ while(line.size() > 0)
+ {
+ QFileInfo filename1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
+ QFileInfo filename2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
+
+ filename1.setCaching(false);
+ filename2.setCaching(false);
+
+ if(!(filename1.filePath().startsWith("#") || filename2.filePath().startsWith("#")))
+ {
+ fixFilePath(filename1, baseDir, rootDir);
+ fixFilePath(filename2, baseDir, rootDir);
+
+ if(filename1.exists())
+ {
+ if(isPlaylist(filename1.canonicalFilePath()) == notPlaylist)
+ {
+ fileList << filename1.canonicalFilePath();
+ }
+ }
+ else if(filename2.exists())
+ {
+ if(isPlaylist(filename2.canonicalFilePath()) == notPlaylist)
+ {
+ fileList << filename2.canonicalFilePath();
+ }
+ }
+ }
+
+ line = data.readLine();
+ }
+
+ return true;
+}
+
+bool PlaylistImporter::parsePlaylist_pls(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
+{
+ QRegExp plsEntry("File(\\d+)=(.+)", Qt::CaseInsensitive);
+ QByteArray line = data.readLine();
+
+ while(line.size() > 0)
+ {
+ bool flag = false;
+
+ QString temp1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
+ QString temp2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
+
+ if(!flag && plsEntry.indexIn(temp1) >= 0)
+ {
+ QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
+ filename.setCaching(false);
+ fixFilePath(filename, baseDir, rootDir);
+
+ if(filename.exists())
+ {
+ if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
+ {
+ fileList << filename.canonicalFilePath();
+ }
+ flag = true;
+ }
+ }
+
+ if(!flag && plsEntry.indexIn(temp2) >= 0)
+ {
+ QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
+ filename.setCaching(false);
+ fixFilePath(filename, baseDir, rootDir);
+
+ if(filename.exists())
+ {
+ if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
+ {
+ fileList << filename.canonicalFilePath();
+ }
+ flag = true;
+ }
+ }
+
+ line = data.readLine();
+ }
+
+ return true;
+}
+
+bool PlaylistImporter::parsePlaylist_wpl(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
+{
+ QRegExp skipData("", Qt::CaseInsensitive);
+ QRegExp wplEntry("<(media|ref)[^<>]*(src|href)=\"([^\"]+)\"[^<>]*>", Qt::CaseInsensitive);
+
+ skipData.setMinimal(true);
+
+ QByteArray buffer = data.readAll();
+ QString line = QString::fromUtf8(buffer.constData(), buffer.size()).simplified();
+ buffer.clear();
+
+ int index = 0;
+
+ while((index = skipData.indexIn(line)) >= 0)
+ {
+ line.remove(index, skipData.matchedLength());
+ }
+
+ int offset = 0;
+
+ while((offset = wplEntry.indexIn(line, offset) + 1) > 0)
+ {
+ QFileInfo filename(QDir::fromNativeSeparators(unescapeXml(wplEntry.cap(3)).trimmed()));
+ filename.setCaching(false);
+ fixFilePath(filename, baseDir, rootDir);
+
+ if(filename.exists())
+ {
+ if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
+ {
+ fileList << filename.canonicalFilePath();
+ }
+ }
+ }
+
+ return true;
+}
+
+void PlaylistImporter::fixFilePath(QFileInfo &filename, const QDir &baseDir, const QDir &rootDir)
+{
+ if(filename.filePath().startsWith("/"))
+ {
+ while(filename.filePath().startsWith("/"))
+ {
+ filename.setFile(filename.filePath().mid(1));
+ }
+ filename.setFile(rootDir.filePath(filename.filePath()));
+ }
+
+ if(!filename.isAbsolute())
+ {
+ filename.setFile(baseDir.filePath(filename.filePath()));
+ }
+}
+
+QString &PlaylistImporter::unescapeXml(QString &str)
+{
+ for(int i = 0; (g_xmlEscapeSequence[i].escape && g_xmlEscapeSequence[i].output); i++)
+ {
+ str.replace(g_xmlEscapeSequence[i].escape, g_xmlEscapeSequence[i].output);
+ }
+
+ return str;
+}
diff --git a/src/PlaylistImporter.h b/src/PlaylistImporter.h
new file mode 100644
index 00000000..60fbb5a8
--- /dev/null
+++ b/src/PlaylistImporter.h
@@ -0,0 +1,54 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2011 LoRd_MuldeR
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+class QFile;
+class QDir;
+class QFileInfo;
+class QStringList;
+class QString;
+
+class PlaylistImporter
+{
+public:
+ enum playlist_t
+ {
+ notPlaylist,
+ m3uPlaylist,
+ plsPlaylist,
+ wplPlaylist
+ };
+
+ static bool importPlaylist(QStringList &fileList, const QString &playlistFile);
+
+private:
+ PlaylistImporter(void) {}
+ ~PlaylistImporter(void) {}
+
+ static bool parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
+ static bool parsePlaylist_pls(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
+ static bool parsePlaylist_wpl(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
+
+ static playlist_t isPlaylist(const QString &fileName);
+ static void fixFilePath(QFileInfo &filename, const QDir &baseDir, const QDir &rootDir);
+ static QString &PlaylistImporter::unescapeXml(QString &str);
+};
diff --git a/src/Thread_FileAnalyzer.cpp b/src/Thread_FileAnalyzer.cpp
index a3c27567..5b71db3f 100644
--- a/src/Thread_FileAnalyzer.cpp
+++ b/src/Thread_FileAnalyzer.cpp
@@ -24,6 +24,7 @@
#include "Global.h"
#include "LockedFile.h"
#include "Model_AudioFile.h"
+#include "PlaylistImporter.h"
#include
#include
@@ -31,13 +32,9 @@
#include
#include
#include
-#include
#include
-//Un-escape XML characters
-#define XML_DECODE replace("&", "&").replace("'", "'").replace(" ", " ").replace(""", "\"").replace("<", "<").replace(">", ">")
-
////////////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////////////
@@ -82,7 +79,7 @@ void FileAnalyzer::run()
AudioFileModel file = analyzeFile(currentFile);
if(file.fileName().isEmpty() || file.formatContainerType().isEmpty() || file.formatAudioType().isEmpty())
{
- if(!importPlaylist(m_inputFiles, currentFile))
+ if(!PlaylistImporter::importPlaylist(m_inputFiles, currentFile))
{
m_filesRejected++;
qDebug("Skipped: %s", file.filePath().toUtf8().constData());
@@ -362,230 +359,6 @@ unsigned int FileAnalyzer::parseDuration(const QString &str)
return 0;
}
-
-bool FileAnalyzer::importPlaylist(QStringList &fileList, const QString &playlistFile)
-{
- QFileInfo file(playlistFile);
- QDir baseDir(file.canonicalPath());
-
- QDir rootDir(baseDir);
- while(rootDir.cdUp());
-
- //Sanity check
- if(file.size() < 3 || file.size() > 512000)
- {
- return false;
- }
-
- //Detect playlist type
- playlist_t playlistType = isPlaylist(file.canonicalFilePath());
-
- //Exit if not a playlist
- if(playlistType == noPlaylist)
- {
- return false;
- }
-
- QFile data(playlistFile);
-
- //Open file for reading
- if(!data.open(QIODevice::ReadOnly))
- {
- return false;
- }
-
- //Parse playlist depending on type
- switch(playlistType)
- {
- case m3uPlaylist:
- return parsePlaylist_m3u(data, fileList, baseDir, rootDir);
- break;
- case plsPlaylist:
- return parsePlaylist_pls(data, fileList, baseDir, rootDir);
- break;
- case wplPlaylist:
- return parsePlaylist_wpl(data, fileList, baseDir, rootDir);
- break;
- default:
- return false;
- break;
- }
-}
-
-bool FileAnalyzer::parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
-{
- QByteArray line = data.readLine();
-
- while(line.size() > 0)
- {
- QFileInfo filename1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
- QFileInfo filename2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
-
- filename1.setCaching(false);
- filename2.setCaching(false);
-
- if(!(filename1.filePath().startsWith("#") || filename2.filePath().startsWith("#")))
- {
- fixFilePath(filename1, baseDir, rootDir);
- fixFilePath(filename2, baseDir, rootDir);
-
- if(filename1.exists())
- {
- if(isPlaylist(filename1.canonicalFilePath()) == noPlaylist)
- {
- fileList << filename1.canonicalFilePath();
- }
- }
- else if(filename2.exists())
- {
- if(isPlaylist(filename2.canonicalFilePath()) == noPlaylist)
- {
- fileList << filename2.canonicalFilePath();
- }
- }
- }
-
- line = data.readLine();
- }
-
- return true;
-}
-
-bool FileAnalyzer::parsePlaylist_pls(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
-{
- QRegExp plsEntry("File(\\d+)=(.+)", Qt::CaseInsensitive);
- QByteArray line = data.readLine();
-
- while(line.size() > 0)
- {
- bool flag = false;
-
- QString temp1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
- QString temp2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
-
- if(!flag && plsEntry.indexIn(temp1) >= 0)
- {
- QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
- filename.setCaching(false);
- fixFilePath(filename, baseDir, rootDir);
-
- if(filename.exists())
- {
- if(isPlaylist(filename.canonicalFilePath()) == noPlaylist)
- {
- fileList << filename.canonicalFilePath();
- flag = true;
- }
- }
- }
-
- if(!flag && plsEntry.indexIn(temp2) >= 0)
- {
- QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
- filename.setCaching(false);
- fixFilePath(filename, baseDir, rootDir);
-
- if(filename.exists())
- {
- if(isPlaylist(filename.canonicalFilePath()) == noPlaylist)
- {
- fileList << filename.canonicalFilePath();
- flag = true;
- }
- }
- }
-
- line = data.readLine();
- }
-
- return true;
-}
-
-bool FileAnalyzer::parsePlaylist_wpl(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
-{
- QRegExp skipData("", Qt::CaseInsensitive);
- QRegExp wplEntry("<(media|ref)[^<>]*(src|href)=\"([^\"]+)\"[^<>]*>", Qt::CaseInsensitive);
-
- skipData.setMinimal(true);
-
- QByteArray buffer = data.readAll();
- QString line = QString::fromUtf8(buffer.constData(), buffer.size()).simplified();
- buffer.clear();
-
- int index = 0;
-
- while((index = skipData.indexIn(line)) >= 0)
- {
- line.remove(index, skipData.matchedLength());
- }
-
- int offset = 0;
-
- while((offset = wplEntry.indexIn(line, offset) + 1) > 0)
- {
- QFileInfo filename(QDir::fromNativeSeparators(wplEntry.cap(3).XML_DECODE.trimmed()));
- filename.setCaching(false);
- fixFilePath(filename, baseDir, rootDir);
-
- if(filename.exists())
- {
- if(isPlaylist(filename.canonicalFilePath()) == noPlaylist)
- {
- fileList << filename.canonicalFilePath();
- }
- }
- }
-
- return true;
-}
-
-FileAnalyzer::playlist_t FileAnalyzer::isPlaylist(const QString &fileName)
-{
- QFileInfo file (fileName);
-
- if(file.suffix().compare("m3u", Qt::CaseInsensitive) == 0)
- {
- return m3uPlaylist;
- }
- else if(file.suffix().compare("m3u8", Qt::CaseInsensitive) == 0)
- {
- return m3uPlaylist;
- }
- else if(file.suffix().compare("pls", Qt::CaseInsensitive) == 0)
- {
- return plsPlaylist;
- }
- else if(file.suffix().compare("asx", Qt::CaseInsensitive) == 0)
- {
- return wplPlaylist;
- }
- else if(file.suffix().compare("wpl", Qt::CaseInsensitive) == 0)
- {
- return wplPlaylist;
- }
- else
- {
- return noPlaylist;
- }
-}
-
-void FileAnalyzer::fixFilePath(QFileInfo &filename, const QDir &baseDir, const QDir &rootDir)
-{
- if(filename.filePath().startsWith("/"))
- {
- while(filename.filePath().startsWith("/"))
- {
- filename.setFile(filename.filePath().mid(1));
- }
- filename.setFile(rootDir.filePath(filename.filePath()));
- }
-
- if(!filename.isAbsolute())
- {
- filename.setFile(baseDir.filePath(filename.filePath()));
- }
-}
-
////////////////////////////////////////////////////////////
// Public Functions
////////////////////////////////////////////////////////////
diff --git a/src/Thread_FileAnalyzer.h b/src/Thread_FileAnalyzer.h
index d3d2bf9c..08f57653 100644
--- a/src/Thread_FileAnalyzer.h
+++ b/src/Thread_FileAnalyzer.h
@@ -58,27 +58,12 @@ private:
sectionAudio,
sectionOther
};
-
- enum playlist_t
- {
- noPlaylist,
- m3uPlaylist,
- plsPlaylist,
- wplPlaylist
- };
const AudioFileModel analyzeFile(const QString &filePath);
void updateInfo(AudioFileModel &audioFile, const QString &key, const QString &value);
void updateSection(const QString §ion);
unsigned int parseYear(const QString &str);
unsigned int parseDuration(const QString &str);
- bool importPlaylist(QStringList &fileList, const QString &playlistFile);
- bool parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
- bool parsePlaylist_pls(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
- bool parsePlaylist_wpl(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir);
- playlist_t isPlaylist(const QString &fileName);
- void fixFilePath(QFileInfo &filename, const QDir &baseDir, const QDir &rootDir);
-
QStringList m_inputFiles;
const QString m_mediaInfoBin_x86;