2
// C++ Implementation: parserm3u
4
// Description: module to parse m3u(plaintext) formated playlists
7
// Author: Ingo Kossyk <kossyki@cs.tu-berlin.de>, (C) 2004
8
// Author: Tobias Rafreider trafreider@mixxx.org, (C) 2011
10
// Copyright: See COPYING file that comes with this distribution
13
#include <QTextStream>
16
#include <QMessageBox>
17
#include "parserm3u.h"
22
@author Ingo Kossyk (kossyki@cs.tu-berlin.de)
27
- parse ALL informations from the pls file if available ,
28
not only the filepath;
31
The M3U format is just a headerless plaintext format
32
where every line of text either represents
33
a file location or a comment. comments are being
34
preceeded by a '#'. This parser will try to parse all
35
file information from the given file and add the filepaths
36
to the locations ptrlist when the file is existing locally
37
or on a mounted harddrive.
40
ParserM3u::ParserM3u() : Parser()
44
ParserM3u::~ParserM3u()
50
QList<QString> ParserM3u::parse(QString sFilename)
52
QFile file(sFilename);
53
QString basepath = sFilename.section('/', 0, -2);
56
//qDebug() << "ParserM3u: Starting to parse.";
57
if (file.open(QIODevice::ReadOnly) && !isBinary(sFilename)) {
58
/* Unfortunately, QT 4.7 does not handle <CR> (=\r or asci value 13) line breaks.
59
* This is important on OS X where iTunes, e.g., exports M3U playlists using <CR>
62
* Using QFile::readAll() we obtain the complete content of the playlist as a ByteArray.
63
* We replace any '\r' with '\n' if applicaple
64
* This ensures that playlists from iTunes on OS X can be parsed
66
QByteArray ba = file.readAll();
68
bool isCRLF_encoded = ba.contains("\r\n");
69
bool isCR_encoded = ba.contains("\r");
70
if(isCR_encoded && !isCRLF_encoded)
71
ba.replace('\r','\n');
72
QTextStream textstream(ba.data());
74
if (isUtf8(ba.data())) {
75
textstream.setCodec("UTF-8");
77
textstream.setCodec("windows-1252");
80
while(!textstream.atEnd()) {
81
QString sLine = getFilepath(&textstream, basepath);
85
//qDebug() << "ParserM3u: parsed: " << (sLine);
86
m_sLocations.append(sLine);
91
if(m_sLocations.count() != 0)
94
return QList<QString>(); // NULL pointer returned when no locations were found
99
return QList<QString>(); //if we get here something went wrong
103
QString ParserM3u::getFilepath(QTextStream *stream, QString basepath)
105
QString textline,filename = "";
107
textline = stream->readLine();
109
while(!textline.isEmpty()){
110
//qDebug() << "Untransofrmed text: " << textline;
111
if(textline.isNull())
114
if(!textline.contains("#")){
116
filename.remove("file://");
117
QByteArray strlocbytes = filename.toUtf8();
118
//qDebug() << "QByteArray UTF-8: " << strlocbytes;
119
QUrl location = QUrl::fromEncoded(strlocbytes);
120
//qDebug() << "QURL UTF-8: " << location;
121
QString trackLocation = location.toString();
122
//qDebug() << "UTF8 TrackLocation:" << trackLocation;
123
if(isFilepath(trackLocation)) {
124
return trackLocation;
126
// Try relative to m3u dir
127
QString rel = basepath + "/" + trackLocation;
128
if (isFilepath(rel)) {
131
// We couldn't match this to a real file so ignore it
134
textline = stream->readLine();
137
// Signal we reached the end
142
bool ParserM3u::writeM3UFile(const QString &file_str, QList<QString> &items, bool useRelativePath) {
143
return writeM3UFile(file_str, items, useRelativePath, false);
146
bool ParserM3u::writeM3U8File(const QString &file_str, QList<QString> &items, bool useRelativePath) {
147
return writeM3UFile(file_str, items, useRelativePath, true);
150
bool ParserM3u::writeM3UFile(const QString &file_str, QList<QString> &items, bool useRelativePath, bool useUtf8)
153
// On Windows \n will produce a <CR><CL> (=\r\n)
154
// On Linux and OS X \n is <CR> (which remains \n)
158
codec = QTextCodec::codecForName("UTF-8");
160
// according to http://en.wikipedia.org/wiki/M3U the default encoding of m3u is Windows-1252
161
// see also http://tools.ietf.org/html/draft-pantos-http-live-streaming-07
162
// check if the all items can be properly encoded to Latin1.
163
codec = QTextCodec::codecForName("windows-1252");
164
for (int i = 0; i < items.size(); ++i) {
165
if (!codec->canEncode(items.at(i))) {
166
// filepath contains incompatible character
167
QMessageBox::warning(NULL,tr("Playlist Export Failed"),
168
tr("File path contains characters, not allowed in m3u playlists.\n") +
169
tr("Export a m3u8 playlist instead!\n") +
176
QFile file(file_str);
177
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
178
QMessageBox::warning(NULL,tr("Playlist Export Failed"),
179
tr("Could not create file") + " " + file_str);
183
// Base folder of file
184
QString base = file_str.section('/', 0, -2);
187
qDebug() << "Basepath: " << base;
188
QTextStream out(&file);
191
for (int i = 0; i < items.size(); ++i) {
193
// Write relative path if possible
194
if (useRelativePath) {
195
//QDir::relativePath() will return the absolutePath if it cannot compute the
197
out << base_dir.relativeFilePath(items.at(i)) << "\n";
199
out << items.at(i) << "\n";