diff options
Diffstat (limited to 'src/plugins/PlayListFormats')
6 files changed, 176 insertions, 65 deletions
diff --git a/src/plugins/PlayListFormats/m3u/m3uplaylistformat.cpp b/src/plugins/PlayListFormats/m3u/m3uplaylistformat.cpp index 87bd2eaf8..783f3c518 100644 --- a/src/plugins/PlayListFormats/m3u/m3uplaylistformat.cpp +++ b/src/plugins/PlayListFormats/m3u/m3uplaylistformat.cpp @@ -32,34 +32,57 @@ const PlayListFormatProperties M3UPlaylistFormat::properties() const return p; } -QStringList M3UPlaylistFormat::decode(const QString & contents) +QList<PlayListTrack *> M3UPlaylistFormat::decode(const QByteArray &contents) { - QStringList out; - QStringList splitted = contents.split("\n"); + QList<PlayListTrack*> out; + QStringList splitted = QString::fromUtf8(contents).split("\n"); if(splitted.isEmpty()) - return QStringList(); + return out; + + QRegExp extInfRegExp("#EXTINF:(-{0,1}\\d+),(.*) - (.*)"); + int length = 0; + QString artist, title; + bool hasExtInf = false; foreach(QString str, splitted) { - str = str.trimmed (); - if (str.startsWith("#EXTM3U") || str.startsWith("#EXTINF:") || str.isEmpty()) - continue;//TODO: Let's skip it for now.. - else if (str.startsWith("#") || str.isEmpty()) + str = str.trimmed(); + if(str.startsWith("#EXTM3U") || str.isEmpty()) continue; - else - out << str; + + if(extInfRegExp.indexIn(str) > -1) + { + length = extInfRegExp.cap(1).toInt(); + artist = extInfRegExp.cap(2); + title = extInfRegExp.cap(3); + hasExtInf = true; + } + + if(str.startsWith("#")) + continue; + + out << new PlayListTrack(); + out.last()->insert(Qmmp::URL, str); + + if(hasExtInf) + { + out.last()->setLength(length); + out.last()->insert(Qmmp::ARTIST, artist); + out.last()->insert(Qmmp::TITLE, title); + hasExtInf = false; + } } return out; } -QString M3UPlaylistFormat::encode(const QList<PlayListTrack*> & contents, const QString &path) +QByteArray M3UPlaylistFormat::encode(const QList<PlayListTrack*> &contents, const QString &path) { QStringList out; out << QString("#EXTM3U"); MetaDataFormatter formatter("%if(%p,%p - %t,%t)%if(%p|%t,,%f)"); QString m3uDir = QFileInfo(path).canonicalPath(); - foreach(PlayListTrack* f,contents) + foreach(PlayListTrack* f, contents) { QString info = "#EXTINF:" + QString::number(f->length()) + "," + formatter.format(f); out.append(info); @@ -75,7 +98,7 @@ QString M3UPlaylistFormat::encode(const QList<PlayListTrack*> & contents, const else out.append(f->url()); } - return out.join("\n"); + return out.join("\n").toUtf8(); } Q_EXPORT_PLUGIN2(m3uplaylistformat,M3UPlaylistFormat) diff --git a/src/plugins/PlayListFormats/m3u/m3uplaylistformat.h b/src/plugins/PlayListFormats/m3u/m3uplaylistformat.h index 379ae063e..dd859c807 100644 --- a/src/plugins/PlayListFormats/m3u/m3uplaylistformat.h +++ b/src/plugins/PlayListFormats/m3u/m3uplaylistformat.h @@ -36,8 +36,8 @@ class M3UPlaylistFormat : public QObject, public PlayListFormat Q_INTERFACES(PlayListFormat) public: const PlayListFormatProperties properties() const; - QStringList decode(const QString& contents); - QString encode(const QList<PlayListTrack*>& contents, const QString &path); + QList<PlayListTrack*> decode(const QByteArray &contents); + QByteArray encode(const QList<PlayListTrack*>& contents, const QString &path); }; diff --git a/src/plugins/PlayListFormats/pls/plsplaylistformat.cpp b/src/plugins/PlayListFormats/pls/plsplaylistformat.cpp index ac4954567..a4822c423 100644 --- a/src/plugins/PlayListFormats/pls/plsplaylistformat.cpp +++ b/src/plugins/PlayListFormats/pls/plsplaylistformat.cpp @@ -18,8 +18,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ -#include <QFileInfo> #include <QtPlugin> +#include <QRegExp> +#include <qmmpui/metadataformatter.h> #include "plsplaylistformat.h" const PlayListFormatProperties PLSPlaylistFormat::properties() const @@ -31,57 +32,111 @@ const PlayListFormatProperties PLSPlaylistFormat::properties() const return p; } -QStringList PLSPlaylistFormat::decode(const QString & contents) +QList<PlayListTrack *> PLSPlaylistFormat::decode(const QByteArray &contents) { - QStringList out; - QStringList splitted = contents.split("\n"); - if (!splitted.isEmpty()) + QList<PlayListTrack *> out; + QStringList splitted = QString::fromUtf8(contents).split("\n"); + + if(splitted.isEmpty()) { - if (splitted.takeAt(0).toLower().contains("[playlist]")) + qWarning("PLSPlaylistFormat: error parsing PLS format"); + return out; + } + + if(!splitted.takeFirst().toLower().startsWith("[playlist]")) + { + qWarning("PLSPlaylistFormat: unknown playlist format"); + return out; + } + + QRegExp fileRegExp("^File(\\d+)=(.+)"); + QRegExp fullTitleRegExp("^Title(\\d+)=(.+) - (.+)"); + QRegExp titleRegExp("^Title(\\d+)=(.+)"); + QRegExp lengthRegExp("^Length(\\d+)=(-{0,1}\\d+)"); + + int number = 0; + bool error = false; + + foreach (QString line, splitted) + { + if(fileRegExp.indexIn(line) > -1) { - foreach(QString str, splitted) + if((number = fileRegExp.cap(1).toInt()) > 0) { - if (str.startsWith("File")) - { - QString unverified = str.remove(0,str.indexOf(QChar('=')) + 1); - unverified = unverified.trimmed(); - if (unverified.startsWith("http://")) - { - out << unverified; - } - else /*if (QFileInfo(unverified).exists())*/ - out << QFileInfo(unverified).absoluteFilePath(); - /*else - qWarning("File %s does not exist", qPrintable(unverified));*/ - } + while(number > out.count()) + out << new PlayListTrack(); + out[number - 1]->insert(Qmmp::URL, fileRegExp.cap(2)); } - return out; + else + error = true; + } + else if(fullTitleRegExp.indexIn(line) > -1) + { + if((number = fullTitleRegExp.cap(1).toInt()) > 0) + { + while(number > out.count()) + out << new PlayListTrack(); + out[number - 1]->insert(Qmmp::ARTIST, fullTitleRegExp.cap(2)); + out[number - 1]->insert(Qmmp::TITLE, fullTitleRegExp.cap(3)); + } + else + error = true; + } + else if(titleRegExp.indexIn(line) > -1) + { + if((number = titleRegExp.cap(1).toInt()) > 0) + { + while(number > out.count()) + out << new PlayListTrack(); + out[number - 1]->insert(Qmmp::TITLE, titleRegExp.cap(2)); + } + else + error = true; + } + else if(lengthRegExp.indexIn(line) > -1) + { + if((number = lengthRegExp.cap(1).toInt()) > 0) + { + while(number > out.count()) + out << new PlayListTrack(); + out[number - 1]->setLength(lengthRegExp.cap(2).toInt()); + } + else + error = true; + } + + if(error) + { + qWarning("PLSPlaylistFormat: error while parsing line: '%s'", qPrintable(line)); + qDeleteAll(out); + out.clear(); + break; } } - else - qWarning("Error parsing PLS format"); - return QStringList(); + return out; } -QString PLSPlaylistFormat::encode(const QList<PlayListTrack *> & contents, const QString &path) +QByteArray PLSPlaylistFormat::encode(const QList<PlayListTrack *> &contents, const QString &path) { Q_UNUSED(path); + MetaDataFormatter formatter("%if(%p,%p - %t,%t)%if(%p|%t,,%f)"); QStringList out; out << QString("[playlist]"); int counter = 1; - foreach(PlayListTrack* f,contents) + foreach(PlayListTrack *f, contents) { QString begin = "File" + QString::number(counter) + "="; out.append(begin + f->url()); begin = "Title" + QString::number(counter) + "="; - out.append(begin + f->value(Qmmp::TITLE)); + out.append(begin + formatter.format(f)); begin = "Length" + QString::number(counter) + "="; out.append(begin + QString::number(f->length())); - counter ++; + counter++; } out << "NumberOfEntries=" + QString::number(contents.count()); - return out.join("\n"); + out << "Version=2"; + return out.join("\n").toUtf8(); } Q_EXPORT_PLUGIN2(plsplaylistformat, PLSPlaylistFormat) diff --git a/src/plugins/PlayListFormats/pls/plsplaylistformat.h b/src/plugins/PlayListFormats/pls/plsplaylistformat.h index 7fed6d810..79bebf91c 100644 --- a/src/plugins/PlayListFormats/pls/plsplaylistformat.h +++ b/src/plugins/PlayListFormats/pls/plsplaylistformat.h @@ -36,8 +36,8 @@ class PLSPlaylistFormat : public QObject, public PlayListFormat Q_INTERFACES(PlayListFormat) public: const PlayListFormatProperties properties() const; - QStringList decode(const QString& contents); - QString encode(const QList<PlayListTrack*>& contents, const QString &path); + QList<PlayListTrack*> decode(const QByteArray& contents); + QByteArray encode(const QList<PlayListTrack*> &contents, const QString &path); }; diff --git a/src/plugins/PlayListFormats/xspf/xspfplaylistformat.cpp b/src/plugins/PlayListFormats/xspf/xspfplaylistformat.cpp index d5ab21fb5..93d691d3c 100644 --- a/src/plugins/PlayListFormats/xspf/xspfplaylistformat.cpp +++ b/src/plugins/PlayListFormats/xspf/xspfplaylistformat.cpp @@ -37,11 +37,11 @@ const PlayListFormatProperties XSPFPlaylistFormat::XSPFPlaylistFormat::propertie return p; } -QStringList XSPFPlaylistFormat::decode(const QString & contents) +QList<PlayListTrack*> XSPFPlaylistFormat::decode(const QByteArray &contents) { - QStringList out; + QList<PlayListTrack*> out; QString currentTag; - QString contents_copy = contents; + QString contents_copy = QString::fromUtf8(contents); //remove control symbols to avoid xml errors for(int i = 0; i < contents_copy.size(); ++i) @@ -54,24 +54,47 @@ QStringList XSPFPlaylistFormat::decode(const QString & contents) } QXmlStreamReader xml(contents_copy); - while(!xml.atEnd()) + while(!xml.atEnd() || !xml.hasError()) { xml.readNext(); if (xml.isStartElement()) { currentTag = xml.name().toString(); - + if(currentTag == "track") + out << new PlayListTrack(); } else if (xml.isCharacters() && !xml.isWhitespace()) { - if (currentTag == "location") - { + if(out.isEmpty()) + continue; + if(currentTag == "location") + { QUrl url(xml.text().toString()); if (url.scheme() == "file") //remove scheme for local files only - out << QUrl::fromPercentEncoding(url.toString().toLatin1()).remove("file://"); + out.last()->insert(Qmmp::URL, QUrl::fromPercentEncoding(url.toString().toLatin1()).remove("file://")); else - out << QUrl::fromPercentEncoding(url.toString().toLatin1()); + out.last()->insert(Qmmp::URL, QUrl::fromPercentEncoding(url.toString().toLatin1())); + } + else if(currentTag == "title") + { + out.last()->insert(Qmmp::TITLE, xml.text().toString()); + } + else if(currentTag == "creator") + { + out.last()->insert(Qmmp::ARTIST, xml.text().toString()); + } + else if(currentTag == "annotation") + { + out.last()->insert(Qmmp::COMMENT, xml.text().toString()); + } + else if(currentTag == "album") + { + out.last()->insert(Qmmp::ALBUM, xml.text().toString()); + } + else if(currentTag == "meta" && xml.attributes().value("rel") == "year") + { + out.last()->insert(Qmmp::YEAR, xml.text().toString()); } else xml.skipCurrentElement(); @@ -88,10 +111,10 @@ QStringList XSPFPlaylistFormat::decode(const QString & contents) // Needs more work - it's better use libSpiff there and put it as plugin. -QString XSPFPlaylistFormat::encode(const QList<PlayListTrack*> & files, const QString &path) +QByteArray XSPFPlaylistFormat::encode(const QList<PlayListTrack*> &files, const QString &path) { - Q_UNUSED(path); - QString out; + QString xspfDir = QFileInfo(path).canonicalPath(); + QByteArray out; QXmlStreamWriter xml(&out); xml.setCodec("UTF-8"); xml.setAutoFormatting(true); @@ -103,16 +126,27 @@ QString XSPFPlaylistFormat::encode(const QList<PlayListTrack*> & files, const QS xml.writeStartElement("trackList"); int counter = 1; - foreach(PlayListTrack* f,files) + foreach(PlayListTrack* f, files) { xml.writeStartElement("track"); QString url; if (f->url().contains("://")) + { url = QUrl::toPercentEncoding(f->url(), ":/"); - else //append protocol - url = QUrl::toPercentEncoding(QString("file://") + - QFileInfo(f->url()).absoluteFilePath(), ":/"); + } + else if(f->url().startsWith(xspfDir)) //relative path + { + QString p = f->url(); + p.remove(0, xspfDir.size()); + if(p.startsWith("/")) + p.remove(0, 1); + url = QUrl::toPercentEncoding(p, ":/"); + } + else //absolute path + { + url = QUrl::toPercentEncoding(QLatin1String("file://") + f->url(), ":/"); + } xml.writeTextElement("location", url); xml.writeTextElement("title", f->value(Qmmp::TITLE)); @@ -133,7 +167,6 @@ QString XSPFPlaylistFormat::encode(const QList<PlayListTrack*> & files, const QS xml.writeEndElement(); //playlist xml.writeEndDocument(); return out; - } Q_EXPORT_PLUGIN2(xspfplaylistformat,XSPFPlaylistFormat) diff --git a/src/plugins/PlayListFormats/xspf/xspfplaylistformat.h b/src/plugins/PlayListFormats/xspf/xspfplaylistformat.h index d3b03d3ca..dbd1325d5 100644 --- a/src/plugins/PlayListFormats/xspf/xspfplaylistformat.h +++ b/src/plugins/PlayListFormats/xspf/xspfplaylistformat.h @@ -36,8 +36,8 @@ class XSPFPlaylistFormat : public QObject, public PlayListFormat Q_INTERFACES(PlayListFormat) public: const PlayListFormatProperties properties() const; - QStringList decode(const QString& contents); - QString encode(const QList<PlayListTrack*>& contents, const QString &path); + QList<PlayListTrack*> decode(const QByteArray &contents); + QByteArray encode(const QList<PlayListTrack*> &contents, const QString &path); }; #endif |
