1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2011 LoRd_MuldeR <MuldeR2@GMX.de>
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.
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"
25 #include <QStringList>
33 //Un-escape XML characters
39 g_xmlEscapeSequence
[] =
50 const char *PlaylistImporter::supportedExtensions
= "*.m3u *.m3u8 *.pls *.asx *.wpl";
53 ////////////////////////////////////////////////////////////
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());
66 if(file
.size() < 3 || file
.size() > 512000)
71 //Detect playlist type
72 playlist_t playlistType
= isPlaylist(file
.canonicalFilePath());
74 //Exit if not a playlist
75 if(playlistType
== notPlaylist
)
80 QFile
data(playlistFile
);
82 //Open file for reading
83 if(!data
.open(QIODevice::ReadOnly
))
88 //Parse playlist depending on type
92 return parsePlaylist_m3u(data
, fileList
, baseDir
, rootDir
);
95 return parsePlaylist_pls(data
, fileList
, baseDir
, rootDir
);
98 return parsePlaylist_wpl(data
, fileList
, baseDir
, rootDir
);
106 ////////////////////////////////////////////////////////////
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)
118 else if(file
.suffix().compare("pls", Qt::CaseInsensitive
) == 0)
122 else if(file
.suffix().compare("asx", Qt::CaseInsensitive
) == 0 || file
.suffix().compare("wpl", Qt::CaseInsensitive
) == 0)
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();
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)
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();
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();
215 line
= data
.readLine();
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();
234 while((index
= skipData
.indexIn(line
)) >= 0)
236 line
.remove(index
, skipData
.matchedLength());
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();
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
);