Added support for Speex input.
[LameXP.git] / src / PlaylistImporter.cpp
blob359f66382e0e5c5262d454ee8b97dcf62b5f0076
1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2011 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 // http://www.gnu.org/licenses/gpl-2.0.txt
20 ///////////////////////////////////////////////////////////////////////////////
22 #include "PlaylistImporter.h"
24 #include <QString>
25 #include <QStringList>
26 #include <QDir>
27 #include <QFileInfo>
28 #include <QProcess>
29 #include <QDate>
30 #include <QTime>
31 #include <QDebug>
33 //Un-escape XML characters
34 static const struct
36 char *escape;
37 char *output;
39 g_xmlEscapeSequence[] =
41 {"&amp;", "&"},
42 {"&lt;", "<"},
43 {"&gt;", ">"},
44 {"&apos;", "'"},
45 {"&nbsp;", " "},
46 {"&quot;", "\""},
47 {NULL, NULL}
50 const char *PlaylistImporter::supportedExtensions = "*.m3u *.m3u8 *.pls *.asx *.wpl";
53 ////////////////////////////////////////////////////////////
54 // Public Functions
55 ////////////////////////////////////////////////////////////
57 bool PlaylistImporter::importPlaylist(QStringList &fileList, const QString &playlistFile)
59 QFileInfo file(playlistFile);
60 QDir baseDir(file.canonicalPath());
62 QDir rootDir(baseDir);
63 while(rootDir.cdUp());
65 //Sanity check
66 if(file.size() < 3 || file.size() > 512000)
68 return false;
71 //Detect playlist type
72 playlist_t playlistType = isPlaylist(file.canonicalFilePath());
74 //Exit if not a playlist
75 if(playlistType == notPlaylist)
77 return false;
80 QFile data(playlistFile);
82 //Open file for reading
83 if(!data.open(QIODevice::ReadOnly))
85 return false;
88 //Parse playlist depending on type
89 switch(playlistType)
91 case m3uPlaylist:
92 return parsePlaylist_m3u(data, fileList, baseDir, rootDir);
93 break;
94 case plsPlaylist:
95 return parsePlaylist_pls(data, fileList, baseDir, rootDir);
96 break;
97 case wplPlaylist:
98 return parsePlaylist_wpl(data, fileList, baseDir, rootDir);
99 break;
100 default:
101 return false;
102 break;
106 ////////////////////////////////////////////////////////////
107 // Private Functions
108 ////////////////////////////////////////////////////////////
110 PlaylistImporter::playlist_t PlaylistImporter::isPlaylist(const QString &fileName)
112 QFileInfo file (fileName);
114 if(file.suffix().compare("m3u", Qt::CaseInsensitive) == 0 || file.suffix().compare("m3u8", Qt::CaseInsensitive) == 0)
116 return m3uPlaylist;
118 else if(file.suffix().compare("pls", Qt::CaseInsensitive) == 0)
120 return plsPlaylist;
122 else if(file.suffix().compare("asx", Qt::CaseInsensitive) == 0 || file.suffix().compare("wpl", Qt::CaseInsensitive) == 0)
124 return wplPlaylist;
126 else
128 return notPlaylist;
132 bool PlaylistImporter::parsePlaylist_m3u(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
134 QByteArray line = data.readLine();
136 while(line.size() > 0)
138 QFileInfo filename1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
139 QFileInfo filename2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
141 filename1.setCaching(false);
142 filename2.setCaching(false);
144 if(!(filename1.filePath().startsWith("#") || filename2.filePath().startsWith("#")))
146 fixFilePath(filename1, baseDir, rootDir);
147 fixFilePath(filename2, baseDir, rootDir);
149 if(filename1.exists())
151 if(isPlaylist(filename1.canonicalFilePath()) == notPlaylist)
153 fileList << filename1.canonicalFilePath();
156 else if(filename2.exists())
158 if(isPlaylist(filename2.canonicalFilePath()) == notPlaylist)
160 fileList << filename2.canonicalFilePath();
165 line = data.readLine();
168 return true;
171 bool PlaylistImporter::parsePlaylist_pls(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
173 QRegExp plsEntry("File(\\d+)=(.+)", Qt::CaseInsensitive);
174 QByteArray line = data.readLine();
176 while(line.size() > 0)
178 bool flag = false;
180 QString temp1(QDir::fromNativeSeparators(QString::fromUtf8(line.constData(), line.size()).trimmed()));
181 QString temp2(QDir::fromNativeSeparators(QString::fromLatin1(line.constData(), line.size()).trimmed()));
183 if(!flag && plsEntry.indexIn(temp1) >= 0)
185 QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
186 filename.setCaching(false);
187 fixFilePath(filename, baseDir, rootDir);
189 if(filename.exists())
191 if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
193 fileList << filename.canonicalFilePath();
195 flag = true;
199 if(!flag && plsEntry.indexIn(temp2) >= 0)
201 QFileInfo filename(QDir::fromNativeSeparators(plsEntry.cap(2)).trimmed());
202 filename.setCaching(false);
203 fixFilePath(filename, baseDir, rootDir);
205 if(filename.exists())
207 if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
209 fileList << filename.canonicalFilePath();
211 flag = true;
215 line = data.readLine();
218 return true;
221 bool PlaylistImporter::parsePlaylist_wpl(QFile &data, QStringList &fileList, const QDir &baseDir, const QDir &rootDir)
223 QRegExp skipData("<!--(.+)-->", Qt::CaseInsensitive);
224 QRegExp wplEntry("<(media|ref)[^<>]*(src|href)=\"([^\"]+)\"[^<>]*>", Qt::CaseInsensitive);
226 skipData.setMinimal(true);
228 QByteArray buffer = data.readAll();
229 QString line = QString::fromUtf8(buffer.constData(), buffer.size()).simplified();
230 buffer.clear();
232 int index = 0;
234 while((index = skipData.indexIn(line)) >= 0)
236 line.remove(index, skipData.matchedLength());
239 int offset = 0;
241 while((offset = wplEntry.indexIn(line, offset) + 1) > 0)
243 QFileInfo filename(QDir::fromNativeSeparators(unescapeXml(wplEntry.cap(3)).trimmed()));
244 filename.setCaching(false);
245 fixFilePath(filename, baseDir, rootDir);
247 if(filename.exists())
249 if(isPlaylist(filename.canonicalFilePath()) == notPlaylist)
251 fileList << filename.canonicalFilePath();
256 return true;
259 void PlaylistImporter::fixFilePath(QFileInfo &filename, const QDir &baseDir, const QDir &rootDir)
261 if(filename.filePath().startsWith("/"))
263 while(filename.filePath().startsWith("/"))
265 filename.setFile(filename.filePath().mid(1));
267 filename.setFile(rootDir.filePath(filename.filePath()));
270 if(!filename.isAbsolute())
272 filename.setFile(baseDir.filePath(filename.filePath()));
276 QString &PlaylistImporter::unescapeXml(QString &str)
278 for(int i = 0; (g_xmlEscapeSequence[i].escape && g_xmlEscapeSequence[i].output); i++)
280 str.replace(g_xmlEscapeSequence[i].escape, g_xmlEscapeSequence[i].output);
283 return str;