summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Strømme <christian.stromme@qt.io>2016-08-31 17:55:37 +0200
committerChristian Stromme <christian.stromme@qt.io>2016-12-12 13:08:07 +0000
commitc89e2ea249015142f59c8ea440b6e36bac6f96c9 (patch)
tree9dc4b156aa7b069af61d4c57e5e03a22758a70db
parent57c146936c36e7ab9591970e22a9b6e2840ef37a (diff)
Improve the playlist parser
The main goals of this change is to make the parser more lightweight, e.g., by removing unneeded QObject allocations, and make it possible to stop the parsing more quickly. In addition, support for the same resources as the media player was added, that is, support for QMediaContent, QMediaResource, and QIODevice. The combination of these changes should make it easier and faster to use the parser internally. Change-Id: I1f25d6529fa9bab0c6c3c9d9de35b7f8b4a708e0 Reviewed-by: Yoann Lopes <yoann.lopes@qt.io>
-rw-r--r--src/multimedia/playback/playback.pri4
-rw-r--r--src/multimedia/playback/qmedianetworkplaylistprovider.cpp10
-rw-r--r--src/multimedia/playback/qplaylistfileparser.cpp (renamed from src/multimedia/playback/playlistfileparser.cpp)438
-rw-r--r--src/multimedia/playback/qplaylistfileparser_p.h (renamed from src/multimedia/playback/playlistfileparser_p.h)36
4 files changed, 312 insertions, 176 deletions
diff --git a/src/multimedia/playback/playback.pri b/src/multimedia/playback/playback.pri
index 3bbb8ce15..cc55fc1b0 100644
--- a/src/multimedia/playback/playback.pri
+++ b/src/multimedia/playback/playback.pri
@@ -12,7 +12,7 @@ PRIVATE_HEADERS += \
playback/qmediaplaylistioplugin_p.h \
playback/qmediaplaylistnavigator_p.h \
playback/qmedianetworkplaylistprovider_p.h \
- playback/playlistfileparser_p.h
+ playback/qplaylistfileparser_p.h
SOURCES += \
playback/qmedianetworkplaylistprovider.cpp \
@@ -23,4 +23,4 @@ SOURCES += \
playback/qmediaplaylistnavigator.cpp \
playback/qmediaplaylistprovider.cpp \
playback/qmediaresource.cpp \
- playback/playlistfileparser.cpp
+ playback/qplaylistfileparser.cpp
diff --git a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
index 7de90d9a1..a4ad97251 100644
--- a/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
+++ b/src/multimedia/playback/qmedianetworkplaylistprovider.cpp
@@ -41,7 +41,7 @@
#include "qmediaplaylistprovider_p.h"
#include "qmediacontent.h"
#include "qmediaobject_p.h"
-#include "playlistfileparser_p.h"
+#include "qplaylistfileparser_p.h"
QT_BEGIN_NAMESPACE
@@ -62,8 +62,8 @@ public:
bool QMediaNetworkPlaylistProviderPrivate::load(const QNetworkRequest &request)
{
- parser.stop();
- parser.start(request, false);
+ parser.abort();
+ parser.start(request);
return true;
}
@@ -83,12 +83,14 @@ void QMediaNetworkPlaylistProviderPrivate::_q_handleParserError(QPlaylistFilePar
case QPlaylistFileParser::FormatNotSupportedError:
playlistError = QMediaPlaylist::FormatNotSupportedError;
break;
+ case QPlaylistFileParser::ResourceError:
+ // fall through
case QPlaylistFileParser::NetworkError:
playlistError = QMediaPlaylist::NetworkError;
break;
}
- parser.stop();
+ parser.abort();
emit q->loadFailed(playlistError, errorMessage);
}
diff --git a/src/multimedia/playback/playlistfileparser.cpp b/src/multimedia/playback/qplaylistfileparser.cpp
index 237e417a6..424e54d34 100644
--- a/src/multimedia/playback/playlistfileparser.cpp
+++ b/src/multimedia/playback/qplaylistfileparser.cpp
@@ -37,31 +37,48 @@
**
****************************************************************************/
-#include "playlistfileparser_p.h"
+#include "qplaylistfileparser_p.h"
#include <qfileinfo.h>
#include <QtCore/QDebug>
+#include <QtCore/qiodevice.h>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
+#include "qmediaplayer.h"
#include "qmediaobject_p.h"
-#include <private/qobject_p.h>
#include "qmediametadata.h"
+#include "qmediacontent.h"
+#include "qmediaresource.h"
QT_BEGIN_NAMESPACE
namespace {
-class ParserBase : public QObject
+
+class ParserBase
{
- Q_OBJECT
public:
- ParserBase(QObject *parent)
- : QObject(parent)
+ explicit ParserBase(QPlaylistFileParser *parent)
+ : m_parent(parent)
+ , m_aborted(false)
+ {
+ Q_ASSERT(m_parent);
+ }
+
+ bool parseLine(int lineIndex, const QString& line, const QUrl& root)
{
+ if (m_aborted)
+ return false;
+
+ const bool ok = parseLineImpl(lineIndex, line, root);
+ return ok && !m_aborted;
}
- virtual void parseLine(int lineIndex, const QString& line, const QUrl& root) = 0;
+ virtual void abort() { m_aborted = true; }
+ virtual ~ParserBase() { }
protected:
- QUrl expandToFullPath(const QUrl &root, const QString &line)
+ virtual bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root) = 0;
+
+ static QUrl expandToFullPath(const QUrl &root, const QString &line)
{
// On Linux, backslashes are not converted to forward slashes :/
if (line.startsWith(QLatin1String("//")) || line.startsWith(QLatin1String("\\\\"))) {
@@ -84,22 +101,22 @@ protected:
return url;
}
-Q_SIGNALS:
- void newItem(const QVariant& content);
- void finished();
- void error(QPlaylistFileParser::ParserError err, const QString& errorMsg);
+ void newItemFound(const QVariant& content) { Q_EMIT m_parent->newItem(content); }
+
+private:
+ QPlaylistFileParser *m_parent;
+ bool m_aborted;
};
class M3UParser : public ParserBase
{
public:
- M3UParser(QObject *parent)
- : ParserBase(parent)
+ explicit M3UParser(QPlaylistFileParser *q)
+ : ParserBase(q)
, m_extendedFormat(false)
{
}
-
/*
*
Extended M3U directives
@@ -117,7 +134,7 @@ public:
C:\Documents and Settings\I\My Music\Greatest Hits\Example.ogg
*/
- void parseLine(int lineIndex, const QString& line, const QUrl& root)
+ bool parseLineImpl(int lineIndex, const QString& line, const QUrl& root)
{
if (line[0] == '#' ) {
if (m_extendedFormat) {
@@ -149,9 +166,11 @@ public:
}
} else {
m_extraInfo[QLatin1String("url")] = expandToFullPath(root, line);
- emit newItem(QVariant(m_extraInfo));
+ newItemFound(QVariant(m_extraInfo));
m_extraInfo.clear();
}
+
+ return true;
}
int getSplitIndex(const QString& line, int startPos)
@@ -172,16 +191,15 @@ public:
}
private:
- bool m_extendedFormat;
QVariantMap m_extraInfo;
+ bool m_extendedFormat;
};
class PLSParser : public ParserBase
{
- Q_OBJECT
public:
- PLSParser(QObject *parent)
- : ParserBase(parent)
+ explicit PLSParser(QPlaylistFileParser *q)
+ : ParserBase(q)
{
}
@@ -223,17 +241,19 @@ NumberOfEntries=2
Version=2
*/
- void parseLine(int, const QString &line, const QUrl &root)
+ bool parseLineImpl(int, const QString &line, const QUrl &root)
{
// We ignore everything but 'File' entries, since that's the only thing we care about.
if (!line.startsWith(QLatin1String("File")))
- return;
+ return true;
QString value = getValue(line);
if (value.isEmpty())
- return;
+ return true;
- emit newItem(expandToFullPath(root, value));
+ newItemFound(expandToFullPath(root, value));
+
+ return true;
}
QString getValue(const QString& line) {
@@ -247,75 +267,84 @@ Version=2
/////////////////////////////////////////////////////////////////////////////////////////////////
-class QPlaylistFileParserPrivate : public QObjectPrivate
+class QPlaylistFileParserPrivate
{
Q_DECLARE_PUBLIC(QPlaylistFileParser)
public:
- QPlaylistFileParserPrivate()
- : m_source(0)
+ QPlaylistFileParserPrivate(QPlaylistFileParser *q)
+ : q_ptr(q)
+ , m_stream(0)
+ , m_type(QPlaylistFileParser::UNKNOWN)
, m_scanIndex(0)
- , m_utf8(false)
, m_lineIndex(-1)
- , m_type(QPlaylistFileParser::UNKNOWN)
- , m_currentParser(0)
+ , m_utf8(false)
+ , m_aborted(false)
{
}
- void _q_handleData();
- void _q_handleError();
- void _q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg);
- void _q_handleParserFinished();
+ void handleData();
+ void handleParserFinished();
+ void abort();
+ void reset();
- QNetworkReply *m_source;
+ QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> m_source;
+ QScopedPointer<ParserBase> m_currentParser;
QByteArray m_buffer;
- int m_scanIndex;
QUrl m_root;
- bool m_utf8;
- int m_lineIndex;
- QPlaylistFileParser::FileType m_type;
- ParserBase *m_currentParser;
QNetworkAccessManager m_mgr;
+ QString m_mimeType;
+ QPlaylistFileParser *q_ptr;
+ QIODevice *m_stream;
+ QPlaylistFileParser::FileType m_type;
+ struct ParserJob
+ {
+ QIODevice *m_stream;
+ QMediaResource m_resource;
+ bool isValid() const { return m_stream || !m_resource.isNull(); }
+ void reset() { m_stream = 0; m_resource = QMediaResource(); }
+ } m_pendingJob;
+ int m_scanIndex;
+ int m_lineIndex;
+ bool m_utf8;
+ bool m_aborted;
private:
- void processLine(int startIndex, int length);
+ bool processLine(int startIndex, int length);
};
#define LINE_LIMIT 4096
#define READ_LIMIT 64
-void QPlaylistFileParserPrivate::processLine(int startIndex, int length)
+bool QPlaylistFileParserPrivate::processLine(int startIndex, int length)
{
Q_Q(QPlaylistFileParser);
m_lineIndex++;
if (!m_currentParser) {
- Q_ASSERT(!m_currentParser);
-
- QString mimeType = m_source->header(QNetworkRequest::ContentTypeHeader).toString();
- m_type = QPlaylistFileParser::findPlaylistType(m_root.toString(), mimeType, m_buffer.constData(), m_buffer.size());
+ const QString urlString = m_root.toString();
+ const QString &suffix = !urlString.isEmpty() ? QFileInfo(urlString).suffix() : urlString;
+ const QString &mimeType = m_source->header(QNetworkRequest::ContentTypeHeader).toString();
+ m_type = QPlaylistFileParser::findPlaylistType(suffix, !mimeType.isEmpty() ? mimeType : m_mimeType, m_buffer.constData(), quint32(m_buffer.size()));
switch (m_type) {
case QPlaylistFileParser::UNKNOWN:
emit q->error(QPlaylistFileParser::FormatError,
QPlaylistFileParser::tr("%1 playlist type is unknown").arg(m_root.toString()));
- q->stop();
- return;
+ q->abort();
+ return false;
case QPlaylistFileParser::M3U:
- m_currentParser = new M3UParser(q);
+ m_currentParser.reset(new M3UParser(q));
break;
case QPlaylistFileParser::M3U8:
- m_currentParser = new M3UParser(q);
+ m_currentParser.reset(new M3UParser(q));
m_utf8 = true;
break;
case QPlaylistFileParser::PLS:
- m_currentParser = new PLSParser(q);
+ m_currentParser.reset(new PLSParser(q));
break;
}
- Q_ASSERT(m_currentParser);
- QObject::connect(m_currentParser, SIGNAL(newItem(QVariant)), q, SIGNAL(newItem(QVariant)));
- QObject::connect(m_currentParser, SIGNAL(finished()), q, SLOT(_q_handleParserFinished()));
- QObject::connect(m_currentParser, SIGNAL(error(QPlaylistFileParser::ParserError,QString)),
- q, SLOT(_q_handleParserError(QPlaylistFileParser::ParserError,QString)));
+
+ Q_ASSERT(!m_currentParser.isNull());
}
QString line;
@@ -326,26 +355,28 @@ void QPlaylistFileParserPrivate::processLine(int startIndex, int length)
line = QString::fromLatin1(m_buffer.constData() + startIndex, length).trimmed();
}
if (line.isEmpty())
- return;
+ return true;
Q_ASSERT(m_currentParser);
- m_currentParser->parseLine(m_lineIndex, line, m_root);
+ return m_currentParser->parseLine(m_lineIndex, line, m_root);
}
-void QPlaylistFileParserPrivate::_q_handleData()
+void QPlaylistFileParserPrivate::handleData()
{
Q_Q(QPlaylistFileParser);
- while (m_source->bytesAvailable()) {
+ while (m_source->bytesAvailable() && !m_aborted) {
int expectedBytes = qMin(READ_LIMIT, int(qMin(m_source->bytesAvailable(),
qint64(LINE_LIMIT - m_buffer.size()))));
m_buffer.push_back(m_source->read(expectedBytes));
int processedBytes = 0;
- while (m_scanIndex < m_buffer.length()) {
+ while (m_scanIndex < m_buffer.length() && !m_aborted) {
char s = m_buffer[m_scanIndex];
if (s == '\r' || s == '\n') {
int l = m_scanIndex - processedBytes;
- if (l > 0)
- processLine(processedBytes, l);
+ if (l > 0) {
+ if (!processLine(processedBytes, l))
+ break;
+ }
processedBytes = m_scanIndex + 1;
if (!m_source) {
//some error happened, so exit parsing
@@ -355,11 +386,13 @@ void QPlaylistFileParserPrivate::_q_handleData()
m_scanIndex++;
}
+ if (m_aborted)
+ break;
+
if (m_buffer.length() - processedBytes >= LINE_LIMIT) {
- qWarning() << "error parsing playlist["<< m_root << "] with line content >= 4096 bytes.";
emit q->error(QPlaylistFileParser::FormatError, QPlaylistFileParser::tr("invalid line in playlist file"));
- q->stop();
- return;
+ q->abort();
+ break;
}
if (m_source->isFinished() && !m_source->bytesAvailable()) {
@@ -382,143 +415,226 @@ void QPlaylistFileParserPrivate::_q_handleData()
m_scanIndex = 0;
}
- if (m_source->isFinished()) {
- _q_handleParserFinished();
- }
+ handleParserFinished();
}
-void QPlaylistFileParserPrivate::_q_handleError()
+QPlaylistFileParser::QPlaylistFileParser(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QPlaylistFileParserPrivate(this))
{
- Q_Q(QPlaylistFileParser);
- emit q->error(QPlaylistFileParser::NetworkError, m_source->errorString());
- q->stop();
+
}
-void QPlaylistFileParserPrivate::_q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg)
+QPlaylistFileParser::~QPlaylistFileParser()
{
- Q_Q(QPlaylistFileParser);
- emit q->error(err, errorMsg);
+
}
-void QPlaylistFileParserPrivate::_q_handleParserFinished()
+QPlaylistFileParser::FileType QPlaylistFileParser::findByMimeType(const QString &mime)
{
- Q_Q(QPlaylistFileParser);
- bool isParserValid = (m_currentParser != 0);
- if (!isParserValid)
- emit q->error(QPlaylistFileParser::FormatNotSupportedError, QPlaylistFileParser::tr("Empty file provided"));
+ if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") || mime == QLatin1String("audio/mpegurl"))
+ return QPlaylistFileParser::M3U;
- q->stop();
+ if (mime == QLatin1String("application/x-mpegURL") || mime == QLatin1String("application/vnd.apple.mpegurl"))
+ return QPlaylistFileParser::M3U8;
- if (isParserValid)
- emit q->finished();
-}
+ if (mime == QLatin1String("audio/x-scpls"))
+ return QPlaylistFileParser::PLS;
+ return QPlaylistFileParser::UNKNOWN;
+}
-QPlaylistFileParser::QPlaylistFileParser(QObject *parent)
- : QObject(*new QPlaylistFileParserPrivate, parent)
+QPlaylistFileParser::FileType QPlaylistFileParser::findBySuffixType(const QString &suffix)
{
+ const QString &s = suffix.toLower();
+
+ if (s == QLatin1String("m3u"))
+ return QPlaylistFileParser::M3U;
+
+ if (s == QLatin1String("m3u8"))
+ return QPlaylistFileParser::M3U8;
+ if (s == QLatin1String("pls"))
+ return QPlaylistFileParser::PLS;
+
+ return QPlaylistFileParser::UNKNOWN;
}
-QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString& uri, const QString& mime, const void *data, quint32 size)
+QPlaylistFileParser::FileType QPlaylistFileParser::findByDataHeader(const char *data, quint32 size)
{
- if (!data || !size)
- return UNKNOWN;
-
- FileType uriType = UNKNOWN;
- QString suffix = QFileInfo(uri).suffix().toLower();
- if (suffix == QLatin1String("m3u"))
- uriType = M3U;
- else if (suffix == QLatin1String("m3u8"))
- uriType = M3U8;
- else if (suffix == QLatin1String("pls"))
- uriType = PLS;
-
- FileType mimeType = UNKNOWN;
- if (mime == QLatin1String("text/uri-list") || mime == QLatin1String("audio/x-mpegurl") || mime == QLatin1String("audio/mpegurl"))
- mimeType = QPlaylistFileParser::M3U;
- else if (mime == QLatin1String("application/x-mpegURL") || mime == QLatin1String("application/vnd.apple.mpegurl"))
- mimeType = QPlaylistFileParser::M3U8;
- else if (mime == QLatin1String("audio/x-scpls"))
- mimeType = QPlaylistFileParser::PLS;
-
- FileType bufferType = UNKNOWN;
- if (size >= 7 && strncmp((const char*)data, "#EXTM3U", 7) == 0)
- bufferType = M3U;
- else if (size >= 10 && strncmp((const char*)data, "[playlist]", 10) == 0)
- bufferType = PLS;
- else {
- // Make sure every line is a text string
- quint32 n;
- for (n = 0; n < size; n++)
- if (!QChar(QLatin1Char(((const char*)data)[n])).isPrint())
- break;
- if (n == size)
- bufferType = M3U;
- }
+ if (!data || size == 0)
+ return QPlaylistFileParser::UNKNOWN;
- if (bufferType == M3U && (uriType == M3U8 || mimeType == M3U8))
- bufferType = M3U8;
+ if (size >= 7 && strncmp(data, "#EXTM3U", 7) == 0)
+ return QPlaylistFileParser::M3U;
+
+ if (size >= 10 && strncmp(data, "[playlist]", 10) == 0)
+ return QPlaylistFileParser::PLS;
+
+ return QPlaylistFileParser::UNKNOWN;
+}
- if (bufferType != UNKNOWN)
- return bufferType;
+QPlaylistFileParser::FileType QPlaylistFileParser::findPlaylistType(const QString& suffix,
+ const QString& mime,
+ const char *data,
+ quint32 size)
+{
- if (uriType != UNKNOWN)
- return uriType;
+ FileType dataHeaderType = findByDataHeader(data, size);
+ if (dataHeaderType != UNKNOWN)
+ return dataHeaderType;
+ FileType mimeType = findByMimeType(mime);
if (mimeType != UNKNOWN)
return mimeType;
+ FileType suffixType = findBySuffixType(suffix);
+ if (suffixType != UNKNOWN)
+ return suffixType;
+
return UNKNOWN;
}
-void QPlaylistFileParser::start(const QNetworkRequest& request, bool utf8)
+/*
+ * Delegating
+ */
+void QPlaylistFileParser::start(const QMediaContent &media, QIODevice *stream)
+{
+ const QMediaResource &mediaResource = media.canonicalResource();
+ const QString &mimeType = mediaResource.mimeType();
+
+ if (stream) {
+ start(stream, mediaResource.mimeType());
+ } else {
+ const QNetworkRequest &request = mediaResource.request();
+ const QUrl &url = mediaResource.url();
+
+ if (request.url().isValid())
+ start(request, mimeType);
+ else
+ start(QNetworkRequest(url), mimeType);
+ }
+}
+
+void QPlaylistFileParser::start(QIODevice *stream, const QString &mimeType)
{
Q_D(QPlaylistFileParser);
- stop();
+ const bool validStream = stream ? (stream->isOpen() && stream->isReadable()) : false;
+
+ if (!validStream) {
+ Q_EMIT error(ResourceError, tr("Invalid stream"));
+ return;
+ }
+
+ if (!d->m_currentParser.isNull()) {
+ abort();
+ d->m_pendingJob = { stream, QMediaResource(QUrl(), mimeType) };
+ return;
+ }
+
+ d->reset();
+ d->m_mimeType = mimeType;
+ d->m_stream = stream;
+ connect(d->m_stream, SIGNAL(readyRead()), this, SLOT(_q_handleData()));
+ d->handleData();
+}
- d->m_type = UNKNOWN;
- d->m_utf8 = utf8;
- d->m_root = request.url();
+void QPlaylistFileParser::start(const QNetworkRequest& request, const QString &mimeType)
+{
+ Q_D(QPlaylistFileParser);
+ const QUrl &url = request.url();
- if (d->m_root.isLocalFile() && !QFile::exists(d->m_root.toLocalFile())) {
- emit error(NetworkError, QString(tr("%1 does not exist")).arg(d->m_root.toString()));
+ if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) {
+ emit error(ResourceError, QString(tr("%1 does not exist")).arg(url.toString()));
return;
}
- d->m_source = d->m_mgr.get(request);
+ if (!d->m_currentParser.isNull()) {
+ abort();
+ d->m_pendingJob = { Q_NULLPTR, QMediaResource(request, mimeType) };
+ return;
+ }
- connect(d->m_source, SIGNAL(readyRead()), this, SLOT(_q_handleData()));
- connect(d->m_source, SIGNAL(finished()), this, SLOT(_q_handleData()));
- connect(d->m_source, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(_q_handleError()));
+ d->reset();
+ d->m_root = url;
+ d->m_mimeType = mimeType;
+ d->m_source.reset(d->m_mgr.get(request));
+ connect(d->m_source.data(), SIGNAL(readyRead()), this, SLOT(handleData()));
+ connect(d->m_source.data(), SIGNAL(finished()), this, SLOT(handleData()));
+ connect(d->m_source.data(), SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleError()));
- d->_q_handleData();
+ d->handleData();
}
-void QPlaylistFileParser::stop()
+void QPlaylistFileParser::abort()
{
Q_D(QPlaylistFileParser);
- if (d->m_currentParser) {
- disconnect(d->m_currentParser, SIGNAL(newItem(QVariant)), this, SIGNAL(newItem(QVariant)));
- disconnect(d->m_currentParser, SIGNAL(finished()), this, SLOT(_q_handleParserFinished()));
- disconnect(d->m_currentParser, SIGNAL(error(QPlaylistFileParser::ParserError,QString)),
- this, SLOT(_q_handleParserError(QPlaylistFileParser::ParserError,QString)));
- d->m_currentParser->deleteLater();
- d->m_currentParser = 0;
- }
+ d->abort();
+
+ if (d->m_source)
+ d->m_source->disconnect();
- d->m_buffer.clear();
- d->m_scanIndex = 0;
- d->m_lineIndex = -1;
- if (d->m_source) {
- disconnect(d->m_source, SIGNAL(readyRead()), this, SLOT(_q_handleData()));
- disconnect(d->m_source, SIGNAL(finished()), this, SLOT(_q_handleData()));
- disconnect(d->m_source, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(_q_handleError()));
- d->m_source->deleteLater();
- d->m_source = 0;
+ if (d->m_stream)
+ disconnect(d->m_stream, SIGNAL(readyRead()), this, SLOT(handleData()));
+}
+
+void QPlaylistFileParser::handleData()
+{
+ Q_D(QPlaylistFileParser);
+ d->handleData();
+}
+
+void QPlaylistFileParserPrivate::handleParserFinished()
+{
+ Q_Q(QPlaylistFileParser);
+ const bool isParserValid = !m_currentParser.isNull();
+ if (!isParserValid && !m_aborted)
+ emit q->error(QPlaylistFileParser::FormatNotSupportedError, QPlaylistFileParser::tr("Empty file provided"));
+
+ if (isParserValid && !m_aborted) {
+ m_currentParser.reset();
+ emit q->finished();
}
+
+ if (!m_aborted)
+ q->abort();
+
+ if (!m_source.isNull())
+ m_source.reset();
+
+ if (m_pendingJob.isValid())
+ q->start(m_pendingJob.m_resource, m_pendingJob.m_stream);
+}
+
+void QPlaylistFileParserPrivate::abort()
+{
+ m_aborted = true;
+ if (!m_currentParser.isNull())
+ m_currentParser->abort();
+}
+
+void QPlaylistFileParserPrivate::reset()
+{
+ Q_ASSERT(m_currentParser.isNull());
+ Q_ASSERT(m_source.isNull());
+ m_buffer.clear();
+ m_root.clear();
+ m_mimeType.clear();
+ m_stream = 0;
+ m_type = QPlaylistFileParser::UNKNOWN;
+ m_scanIndex = 0;
+ m_lineIndex = -1;
+ m_utf8 = false;
+ m_aborted = false;
+ m_pendingJob.reset();
+}
+
+void QPlaylistFileParser::handleError()
+{
+ Q_D(QPlaylistFileParser);
+ const QString &errorString = d->m_source->errorString();
+ Q_EMIT error(QPlaylistFileParser::NetworkError, errorString);
+ abort();
}
-#include "moc_playlistfileparser_p.cpp"
-#include "playlistfileparser.moc"
QT_END_NAMESPACE
diff --git a/src/multimedia/playback/playlistfileparser_p.h b/src/multimedia/playback/qplaylistfileparser_p.h
index bdf95fe7a..927dbb739 100644
--- a/src/multimedia/playback/playlistfileparser_p.h
+++ b/src/multimedia/playback/qplaylistfileparser_p.h
@@ -52,10 +52,14 @@
//
#include "qtmultimediaglobal.h"
-#include <QtNetwork/QNetworkRequest>
+#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
+class QIODevice;
+class QMediaContent;
+class QNetworkRequest;
+
class QPlaylistFileParserPrivate;
class Q_MULTIMEDIA_EXPORT QPlaylistFileParser : public QObject
@@ -63,6 +67,7 @@ class Q_MULTIMEDIA_EXPORT QPlaylistFileParser : public QObject
Q_OBJECT
public:
QPlaylistFileParser(QObject *parent = 0);
+ ~QPlaylistFileParser();
enum FileType
{
@@ -77,26 +82,39 @@ public:
NoError,
FormatError,
FormatNotSupportedError,
+ ResourceError,
NetworkError
};
- static FileType findPlaylistType(const QString& uri, const QString& mime, const void *data, quint32 size);
-
- void start(const QNetworkRequest &request, bool utf8 = false);
- void stop();
+ void start(const QMediaContent &media, QIODevice *stream = 0);
+ void start(const QNetworkRequest &request, const QString &mimeType = QString());
+ void abort();
Q_SIGNALS:
void newItem(const QVariant& content);
void finished();
void error(QPlaylistFileParser::ParserError err, const QString& errorMsg);
+private Q_SLOTS:
+ void handleData();
+ void handleError();
+
private:
+ void start(QIODevice *stream, const QString &mimeType = QString());
+
+ static FileType findByMimeType(const QString &mime);
+ static FileType findBySuffixType(const QString &suffix);
+ static FileType findByDataHeader(const char *data, quint32 size);
+ static FileType findPlaylistType(QIODevice *device,
+ const QString& mime);
+ static FileType findPlaylistType(const QString &suffix,
+ const QString& mime,
+ const char *data = 0,
+ quint32 size = 0);
+
Q_DISABLE_COPY(QPlaylistFileParser)
Q_DECLARE_PRIVATE(QPlaylistFileParser)
- Q_PRIVATE_SLOT(d_func(), void _q_handleData())
- Q_PRIVATE_SLOT(d_func(), void _q_handleError())
- Q_PRIVATE_SLOT(d_func(), void _q_handleParserError(QPlaylistFileParser::ParserError err, const QString& errorMsg))
- Q_PRIVATE_SLOT(d_func(), void _q_handleParserFinished())
+ QScopedPointer<QPlaylistFileParserPrivate> d_ptr;
};
QT_END_NAMESPACE