QMediaPlayer frontend: changes to playlist support.
Allow to load playlists using setMedia(). Use QNetworkMediaPlaylistProvider for playlist parsing. Updated unit tests. Change-Id: If4dba07be8b2e8a9e9549d5bed58e552dfb958b7 Reviewed-by: Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com>
This commit is contained in:
committed by
Qt by Nokia
parent
2ebea05283
commit
2c034beab5
@@ -11,16 +11,18 @@ PRIVATE_HEADERS += \
|
|||||||
playback/qmediaplaylist_p.h \
|
playback/qmediaplaylist_p.h \
|
||||||
playback/qmediaplaylistprovider_p.h \
|
playback/qmediaplaylistprovider_p.h \
|
||||||
playback/qmediaplaylistioplugin_p.h \
|
playback/qmediaplaylistioplugin_p.h \
|
||||||
playback/qlocalmediaplaylistprovider_p.h \
|
playback/qmediaplaylistnavigator_p.h \
|
||||||
playback/qmediaplaylistnavigator_p.h
|
playback/qmedianetworkplaylistprovider_p.h \
|
||||||
|
playback/playlistfileparser_p.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
playback/qaudioendpointselector.cpp \
|
playback/qaudioendpointselector.cpp \
|
||||||
playback/qlocalmediaplaylistprovider.cpp \
|
playback/qmedianetworkplaylistprovider.cpp \
|
||||||
playback/qmediacontent.cpp \
|
playback/qmediacontent.cpp \
|
||||||
playback/qmediaplayer.cpp \
|
playback/qmediaplayer.cpp \
|
||||||
playback/qmediaplaylist.cpp \
|
playback/qmediaplaylist.cpp \
|
||||||
playback/qmediaplaylistioplugin.cpp \
|
playback/qmediaplaylistioplugin.cpp \
|
||||||
playback/qmediaplaylistnavigator.cpp \
|
playback/qmediaplaylistnavigator.cpp \
|
||||||
playback/qmediaplaylistprovider.cpp \
|
playback/qmediaplaylistprovider.cpp \
|
||||||
playback/qmediaresource.cpp
|
playback/qmediaresource.cpp \
|
||||||
|
playback/playlistfileparser.cpp
|
||||||
|
|||||||
@@ -1,194 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/
|
|
||||||
**
|
|
||||||
** This file is part of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
|
||||||
** file. Please review the following information to ensure the GNU Lesser
|
|
||||||
** General Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU General
|
|
||||||
** Public License version 3.0 as published by the Free Software Foundation
|
|
||||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
||||||
** file. Please review the following information to ensure the GNU General
|
|
||||||
** Public License version 3.0 requirements will be met:
|
|
||||||
** http://www.gnu.org/copyleft/gpl.html.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "qlocalmediaplaylistprovider_p.h"
|
|
||||||
#include "qmediaplaylistprovider_p.h"
|
|
||||||
#include "qmediacontent.h"
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class QLocalMediaPlaylistProviderPrivate: public QMediaPlaylistProviderPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QList<QMediaContent> resources;
|
|
||||||
};
|
|
||||||
|
|
||||||
QLocalMediaPlaylistProvider::QLocalMediaPlaylistProvider(QObject *parent)
|
|
||||||
:QMediaPlaylistProvider(*new QLocalMediaPlaylistProviderPrivate, parent)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QLocalMediaPlaylistProvider::~QLocalMediaPlaylistProvider()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::isReadOnly() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int QLocalMediaPlaylistProvider::mediaCount() const
|
|
||||||
{
|
|
||||||
return d_func()->resources.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
QMediaContent QLocalMediaPlaylistProvider::media(int pos) const
|
|
||||||
{
|
|
||||||
return d_func()->resources.value(pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::addMedia(const QMediaContent &content)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
int pos = d->resources.count();
|
|
||||||
|
|
||||||
emit mediaAboutToBeInserted(pos, pos);
|
|
||||||
d->resources.append(content);
|
|
||||||
emit mediaInserted(pos, pos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::addMedia(const QList<QMediaContent> &items)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
if (items.isEmpty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int pos = d->resources.count();
|
|
||||||
int end = pos+items.count()-1;
|
|
||||||
|
|
||||||
emit mediaAboutToBeInserted(pos, end);
|
|
||||||
d->resources.append(items);
|
|
||||||
emit mediaInserted(pos, end);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QMediaContent &content)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
emit mediaAboutToBeInserted(pos, pos);
|
|
||||||
d->resources.insert(pos, content);
|
|
||||||
emit mediaInserted(pos,pos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::insertMedia(int pos, const QList<QMediaContent> &items)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
if (items.isEmpty())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
const int last = pos+items.count()-1;
|
|
||||||
|
|
||||||
emit mediaAboutToBeInserted(pos, last);
|
|
||||||
for (int i=0; i<items.count(); i++)
|
|
||||||
d->resources.insert(pos+i, items.at(i));
|
|
||||||
emit mediaInserted(pos, last);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::removeMedia(int fromPos, int toPos)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
Q_ASSERT(fromPos >= 0);
|
|
||||||
Q_ASSERT(fromPos <= toPos);
|
|
||||||
Q_ASSERT(toPos < mediaCount());
|
|
||||||
|
|
||||||
emit mediaAboutToBeRemoved(fromPos, toPos);
|
|
||||||
d->resources.erase(d->resources.begin()+fromPos, d->resources.begin()+toPos+1);
|
|
||||||
emit mediaRemoved(fromPos, toPos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::removeMedia(int pos)
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
|
|
||||||
emit mediaAboutToBeRemoved(pos, pos);
|
|
||||||
d->resources.removeAt(pos);
|
|
||||||
emit mediaRemoved(pos, pos);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QLocalMediaPlaylistProvider::clear()
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
if (!d->resources.isEmpty()) {
|
|
||||||
int lastPos = mediaCount()-1;
|
|
||||||
emit mediaAboutToBeRemoved(0, lastPos);
|
|
||||||
d->resources.clear();
|
|
||||||
emit mediaRemoved(0, lastPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QLocalMediaPlaylistProvider::shuffle()
|
|
||||||
{
|
|
||||||
Q_D(QLocalMediaPlaylistProvider);
|
|
||||||
if (!d->resources.isEmpty()) {
|
|
||||||
QList<QMediaContent> resources;
|
|
||||||
|
|
||||||
while (!d->resources.isEmpty()) {
|
|
||||||
resources.append(d->resources.takeAt(qrand() % d->resources.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
d->resources = resources;
|
|
||||||
emit mediaChanged(0, mediaCount()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "moc_qlocalmediaplaylistprovider_p.cpp"
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/****************************************************************************
|
|
||||||
**
|
|
||||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
||||||
** Contact: http://www.qt-project.org/
|
|
||||||
**
|
|
||||||
** This file is part of the Qt Toolkit.
|
|
||||||
**
|
|
||||||
** $QT_BEGIN_LICENSE:LGPL$
|
|
||||||
** GNU Lesser General Public License Usage
|
|
||||||
** This file may be used under the terms of the GNU Lesser General Public
|
|
||||||
** License version 2.1 as published by the Free Software Foundation and
|
|
||||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
|
||||||
** file. Please review the following information to ensure the GNU Lesser
|
|
||||||
** General Public License version 2.1 requirements will be met:
|
|
||||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
||||||
**
|
|
||||||
** In addition, as a special exception, Nokia gives you certain additional
|
|
||||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
||||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
||||||
**
|
|
||||||
** GNU General Public License Usage
|
|
||||||
** Alternatively, this file may be used under the terms of the GNU General
|
|
||||||
** Public License version 3.0 as published by the Free Software Foundation
|
|
||||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
|
||||||
** file. Please review the following information to ensure the GNU General
|
|
||||||
** Public License version 3.0 requirements will be met:
|
|
||||||
** http://www.gnu.org/copyleft/gpl.html.
|
|
||||||
**
|
|
||||||
** Other Usage
|
|
||||||
** Alternatively, this file may be used in accordance with the terms and
|
|
||||||
** conditions contained in a signed written agreement between you and Nokia.
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
**
|
|
||||||
** $QT_END_LICENSE$
|
|
||||||
**
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef QLOCALMEDIAPAYLISTPROVIDER_P_H
|
|
||||||
#define QLOCALMEDIAPAYLISTPROVIDER_P_H
|
|
||||||
|
|
||||||
//
|
|
||||||
// W A R N I N G
|
|
||||||
// -------------
|
|
||||||
//
|
|
||||||
// This file is not part of the Qt API. It exists purely as an
|
|
||||||
// implementation detail. This header file may change from version to
|
|
||||||
// version without notice, or even be removed.
|
|
||||||
//
|
|
||||||
// We mean it.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "qmediaplaylistprovider_p.h"
|
|
||||||
|
|
||||||
QT_BEGIN_HEADER
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
QT_MODULE(Multimedia)
|
|
||||||
|
|
||||||
|
|
||||||
class QLocalMediaPlaylistProviderPrivate;
|
|
||||||
class Q_MULTIMEDIA_EXPORT QLocalMediaPlaylistProvider : public QMediaPlaylistProvider
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
QLocalMediaPlaylistProvider(QObject *parent=0);
|
|
||||||
virtual ~QLocalMediaPlaylistProvider();
|
|
||||||
|
|
||||||
virtual int mediaCount() const;
|
|
||||||
virtual QMediaContent media(int pos) const;
|
|
||||||
|
|
||||||
virtual bool isReadOnly() const;
|
|
||||||
|
|
||||||
virtual bool addMedia(const QMediaContent &content);
|
|
||||||
virtual bool addMedia(const QList<QMediaContent> &items);
|
|
||||||
virtual bool insertMedia(int pos, const QMediaContent &content);
|
|
||||||
virtual bool insertMedia(int pos, const QList<QMediaContent> &items);
|
|
||||||
virtual bool removeMedia(int pos);
|
|
||||||
virtual bool removeMedia(int start, int end);
|
|
||||||
virtual bool clear();
|
|
||||||
|
|
||||||
public Q_SLOTS:
|
|
||||||
virtual void shuffle();
|
|
||||||
|
|
||||||
private:
|
|
||||||
Q_DECLARE_PRIVATE(QLocalMediaPlaylistProvider)
|
|
||||||
};
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
QT_END_HEADER
|
|
||||||
|
|
||||||
|
|
||||||
#endif // QLOCALMEDIAPAYLISTSOURCE_P_H
|
|
||||||
@@ -49,7 +49,6 @@
|
|||||||
#include <qmediaplaylist.h>
|
#include <qmediaplaylist.h>
|
||||||
#include <qmediaplaylistcontrol_p.h>
|
#include <qmediaplaylistcontrol_p.h>
|
||||||
#include <qmediaplaylistsourcecontrol_p.h>
|
#include <qmediaplaylistsourcecontrol_p.h>
|
||||||
|
|
||||||
#include <qmedianetworkaccesscontrol.h>
|
#include <qmedianetworkaccesscontrol.h>
|
||||||
|
|
||||||
#include <QtCore/qcoreevent.h>
|
#include <QtCore/qcoreevent.h>
|
||||||
@@ -97,6 +96,8 @@ public:
|
|||||||
} _registerPlayerMetaTypes;
|
} _registerPlayerMetaTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define MAX_NESTED_PLAYLISTS 16
|
||||||
|
|
||||||
class QMediaPlayerPrivate : public QMediaObjectPrivate
|
class QMediaPlayerPrivate : public QMediaObjectPrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_NON_CONST_PUBLIC(QMediaPlayer)
|
Q_DECLARE_NON_CONST_PUBLIC(QMediaPlayer)
|
||||||
@@ -105,47 +106,86 @@ public:
|
|||||||
QMediaPlayerPrivate()
|
QMediaPlayerPrivate()
|
||||||
: provider(0)
|
: provider(0)
|
||||||
, control(0)
|
, control(0)
|
||||||
, playlistSourceControl(0)
|
|
||||||
, state(QMediaPlayer::StoppedState)
|
, state(QMediaPlayer::StoppedState)
|
||||||
, error(QMediaPlayer::NoError)
|
, error(QMediaPlayer::NoError)
|
||||||
, filterStates(false)
|
|
||||||
, playlist(0)
|
, playlist(0)
|
||||||
, networkAccessControl(0)
|
, networkAccessControl(0)
|
||||||
|
, nestedPlaylists(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
QMediaServiceProvider *provider;
|
QMediaServiceProvider *provider;
|
||||||
QMediaPlayerControl* control;
|
QMediaPlayerControl* control;
|
||||||
QMediaPlaylistSourceControl* playlistSourceControl;
|
|
||||||
QMediaPlayer::State state;
|
QMediaPlayer::State state;
|
||||||
QMediaPlayer::Error error;
|
QMediaPlayer::Error error;
|
||||||
QString errorString;
|
QString errorString;
|
||||||
bool filterStates;
|
|
||||||
|
|
||||||
QPointer<QObject> videoOutput;
|
QPointer<QObject> videoOutput;
|
||||||
QMediaPlaylist *playlist;
|
QMediaPlaylist *playlist;
|
||||||
QMediaNetworkAccessControl *networkAccessControl;
|
QMediaNetworkAccessControl *networkAccessControl;
|
||||||
QVideoSurfaceOutput surfaceOutput;
|
QVideoSurfaceOutput surfaceOutput;
|
||||||
|
|
||||||
|
QMediaContent rootMedia;
|
||||||
|
QMediaContent pendingPlaylist;
|
||||||
|
QMediaPlaylist *parentPlaylist(QMediaPlaylist *pls);
|
||||||
|
bool isInChain(QUrl url);
|
||||||
|
int nestedPlaylists;
|
||||||
|
|
||||||
|
void setPlaylist(QMediaPlaylist *playlist);
|
||||||
|
void setPlaylistMedia();
|
||||||
|
void loadPlaylist();
|
||||||
|
void disconnectPlaylist();
|
||||||
|
void connectPlaylist();
|
||||||
|
|
||||||
void _q_stateChanged(QMediaPlayer::State state);
|
void _q_stateChanged(QMediaPlayer::State state);
|
||||||
void _q_mediaStatusChanged(QMediaPlayer::MediaStatus status);
|
void _q_mediaStatusChanged(QMediaPlayer::MediaStatus status);
|
||||||
void _q_error(int error, const QString &errorString);
|
void _q_error(int error, const QString &errorString);
|
||||||
void _q_updateMedia(const QMediaContent&);
|
void _q_updateMedia(const QMediaContent&);
|
||||||
void _q_playlistDestroyed();
|
void _q_playlistDestroyed();
|
||||||
|
void _q_handlePlaylistLoaded();
|
||||||
|
void _q_handlePlaylistLoadFailed();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
QMediaPlaylist *QMediaPlayerPrivate::parentPlaylist(QMediaPlaylist *pls)
|
||||||
|
{
|
||||||
|
// This function finds a parent playlist for an item in the active chain of playlists.
|
||||||
|
// Every item in the chain comes from currentMedia() of its parent.
|
||||||
|
// We don't need to travers the whole tree of playlists,
|
||||||
|
// but only the subtree of active ones.
|
||||||
|
for (QMediaPlaylist *current = rootMedia.playlist(); current && current != pls; current = current->currentMedia().playlist())
|
||||||
|
if (current->currentMedia().playlist() == pls)
|
||||||
|
return current;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMediaPlayerPrivate::isInChain(QUrl url)
|
||||||
|
{
|
||||||
|
// Check whether a URL is already in the chain of playlists.
|
||||||
|
// Also see a comment in parentPlaylist().
|
||||||
|
for (QMediaPlaylist *current = rootMedia.playlist(); current && current != playlist; current = current->currentMedia().playlist())
|
||||||
|
if (current->currentMedia().canonicalUrl() == url) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void QMediaPlayerPrivate::_q_stateChanged(QMediaPlayer::State ps)
|
void QMediaPlayerPrivate::_q_stateChanged(QMediaPlayer::State ps)
|
||||||
{
|
{
|
||||||
Q_Q(QMediaPlayer);
|
Q_Q(QMediaPlayer);
|
||||||
|
|
||||||
if (filterStates)
|
// Backend switches into stopped state every time new media is about to be loaded.
|
||||||
return;
|
// If media player has a playlist loaded make sure player doesn' stop.
|
||||||
|
if (playlist && playlist->currentIndex() != -1 && ps != state && ps == QMediaPlayer::StoppedState) {
|
||||||
if (playlist
|
if (control->mediaStatus() == QMediaPlayer::EndOfMedia ||
|
||||||
&& ps != state && ps == QMediaPlayer::StoppedState
|
control->mediaStatus() == QMediaPlayer::InvalidMedia) {
|
||||||
&& (control->mediaStatus() == QMediaPlayer::EndOfMedia ||
|
// if media player is not stopped, and
|
||||||
control->mediaStatus() == QMediaPlayer::InvalidMedia)) {
|
// we have finished playback for the current media,
|
||||||
playlist->next();
|
// advance to the next item in the playlist
|
||||||
ps = control->state();
|
Q_ASSERT(state != QMediaPlayer::StoppedState);
|
||||||
|
playlist->next();
|
||||||
|
return;
|
||||||
|
} else if (control->mediaStatus() == QMediaPlayer::LoadingMedia) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps != state) {
|
if (ps != state) {
|
||||||
@@ -182,10 +222,16 @@ void QMediaPlayerPrivate::_q_error(int error, const QString &errorString)
|
|||||||
{
|
{
|
||||||
Q_Q(QMediaPlayer);
|
Q_Q(QMediaPlayer);
|
||||||
|
|
||||||
this->error = QMediaPlayer::Error(error);
|
if (error == int(QMediaPlayer::MediaIsPlaylist)) {
|
||||||
this->errorString = errorString;
|
loadPlaylist();
|
||||||
|
} else {
|
||||||
|
this->error = QMediaPlayer::Error(error);
|
||||||
|
this->errorString = errorString;
|
||||||
|
emit q->error(this->error);
|
||||||
|
|
||||||
emit q->error(this->error);
|
if (playlist)
|
||||||
|
playlist->next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
|
void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
|
||||||
@@ -195,9 +241,45 @@ void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
|
|||||||
if (!control)
|
if (!control)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// check if the current playlist is a top-level playlist
|
||||||
|
Q_ASSERT(playlist);
|
||||||
|
if (media.isNull() && playlist != rootMedia.playlist()) {
|
||||||
|
// switch back to parent playlist
|
||||||
|
QMediaPlaylist *pls = parentPlaylist(playlist);
|
||||||
|
Q_ASSERT(pls);
|
||||||
|
disconnectPlaylist();
|
||||||
|
playlist = pls;
|
||||||
|
connectPlaylist();
|
||||||
|
|
||||||
|
Q_ASSERT(!pendingPlaylist.playlist());
|
||||||
|
nestedPlaylists--;
|
||||||
|
Q_ASSERT(nestedPlaylists >= 0);
|
||||||
|
|
||||||
|
playlist->next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (media.playlist()) {
|
||||||
|
if (nestedPlaylists < MAX_NESTED_PLAYLISTS) {
|
||||||
|
nestedPlaylists++;
|
||||||
|
Q_ASSERT(!pendingPlaylist.playlist());
|
||||||
|
|
||||||
|
// disconnect current playlist
|
||||||
|
disconnectPlaylist();
|
||||||
|
// new playlist signals are connected
|
||||||
|
// in the call to setPlaylist() in _q_handlePlaylistLoaded()
|
||||||
|
playlist = media.playlist();
|
||||||
|
emit q->currentMediaChanged(media);
|
||||||
|
_q_handlePlaylistLoaded();
|
||||||
|
return;
|
||||||
|
} else if (playlist) {
|
||||||
|
playlist->next();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const QMediaPlayer::State currentState = state;
|
const QMediaPlayer::State currentState = state;
|
||||||
|
|
||||||
filterStates = true;
|
|
||||||
control->setMedia(media, 0);
|
control->setMedia(media, 0);
|
||||||
|
|
||||||
if (!media.isNull()) {
|
if (!media.isNull()) {
|
||||||
@@ -212,18 +294,8 @@ void QMediaPlayerPrivate::_q_updateMedia(const QMediaContent &media)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filterStates = false;
|
|
||||||
|
|
||||||
state = control->state();
|
_q_stateChanged(control->state());
|
||||||
|
|
||||||
if (state != currentState) {
|
|
||||||
if (state == QMediaPlayer::PlayingState)
|
|
||||||
q->addPropertyWatch("position");
|
|
||||||
else
|
|
||||||
q->removePropertyWatch("position");
|
|
||||||
|
|
||||||
emit q->stateChanged(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMediaPlayerPrivate::_q_playlistDestroyed()
|
void QMediaPlayerPrivate::_q_playlistDestroyed()
|
||||||
@@ -233,12 +305,151 @@ void QMediaPlayerPrivate::_q_playlistDestroyed()
|
|||||||
if (!control)
|
if (!control)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (playlistSourceControl)
|
|
||||||
playlistSourceControl->setPlaylist(0);
|
|
||||||
|
|
||||||
control->setMedia(QMediaContent(), 0);
|
control->setMedia(QMediaContent(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::setPlaylist(QMediaPlaylist *pls)
|
||||||
|
{
|
||||||
|
disconnectPlaylist();
|
||||||
|
playlist = pls;
|
||||||
|
|
||||||
|
setPlaylistMedia();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::setPlaylistMedia()
|
||||||
|
{
|
||||||
|
// This function loads current playlist media into backend.
|
||||||
|
// If current media is a playlist, the function recursively
|
||||||
|
// loads media from the playlist.
|
||||||
|
// It also makes sure the correct playlist signals are connected.
|
||||||
|
Q_Q(QMediaPlayer);
|
||||||
|
|
||||||
|
if (playlist) {
|
||||||
|
connectPlaylist();
|
||||||
|
if (playlist->currentMedia().playlist()) {
|
||||||
|
if (nestedPlaylists < MAX_NESTED_PLAYLISTS) {
|
||||||
|
emit q->currentMediaChanged(playlist->currentMedia());
|
||||||
|
// rewind nested playlist to start
|
||||||
|
playlist->currentMedia().playlist()->setCurrentIndex(0);
|
||||||
|
nestedPlaylists++;
|
||||||
|
setPlaylist(playlist->currentMedia().playlist());
|
||||||
|
} else {
|
||||||
|
playlist->next();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (control != 0) {
|
||||||
|
// If we've just switched to a new playlist,
|
||||||
|
// then last emited currentMediaChanged was a playlist.
|
||||||
|
// Make sure we emit currentMediaChanged if new playlist has
|
||||||
|
// the same media as the previous one:
|
||||||
|
// sample.m3u
|
||||||
|
// test.wav -- processed by backend
|
||||||
|
// nested.m3u -- processed by frontend
|
||||||
|
// test.wav -- processed by backend,
|
||||||
|
// media is not changed,
|
||||||
|
// frontend needs to emit currentMediaChanged
|
||||||
|
bool isSameMedia = (control->media() == playlist->currentMedia());
|
||||||
|
control->setMedia(playlist->currentMedia(), 0);
|
||||||
|
if (isSameMedia) {
|
||||||
|
emit q->currentMediaChanged(control->media());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
q->setMedia(QMediaContent(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::loadPlaylist()
|
||||||
|
{
|
||||||
|
Q_Q(QMediaPlayer);
|
||||||
|
Q_ASSERT(pendingPlaylist.isNull());
|
||||||
|
|
||||||
|
// Do not load a playlist if there are more than MAX_NESTED_PLAYLISTS in the chain already,
|
||||||
|
// or if the playlist URL is already in the chain, i.e. do not allow recursive playlists and loops.
|
||||||
|
if (nestedPlaylists < MAX_NESTED_PLAYLISTS && !q->currentMedia().canonicalUrl().isEmpty() && !isInChain(q->currentMedia().canonicalUrl())) {
|
||||||
|
pendingPlaylist = QMediaContent(new QMediaPlaylist, q->currentMedia().canonicalUrl(), true);
|
||||||
|
QObject::connect(pendingPlaylist.playlist(), SIGNAL(loaded()), q, SLOT(_q_handlePlaylistLoaded()));
|
||||||
|
QObject::connect(pendingPlaylist.playlist(), SIGNAL(loadFailed()), q, SLOT(_q_handlePlaylistLoadFailed()));
|
||||||
|
pendingPlaylist.playlist()->load(pendingPlaylist.canonicalUrl());
|
||||||
|
} else if (playlist) {
|
||||||
|
playlist->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::disconnectPlaylist()
|
||||||
|
{
|
||||||
|
Q_Q(QMediaPlayer);
|
||||||
|
if (playlist) {
|
||||||
|
QObject::disconnect(playlist, SIGNAL(currentMediaChanged(QMediaContent)),
|
||||||
|
q, SLOT(_q_updateMedia(QMediaContent)));
|
||||||
|
QObject::disconnect(playlist, SIGNAL(destroyed()), q, SLOT(_q_playlistDestroyed()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::connectPlaylist()
|
||||||
|
{
|
||||||
|
Q_Q(QMediaPlayer);
|
||||||
|
if (playlist) {
|
||||||
|
QObject::connect(playlist, SIGNAL(currentMediaChanged(QMediaContent)),
|
||||||
|
q, SLOT(_q_updateMedia(QMediaContent)));
|
||||||
|
QObject::connect(playlist, SIGNAL(destroyed()), q, SLOT(_q_playlistDestroyed()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::_q_handlePlaylistLoaded()
|
||||||
|
{
|
||||||
|
Q_Q(QMediaPlayer);
|
||||||
|
|
||||||
|
QMediaPlaylist *oldPlaylist = 0;
|
||||||
|
if (pendingPlaylist.playlist()) {
|
||||||
|
Q_ASSERT(!q->currentMedia().playlist());
|
||||||
|
// if there is an active playlist
|
||||||
|
if (playlist) {
|
||||||
|
Q_ASSERT(playlist->currentIndex() >= 0);
|
||||||
|
oldPlaylist = playlist;
|
||||||
|
disconnectPlaylist();
|
||||||
|
playlist->insertMedia(playlist->currentIndex() + 1, pendingPlaylist);
|
||||||
|
playlist->removeMedia(playlist->currentIndex());
|
||||||
|
nestedPlaylists++;
|
||||||
|
} else {
|
||||||
|
Q_ASSERT(!rootMedia.playlist());
|
||||||
|
rootMedia = pendingPlaylist;
|
||||||
|
emit q->mediaChanged(rootMedia);
|
||||||
|
}
|
||||||
|
|
||||||
|
playlist = pendingPlaylist.playlist();
|
||||||
|
emit q->currentMediaChanged(pendingPlaylist);
|
||||||
|
}
|
||||||
|
pendingPlaylist = QMediaContent();
|
||||||
|
|
||||||
|
playlist->next();
|
||||||
|
setPlaylistMedia();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case QMediaPlayer::PausedState:
|
||||||
|
control->pause();
|
||||||
|
break;
|
||||||
|
case QMediaPlayer::PlayingState:
|
||||||
|
control->play();
|
||||||
|
break;
|
||||||
|
case QMediaPlayer::StoppedState:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMediaPlayerPrivate::_q_handlePlaylistLoadFailed()
|
||||||
|
{
|
||||||
|
pendingPlaylist = QMediaContent();
|
||||||
|
|
||||||
|
if (!control)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (playlist)
|
||||||
|
playlist->next();
|
||||||
|
else
|
||||||
|
control->setMedia(QMediaContent(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
static QMediaService *playerService(QMediaPlayer::Flags flags)
|
static QMediaService *playerService(QMediaPlayer::Flags flags)
|
||||||
{
|
{
|
||||||
QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
|
QMediaServiceProvider *provider = QMediaServiceProvider::defaultServiceProvider();
|
||||||
@@ -277,10 +488,9 @@ QMediaPlayer::QMediaPlayer(QObject *parent, QMediaPlayer::Flags flags):
|
|||||||
d->error = ServiceMissingError;
|
d->error = ServiceMissingError;
|
||||||
} else {
|
} else {
|
||||||
d->control = qobject_cast<QMediaPlayerControl*>(d->service->requestControl(QMediaPlayerControl_iid));
|
d->control = qobject_cast<QMediaPlayerControl*>(d->service->requestControl(QMediaPlayerControl_iid));
|
||||||
d->playlistSourceControl = qobject_cast<QMediaPlaylistSourceControl*>(d->service->requestControl(QMediaPlaylistSourceControl_iid));
|
|
||||||
d->networkAccessControl = qobject_cast<QMediaNetworkAccessControl*>(d->service->requestControl(QMediaNetworkAccessControl_iid));
|
d->networkAccessControl = qobject_cast<QMediaNetworkAccessControl*>(d->service->requestControl(QMediaNetworkAccessControl_iid));
|
||||||
if (d->control != 0) {
|
if (d->control != 0) {
|
||||||
connect(d->control, SIGNAL(mediaChanged(QMediaContent)), SIGNAL(mediaChanged(QMediaContent)));
|
connect(d->control, SIGNAL(mediaChanged(QMediaContent)), SIGNAL(currentMediaChanged(QMediaContent)));
|
||||||
connect(d->control, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(_q_stateChanged(QMediaPlayer::State)));
|
connect(d->control, SIGNAL(stateChanged(QMediaPlayer::State)), SLOT(_q_stateChanged(QMediaPlayer::State)));
|
||||||
connect(d->control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
|
connect(d->control, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
|
||||||
SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
|
SLOT(_q_mediaStatusChanged(QMediaPlayer::MediaStatus)));
|
||||||
@@ -330,10 +540,7 @@ QMediaContent QMediaPlayer::media() const
|
|||||||
{
|
{
|
||||||
Q_D(const QMediaPlayer);
|
Q_D(const QMediaPlayer);
|
||||||
|
|
||||||
if (d->control != 0)
|
return d->rootMedia;
|
||||||
return d->control->media();
|
|
||||||
|
|
||||||
return QMediaContent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -356,44 +563,25 @@ const QIODevice *QMediaPlayer::mediaStream() const
|
|||||||
|
|
||||||
QMediaPlaylist *QMediaPlayer::playlist() const
|
QMediaPlaylist *QMediaPlayer::playlist() const
|
||||||
{
|
{
|
||||||
return d_func()->playlistSourceControl ?
|
Q_D(const QMediaPlayer);
|
||||||
d_func()->playlistSourceControl->playlist() :
|
|
||||||
d_func()->playlist;
|
return d->rootMedia.playlist();
|
||||||
|
}
|
||||||
|
|
||||||
|
QMediaContent QMediaPlayer::currentMedia() const
|
||||||
|
{
|
||||||
|
Q_D(const QMediaPlayer);
|
||||||
|
|
||||||
|
if (d->control != 0)
|
||||||
|
return d->control->media();
|
||||||
|
|
||||||
|
return QMediaContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMediaPlayer::setPlaylist(QMediaPlaylist *playlist)
|
void QMediaPlayer::setPlaylist(QMediaPlaylist *playlist)
|
||||||
{
|
{
|
||||||
Q_D(QMediaPlayer);
|
QMediaContent m(playlist, QUrl(), false);
|
||||||
|
setMedia(m);
|
||||||
if (d->playlistSourceControl) {
|
|
||||||
if (d->playlistSourceControl->playlist())
|
|
||||||
disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
|
|
||||||
|
|
||||||
d->playlistSourceControl->setPlaylist(playlist);
|
|
||||||
|
|
||||||
if (playlist)
|
|
||||||
connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
|
|
||||||
} else {
|
|
||||||
if (d->playlist) {
|
|
||||||
disconnect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
|
|
||||||
this, SLOT(_q_updateMedia(QMediaContent)));
|
|
||||||
disconnect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
|
|
||||||
}
|
|
||||||
|
|
||||||
d->playlist = playlist;
|
|
||||||
|
|
||||||
if (d->playlist) {
|
|
||||||
connect(d->playlist, SIGNAL(currentMediaChanged(QMediaContent)),
|
|
||||||
this, SLOT(_q_updateMedia(QMediaContent)));
|
|
||||||
connect(d->playlist, SIGNAL(destroyed()), this, SLOT(_q_playlistDestroyed()));
|
|
||||||
|
|
||||||
if (d->control != 0)
|
|
||||||
d->control->setMedia(playlist->currentMedia(), 0);
|
|
||||||
} else {
|
|
||||||
setMedia(QMediaContent(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -563,8 +751,18 @@ void QMediaPlayer::play()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if playlist control is available, the service should advance itself
|
//if playlist control is available, the service should advance itself
|
||||||
if (d->playlist && d->playlist->currentIndex() == -1 && !d->playlist->isEmpty())
|
if (d->rootMedia.playlist() && d->rootMedia.playlist()->currentIndex() == -1 && !d->rootMedia.playlist()->isEmpty()) {
|
||||||
|
|
||||||
|
// switch to playing state
|
||||||
|
if (d->state != QMediaPlayer::PlayingState)
|
||||||
|
d->_q_stateChanged(QMediaPlayer::PlayingState);
|
||||||
|
|
||||||
|
if (d->playlist != d->rootMedia.playlist())
|
||||||
|
d->setPlaylist(d->rootMedia.playlist());
|
||||||
|
Q_ASSERT(d->playlist == d->rootMedia.playlist());
|
||||||
|
emit currentMediaChanged(d->rootMedia);
|
||||||
d->playlist->setCurrentIndex(0);
|
d->playlist->setCurrentIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Reset error conditions
|
// Reset error conditions
|
||||||
d->error = NoError;
|
d->error = NoError;
|
||||||
@@ -595,6 +793,17 @@ void QMediaPlayer::stop()
|
|||||||
|
|
||||||
if (d->control != 0)
|
if (d->control != 0)
|
||||||
d->control->stop();
|
d->control->stop();
|
||||||
|
|
||||||
|
// If media player didn't stop in response to control.
|
||||||
|
// This happens if we have an active playlist and control
|
||||||
|
// media status is
|
||||||
|
// QMediaPlayer::LoadingMedia, QMediaPlayer::InvalidMedia, or QMediaPlayer::EndOfMedia
|
||||||
|
// see QMediaPlayerPrivate::_q_stateChanged()
|
||||||
|
if (d->playlist && d->state != QMediaPlayer::StoppedState) {
|
||||||
|
d->state = QMediaPlayer::StoppedState;
|
||||||
|
removePropertyWatch("position");
|
||||||
|
emit stateChanged(QMediaPlayer::StoppedState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QMediaPlayer::setPosition(qint64 position)
|
void QMediaPlayer::setPosition(qint64 position)
|
||||||
@@ -654,12 +863,24 @@ void QMediaPlayer::setPlaybackRate(qreal rate)
|
|||||||
void QMediaPlayer::setMedia(const QMediaContent &media, QIODevice *stream)
|
void QMediaPlayer::setMedia(const QMediaContent &media, QIODevice *stream)
|
||||||
{
|
{
|
||||||
Q_D(QMediaPlayer);
|
Q_D(QMediaPlayer);
|
||||||
|
stop();
|
||||||
|
|
||||||
if (playlist() && playlist()->currentMedia() != media)
|
QMediaContent oldMedia = d->rootMedia;
|
||||||
setPlaylist(0);
|
d->disconnectPlaylist();
|
||||||
|
d->playlist = 0;
|
||||||
|
d->rootMedia = media;
|
||||||
|
d->nestedPlaylists = 0;
|
||||||
|
|
||||||
if (d->control != 0)
|
if (oldMedia != media)
|
||||||
d_func()->control->setMedia(media, stream);
|
emit mediaChanged(d->rootMedia);
|
||||||
|
|
||||||
|
if (media.playlist()) {
|
||||||
|
// reset playlist to the 1st item
|
||||||
|
media.playlist()->setCurrentIndex(0);
|
||||||
|
d->setPlaylist(media.playlist());
|
||||||
|
} else if (d->control != 0) {
|
||||||
|
d->control->setMedia(media, stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -796,6 +1017,7 @@ QtMultimedia::AvailabilityError QMediaPlayer::availabilityError() const
|
|||||||
return QMediaObject::availabilityError();
|
return QMediaObject::availabilityError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Enums
|
// Enums
|
||||||
/*!
|
/*!
|
||||||
\enum QMediaPlayer::State
|
\enum QMediaPlayer::State
|
||||||
@@ -841,6 +1063,7 @@ QtMultimedia::AvailabilityError QMediaPlayer::availabilityError() const
|
|||||||
\value NetworkError A network error occurred.
|
\value NetworkError A network error occurred.
|
||||||
\value AccessDeniedError There are not the appropriate permissions to play a media resource.
|
\value AccessDeniedError There are not the appropriate permissions to play a media resource.
|
||||||
\value ServiceMissingError A valid playback service was not found, playback cannot proceed.
|
\value ServiceMissingError A valid playback service was not found, playback cannot proceed.
|
||||||
|
\omitvalue MediaIsPlaylist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
@@ -869,9 +1092,17 @@ QtMultimedia::AvailabilityError QMediaPlayer::availabilityError() const
|
|||||||
/*!
|
/*!
|
||||||
\fn void QMediaPlayer::mediaChanged(const QMediaContent &media);
|
\fn void QMediaPlayer::mediaChanged(const QMediaContent &media);
|
||||||
|
|
||||||
Signals that the current playing content will be obtained from \a media.
|
Signals that the media source has been changed to \a media.
|
||||||
|
|
||||||
\sa media()
|
\sa media(), currentMediaChanged()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn void QMediaPlayer::currentMediaChanged(const QMediaContent &media);
|
||||||
|
|
||||||
|
Signals that the current playing content has been changed to \a media.
|
||||||
|
|
||||||
|
\sa currentMedia(), mediaChanged()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -916,7 +1147,17 @@ QtMultimedia::AvailabilityError QMediaPlayer::availabilityError() const
|
|||||||
information relating to the current media source and to cease all I/O operations related
|
information relating to the current media source and to cease all I/O operations related
|
||||||
to that media.
|
to that media.
|
||||||
|
|
||||||
\sa QMediaContent
|
\sa QMediaContent, currentMedia()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QMediaPlayer::currentMedia
|
||||||
|
\brief the current active media content being played by the player object.
|
||||||
|
This value could be different from QMediaPlayer::media property if a playlist is used.
|
||||||
|
In this case currentMedia indicates the current media content being processed
|
||||||
|
by the player, while QMediaPlayer::media property contains the original playlist.
|
||||||
|
|
||||||
|
\sa QMediaContent, media()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -928,7 +1169,7 @@ QtMultimedia::AvailabilityError QMediaPlayer::availabilityError() const
|
|||||||
|
|
||||||
By default this property is set to null.
|
By default this property is set to null.
|
||||||
|
|
||||||
If the media playlist is used as a source, QMediaPlayer::media is updated with
|
If the media playlist is used as a source, QMediaPlayer::currentMedia is updated with
|
||||||
a current playlist item. The current source should be selected with
|
a current playlist item. The current source should be selected with
|
||||||
QMediaPlaylist::setCurrentIndex(int) instead of QMediaPlayer::setMedia(),
|
QMediaPlaylist::setCurrentIndex(int) instead of QMediaPlayer::setMedia(),
|
||||||
otherwise the current playlist will be discarded.
|
otherwise the current playlist will be discarded.
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class Q_MULTIMEDIA_EXPORT QMediaPlayer : public QMediaObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QMediaContent media READ media WRITE setMedia NOTIFY mediaChanged)
|
Q_PROPERTY(QMediaContent media READ media WRITE setMedia NOTIFY mediaChanged)
|
||||||
|
Q_PROPERTY(QMediaContent currentMedia READ currentMedia NOTIFY currentMediaChanged)
|
||||||
Q_PROPERTY(QMediaPlaylist * playlist READ playlist WRITE setPlaylist)
|
Q_PROPERTY(QMediaPlaylist * playlist READ playlist WRITE setPlaylist)
|
||||||
Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
|
Q_PROPERTY(qint64 duration READ duration NOTIFY durationChanged)
|
||||||
Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged)
|
Q_PROPERTY(qint64 position READ position WRITE setPosition NOTIFY positionChanged)
|
||||||
@@ -118,7 +119,8 @@ public:
|
|||||||
FormatError,
|
FormatError,
|
||||||
NetworkError,
|
NetworkError,
|
||||||
AccessDeniedError,
|
AccessDeniedError,
|
||||||
ServiceMissingError
|
ServiceMissingError,
|
||||||
|
MediaIsPlaylist
|
||||||
};
|
};
|
||||||
|
|
||||||
QMediaPlayer(QObject *parent = 0, Flags flags = 0);
|
QMediaPlayer(QObject *parent = 0, Flags flags = 0);
|
||||||
@@ -136,6 +138,7 @@ public:
|
|||||||
QMediaContent media() const;
|
QMediaContent media() const;
|
||||||
const QIODevice *mediaStream() const;
|
const QIODevice *mediaStream() const;
|
||||||
QMediaPlaylist *playlist() const;
|
QMediaPlaylist *playlist() const;
|
||||||
|
QMediaContent currentMedia() const;
|
||||||
|
|
||||||
State state() const;
|
State state() const;
|
||||||
MediaStatus mediaStatus() const;
|
MediaStatus mediaStatus() const;
|
||||||
@@ -178,6 +181,7 @@ public Q_SLOTS:
|
|||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void mediaChanged(const QMediaContent &media);
|
void mediaChanged(const QMediaContent &media);
|
||||||
|
void currentMediaChanged(const QMediaContent &media);
|
||||||
|
|
||||||
void stateChanged(QMediaPlayer::State newState);
|
void stateChanged(QMediaPlayer::State newState);
|
||||||
void mediaStatusChanged(QMediaPlayer::MediaStatus status);
|
void mediaStatusChanged(QMediaPlayer::MediaStatus status);
|
||||||
@@ -210,6 +214,8 @@ private:
|
|||||||
Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
|
Q_PRIVATE_SLOT(d_func(), void _q_error(int, const QString &))
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_updateMedia(const QMediaContent&))
|
Q_PRIVATE_SLOT(d_func(), void _q_updateMedia(const QMediaContent&))
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_playlistDestroyed())
|
Q_PRIVATE_SLOT(d_func(), void _q_playlistDestroyed())
|
||||||
|
Q_PRIVATE_SLOT(d_func(), void _q_handlePlaylistLoaded())
|
||||||
|
Q_PRIVATE_SLOT(d_func(), void _q_handlePlaylistLoadFailed())
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|||||||
@@ -42,8 +42,8 @@
|
|||||||
#include "qmediaplaylist.h"
|
#include "qmediaplaylist.h"
|
||||||
#include "qmediaplaylist_p.h"
|
#include "qmediaplaylist_p.h"
|
||||||
#include "qmediaplaylistprovider_p.h"
|
#include "qmediaplaylistprovider_p.h"
|
||||||
#include "qlocalmediaplaylistprovider_p.h"
|
|
||||||
#include "qmediaplaylistioplugin_p.h"
|
#include "qmediaplaylistioplugin_p.h"
|
||||||
|
#include "qmedianetworkplaylistprovider_p.h"
|
||||||
#include "qmediaservice.h"
|
#include "qmediaservice.h"
|
||||||
#include "qmediaplaylistcontrol_p.h"
|
#include "qmediaplaylistcontrol_p.h"
|
||||||
#include "qmediaplayercontrol.h"
|
#include "qmediaplayercontrol.h"
|
||||||
@@ -129,7 +129,7 @@ QMediaPlaylist::QMediaPlaylist(QObject *parent)
|
|||||||
Q_D(QMediaPlaylist);
|
Q_D(QMediaPlaylist);
|
||||||
|
|
||||||
d->q_ptr = this;
|
d->q_ptr = this;
|
||||||
d->localPlaylistControl = new QLocalMediaPlaylistControl(this);
|
d->networkPlaylistControl = new QMediaNetworkPlaylistControl(this);
|
||||||
|
|
||||||
setMediaObject(0);
|
setMediaObject(0);
|
||||||
}
|
}
|
||||||
@@ -178,7 +178,7 @@ bool QMediaPlaylist::setMediaObject(QMediaObject *mediaObject)
|
|||||||
newControl = qobject_cast<QMediaPlaylistControl*>(service->requestControl(QMediaPlaylistControl_iid));
|
newControl = qobject_cast<QMediaPlaylistControl*>(service->requestControl(QMediaPlaylistControl_iid));
|
||||||
|
|
||||||
if (!newControl)
|
if (!newControl)
|
||||||
newControl = d->localPlaylistControl;
|
newControl = d->networkPlaylistControl;
|
||||||
|
|
||||||
if (d->control != newControl) {
|
if (d->control != newControl) {
|
||||||
int oldSize = 0;
|
int oldSize = 0;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
#include "qmediaplaylistcontrol_p.h"
|
#include "qmediaplaylistcontrol_p.h"
|
||||||
#include "qmediaplayer.h"
|
#include "qmediaplayer.h"
|
||||||
#include "qmediaplayercontrol.h"
|
#include "qmediaplayercontrol.h"
|
||||||
#include "qlocalmediaplaylistprovider_p.h"
|
#include "qmedianetworkplaylistprovider_p.h"
|
||||||
#include "qmediaobject_p.h"
|
#include "qmediaobject_p.h"
|
||||||
|
|
||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
@@ -86,7 +86,7 @@ public:
|
|||||||
QMediaPlaylistPrivate()
|
QMediaPlaylistPrivate()
|
||||||
:mediaObject(0),
|
:mediaObject(0),
|
||||||
control(0),
|
control(0),
|
||||||
localPlaylistControl(0),
|
networkPlaylistControl(0),
|
||||||
error(QMediaPlaylist::NoError)
|
error(QMediaPlaylist::NoError)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public:
|
|||||||
{
|
{
|
||||||
Q_Q(QMediaPlaylist);
|
Q_Q(QMediaPlaylist);
|
||||||
mediaObject = 0;
|
mediaObject = 0;
|
||||||
if (control != localPlaylistControl)
|
if (control != networkPlaylistControl)
|
||||||
control = 0;
|
control = 0;
|
||||||
q->setMediaObject(0);
|
q->setMediaObject(0);
|
||||||
}
|
}
|
||||||
@@ -115,7 +115,7 @@ public:
|
|||||||
QMediaPlaylistControl *control;
|
QMediaPlaylistControl *control;
|
||||||
QMediaPlaylistProvider *playlist() const { return control->playlistProvider(); }
|
QMediaPlaylistProvider *playlist() const { return control->playlistProvider(); }
|
||||||
|
|
||||||
QMediaPlaylistControl *localPlaylistControl;
|
QMediaPlaylistControl *networkPlaylistControl;
|
||||||
|
|
||||||
bool readItems(QMediaPlaylistReader *reader);
|
bool readItems(QMediaPlaylistReader *reader);
|
||||||
bool writeItems(QMediaPlaylistWriter *writer);
|
bool writeItems(QMediaPlaylistWriter *writer);
|
||||||
@@ -127,14 +127,14 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class QLocalMediaPlaylistControl : public QMediaPlaylistControl
|
class QMediaNetworkPlaylistControl : public QMediaPlaylistControl
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QLocalMediaPlaylistControl(QObject *parent)
|
QMediaNetworkPlaylistControl(QObject *parent)
|
||||||
:QMediaPlaylistControl(parent)
|
:QMediaPlaylistControl(parent)
|
||||||
{
|
{
|
||||||
QMediaPlaylistProvider *playlist = new QLocalMediaPlaylistProvider(this);
|
QMediaPlaylistProvider *playlist = new QMediaNetworkPlaylistProvider(this);
|
||||||
m_navigator = new QMediaPlaylistNavigator(playlist,this);
|
m_navigator = new QMediaPlaylistNavigator(playlist,this);
|
||||||
m_navigator->setPlaybackMode(QMediaPlaylist::Sequential);
|
m_navigator->setPlaybackMode(QMediaPlaylist::Sequential);
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ public:
|
|||||||
connect(m_navigator, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
|
connect(m_navigator, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)), SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~QLocalMediaPlaylistControl() {};
|
virtual ~QMediaNetworkPlaylistControl() {};
|
||||||
|
|
||||||
QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); }
|
QMediaPlaylistProvider* playlistProvider() const { return m_navigator->playlist(); }
|
||||||
bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist)
|
bool setPlaylistProvider(QMediaPlaylistProvider *mediaPlaylist)
|
||||||
|
|||||||
@@ -227,11 +227,12 @@ void tst_QMediaPlayer::testNullService()
|
|||||||
{
|
{
|
||||||
QFETCH_GLOBAL(QMediaContent, mediaContent);
|
QFETCH_GLOBAL(QMediaContent, mediaContent);
|
||||||
|
|
||||||
QSignalSpy spy(&player, SIGNAL(mediaChanged(QMediaContent)));
|
QSignalSpy spy(&player, SIGNAL(currentMediaChanged(QMediaContent)));
|
||||||
QFile file;
|
QFile file;
|
||||||
|
|
||||||
player.setMedia(mediaContent, &file);
|
player.setMedia(mediaContent, &file);
|
||||||
QCOMPARE(player.media(), QMediaContent());
|
QCOMPARE(player.currentMedia(), QMediaContent());
|
||||||
|
QCOMPARE(player.media(), mediaContent);
|
||||||
QCOMPARE(player.mediaStream(), nullDevice);
|
QCOMPARE(player.mediaStream(), nullDevice);
|
||||||
QCOMPARE(spy.count(), 0);
|
QCOMPARE(spy.count(), 0);
|
||||||
} {
|
} {
|
||||||
@@ -297,13 +298,15 @@ void tst_QMediaPlayer::testNullService()
|
|||||||
|
|
||||||
playlist.setCurrentIndex(0);
|
playlist.setCurrentIndex(0);
|
||||||
QCOMPARE(playlist.currentIndex(), 0);
|
QCOMPARE(playlist.currentIndex(), 0);
|
||||||
QCOMPARE(player.media(), QMediaContent());
|
QCOMPARE(player.currentMedia(), QMediaContent());
|
||||||
|
QCOMPARE(player.media().playlist(), &playlist);
|
||||||
QCOMPARE(mediaSpy.count(), 0);
|
QCOMPARE(mediaSpy.count(), 0);
|
||||||
QCOMPARE(statusSpy.count(), 0);
|
QCOMPARE(statusSpy.count(), 0);
|
||||||
|
|
||||||
playlist.next();
|
playlist.next();
|
||||||
QCOMPARE(playlist.currentIndex(), 1);
|
QCOMPARE(playlist.currentIndex(), 1);
|
||||||
QCOMPARE(player.media(), QMediaContent());
|
QCOMPARE(player.currentMedia(), QMediaContent());
|
||||||
|
QCOMPARE(player.media().playlist(), &playlist);
|
||||||
QCOMPARE(mediaSpy.count(), 0);
|
QCOMPARE(mediaSpy.count(), 0);
|
||||||
QCOMPARE(statusSpy.count(), 0);
|
QCOMPARE(statusSpy.count(), 0);
|
||||||
}
|
}
|
||||||
@@ -324,11 +327,11 @@ void tst_QMediaPlayer::testMedia()
|
|||||||
QFETCH_GLOBAL(QMediaContent, mediaContent);
|
QFETCH_GLOBAL(QMediaContent, mediaContent);
|
||||||
|
|
||||||
mockService->setMedia(mediaContent);
|
mockService->setMedia(mediaContent);
|
||||||
QCOMPARE(player->media(), mediaContent);
|
QCOMPARE(player->currentMedia(), mediaContent);
|
||||||
|
|
||||||
QBuffer stream;
|
QBuffer stream;
|
||||||
player->setMedia(mediaContent, &stream);
|
player->setMedia(mediaContent, &stream);
|
||||||
QCOMPARE(player->media(), mediaContent);
|
QCOMPARE(player->currentMedia(), mediaContent);
|
||||||
QCOMPARE((QBuffer*)player->mediaStream(), &stream);
|
QCOMPARE((QBuffer*)player->mediaStream(), &stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,7 +528,7 @@ void tst_QMediaPlayer::testPlay()
|
|||||||
mockService->setState(state);
|
mockService->setState(state);
|
||||||
mockService->setMedia(mediaContent);
|
mockService->setMedia(mediaContent);
|
||||||
QVERIFY(player->state() == state);
|
QVERIFY(player->state() == state);
|
||||||
QVERIFY(player->media() == mediaContent);
|
QVERIFY(player->currentMedia() == mediaContent);
|
||||||
|
|
||||||
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||||
|
|
||||||
@@ -551,7 +554,7 @@ void tst_QMediaPlayer::testPause()
|
|||||||
mockService->setState(state);
|
mockService->setState(state);
|
||||||
mockService->setMedia(mediaContent);
|
mockService->setMedia(mediaContent);
|
||||||
QVERIFY(player->state() == state);
|
QVERIFY(player->state() == state);
|
||||||
QVERIFY(player->media() == mediaContent);
|
QVERIFY(player->currentMedia() == mediaContent);
|
||||||
|
|
||||||
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||||
|
|
||||||
@@ -575,7 +578,7 @@ void tst_QMediaPlayer::testStop()
|
|||||||
mockService->setState(state);
|
mockService->setState(state);
|
||||||
mockService->setMedia(mediaContent);
|
mockService->setMedia(mediaContent);
|
||||||
QVERIFY(player->state() == state);
|
QVERIFY(player->state() == state);
|
||||||
QVERIFY(player->media() == mediaContent);
|
QVERIFY(player->currentMedia() == mediaContent);
|
||||||
|
|
||||||
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
QSignalSpy spy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||||
|
|
||||||
@@ -686,14 +689,15 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
|
|
||||||
QMediaPlaylist *playlist = new QMediaPlaylist;
|
QMediaPlaylist *playlist = new QMediaPlaylist;
|
||||||
player->setPlaylist(playlist);
|
player->setPlaylist(playlist);
|
||||||
|
QCOMPARE(player->media().playlist(), playlist);
|
||||||
|
|
||||||
QSignalSpy stateSpy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
QSignalSpy stateSpy(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||||
QSignalSpy mediaSpy(player, SIGNAL(mediaChanged(QMediaContent)));
|
QSignalSpy mediaSpy(player, SIGNAL(currentMediaChanged(QMediaContent)));
|
||||||
|
|
||||||
// Test the player does nothing with an empty playlist attached.
|
// Test the player does nothing with an empty playlist attached.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
QCOMPARE(stateSpy.count(), 0);
|
QCOMPARE(stateSpy.count(), 0);
|
||||||
QCOMPARE(mediaSpy.count(), 0);
|
QCOMPARE(mediaSpy.count(), 0);
|
||||||
|
|
||||||
@@ -704,28 +708,28 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
|
|
||||||
// Test changing the playlist position, changes the current media, but not the playing state.
|
// Test changing the playlist position, changes the current media, but not the playing state.
|
||||||
playlist->setCurrentIndex(1);
|
playlist->setCurrentIndex(1);
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 0);
|
QCOMPARE(stateSpy.count(), 0);
|
||||||
QCOMPARE(mediaSpy.count(), 1);
|
QCOMPARE(mediaSpy.count(), 1);
|
||||||
|
|
||||||
// Test playing starts with the current media.
|
// Test playing starts with the current media.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 1);
|
QCOMPARE(stateSpy.count(), 1);
|
||||||
QCOMPARE(mediaSpy.count(), 1);
|
QCOMPARE(mediaSpy.count(), 1);
|
||||||
|
|
||||||
// Test pausing doesn't change the current media.
|
// Test pausing doesn't change the current media.
|
||||||
player->pause();
|
player->pause();
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
||||||
QCOMPARE(stateSpy.count(), 2);
|
QCOMPARE(stateSpy.count(), 2);
|
||||||
QCOMPARE(mediaSpy.count(), 1);
|
QCOMPARE(mediaSpy.count(), 1);
|
||||||
|
|
||||||
// Test stopping doesn't change the current media.
|
// Test stopping doesn't change the current media.
|
||||||
player->stop();
|
player->stop();
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 3);
|
QCOMPARE(stateSpy.count(), 3);
|
||||||
QCOMPARE(mediaSpy.count(), 1);
|
QCOMPARE(mediaSpy.count(), 1);
|
||||||
@@ -733,20 +737,20 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
// Test when the player service reaches the end of the current media, the player moves onto
|
// Test when the player service reaches the end of the current media, the player moves onto
|
||||||
// the next item without stopping.
|
// the next item without stopping.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 4);
|
QCOMPARE(stateSpy.count(), 4);
|
||||||
QCOMPARE(mediaSpy.count(), 1);
|
QCOMPARE(mediaSpy.count(), 1);
|
||||||
|
|
||||||
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
||||||
QCOMPARE(player->media(), content2);
|
QCOMPARE(player->currentMedia(), content2);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 4);
|
QCOMPARE(stateSpy.count(), 4);
|
||||||
QCOMPARE(mediaSpy.count(), 2);
|
QCOMPARE(mediaSpy.count(), 2);
|
||||||
|
|
||||||
// Test skipping the current media doesn't change the state.
|
// Test skipping the current media doesn't change the state.
|
||||||
playlist->next();
|
playlist->next();
|
||||||
QCOMPARE(player->media(), content3);
|
QCOMPARE(player->currentMedia(), content3);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 4);
|
QCOMPARE(stateSpy.count(), 4);
|
||||||
QCOMPARE(mediaSpy.count(), 3);
|
QCOMPARE(mediaSpy.count(), 3);
|
||||||
@@ -754,13 +758,13 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
// Test changing the current media while paused doesn't change the state.
|
// Test changing the current media while paused doesn't change the state.
|
||||||
player->pause();
|
player->pause();
|
||||||
mockService->setMediaStatus(QMediaPlayer::BufferedMedia);
|
mockService->setMediaStatus(QMediaPlayer::BufferedMedia);
|
||||||
QCOMPARE(player->media(), content3);
|
QCOMPARE(player->currentMedia(), content3);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
||||||
QCOMPARE(stateSpy.count(), 5);
|
QCOMPARE(stateSpy.count(), 5);
|
||||||
QCOMPARE(mediaSpy.count(), 3);
|
QCOMPARE(mediaSpy.count(), 3);
|
||||||
|
|
||||||
playlist->previous();
|
playlist->previous();
|
||||||
QCOMPARE(player->media(), content2);
|
QCOMPARE(player->currentMedia(), content2);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
QCOMPARE(player->state(), QMediaPlayer::PausedState);
|
||||||
QCOMPARE(stateSpy.count(), 5);
|
QCOMPARE(stateSpy.count(), 5);
|
||||||
QCOMPARE(mediaSpy.count(), 4);
|
QCOMPARE(mediaSpy.count(), 4);
|
||||||
@@ -768,13 +772,13 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
// Test changing the current media while stopped doesn't change the state.
|
// Test changing the current media while stopped doesn't change the state.
|
||||||
player->stop();
|
player->stop();
|
||||||
mockService->setMediaStatus(QMediaPlayer::LoadedMedia);
|
mockService->setMediaStatus(QMediaPlayer::LoadedMedia);
|
||||||
QCOMPARE(player->media(), content2);
|
QCOMPARE(player->currentMedia(), content2);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 6);
|
QCOMPARE(stateSpy.count(), 6);
|
||||||
QCOMPARE(mediaSpy.count(), 4);
|
QCOMPARE(mediaSpy.count(), 4);
|
||||||
|
|
||||||
playlist->next();
|
playlist->next();
|
||||||
QCOMPARE(player->media(), content3);
|
QCOMPARE(player->currentMedia(), content3);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 6);
|
QCOMPARE(stateSpy.count(), 6);
|
||||||
QCOMPARE(mediaSpy.count(), 5);
|
QCOMPARE(mediaSpy.count(), 5);
|
||||||
@@ -782,7 +786,7 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
// Test the player is stopped and the current media cleared when it reaches the end of the last
|
// Test the player is stopped and the current media cleared when it reaches the end of the last
|
||||||
// item in the playlist.
|
// item in the playlist.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->media(), content3);
|
QCOMPARE(player->currentMedia(), content3);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 7);
|
QCOMPARE(stateSpy.count(), 7);
|
||||||
QCOMPARE(mediaSpy.count(), 5);
|
QCOMPARE(mediaSpy.count(), 5);
|
||||||
@@ -790,45 +794,46 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
// Double up the signals to ensure some noise doesn't destabalize things.
|
// Double up the signals to ensure some noise doesn't destabalize things.
|
||||||
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
||||||
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
mockService->setState(QMediaPlayer::StoppedState, QMediaPlayer::EndOfMedia);
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 8);
|
QCOMPARE(stateSpy.count(), 8);
|
||||||
QCOMPARE(mediaSpy.count(), 6);
|
QCOMPARE(mediaSpy.count(), 6);
|
||||||
|
|
||||||
// Test starts playing from the start of the playlist if there is no current media selected.
|
// Test starts playing from the start of the playlist if there is no current media selected.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->media(), content0);
|
QCOMPARE(player->currentMedia(), content0);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 9);
|
QCOMPARE(stateSpy.count(), 9);
|
||||||
QCOMPARE(mediaSpy.count(), 7);
|
// one notification is for playlist and another is for the first media in the playlist
|
||||||
|
QCOMPARE(mediaSpy.count(), 8);
|
||||||
|
|
||||||
// Test deleting the playlist stops the player and clears the media it set.
|
// Test deleting the playlist stops the player and clears the media it set.
|
||||||
delete playlist;
|
delete playlist;
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 10);
|
QCOMPARE(stateSpy.count(), 10);
|
||||||
QCOMPARE(mediaSpy.count(), 8);
|
QCOMPARE(mediaSpy.count(), 9);
|
||||||
|
|
||||||
// Test the player works as normal with the playlist removed.
|
// Test the player works as normal with the playlist removed.
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
QCOMPARE(stateSpy.count(), 10);
|
QCOMPARE(stateSpy.count(), 10);
|
||||||
QCOMPARE(mediaSpy.count(), 8);
|
QCOMPARE(mediaSpy.count(), 9);
|
||||||
|
|
||||||
player->setMedia(content1);
|
player->setMedia(content1);
|
||||||
player->play();
|
player->play();
|
||||||
|
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
QCOMPARE(player->state(), QMediaPlayer::PlayingState);
|
||||||
QCOMPARE(stateSpy.count(), 11);
|
QCOMPARE(stateSpy.count(), 11);
|
||||||
QCOMPARE(mediaSpy.count(), 9);
|
QCOMPARE(mediaSpy.count(), 10);
|
||||||
|
|
||||||
// Test the player can bind to playlist again
|
// Test the player can bind to playlist again
|
||||||
playlist = new QMediaPlaylist;
|
playlist = new QMediaPlaylist;
|
||||||
player->setPlaylist(playlist);
|
player->setPlaylist(playlist);
|
||||||
|
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
|
|
||||||
playlist->addMedia(content0);
|
playlist->addMedia(content0);
|
||||||
@@ -837,7 +842,7 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
playlist->addMedia(content3);
|
playlist->addMedia(content3);
|
||||||
|
|
||||||
playlist->setCurrentIndex(1);
|
playlist->setCurrentIndex(1);
|
||||||
QCOMPARE(player->media(), content1);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
|
|
||||||
// Test attaching the new playlist,
|
// Test attaching the new playlist,
|
||||||
@@ -850,11 +855,11 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
|
|
||||||
player->play();
|
player->play();
|
||||||
player->setPlaylist(playlist2);
|
player->setPlaylist(playlist2);
|
||||||
QCOMPARE(player->media(), playlist2->currentMedia());
|
QCOMPARE(player->currentMedia(), playlist2->currentMedia());
|
||||||
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
QCOMPARE(player->state(), QMediaPlayer::StoppedState);
|
||||||
|
|
||||||
playlist2->setCurrentIndex(1);
|
playlist2->setCurrentIndex(1);
|
||||||
QCOMPARE(player->media(), playlist2->currentMedia());
|
QCOMPARE(player->currentMedia(), playlist2->currentMedia());
|
||||||
|
|
||||||
{
|
{
|
||||||
QMediaPlaylist playlist;
|
QMediaPlaylist playlist;
|
||||||
@@ -863,13 +868,14 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
playlist.addMedia(content3);
|
playlist.addMedia(content3);
|
||||||
playlist.setCurrentIndex(1);
|
playlist.setCurrentIndex(1);
|
||||||
|
|
||||||
|
// playlist resets to the first item
|
||||||
player->setPlaylist(&playlist);
|
player->setPlaylist(&playlist);
|
||||||
QCOMPARE(player->playlist(), &playlist);
|
QCOMPARE(player->playlist(), &playlist);
|
||||||
QCOMPARE(player->media(), content2);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
} //playlist should be detached now
|
} //playlist should be detached now
|
||||||
|
|
||||||
QVERIFY(player->playlist() == 0);
|
QVERIFY(player->playlist() == 0);
|
||||||
QCOMPARE(player->media(), QMediaContent());
|
QCOMPARE(player->currentMedia(), QMediaContent());
|
||||||
|
|
||||||
// Test when the player service encounters an invalid media, the player moves onto
|
// Test when the player service encounters an invalid media, the player moves onto
|
||||||
// the next item without stopping
|
// the next item without stopping
|
||||||
@@ -877,6 +883,7 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
QSignalSpy ss(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
QSignalSpy ss(player, SIGNAL(stateChanged(QMediaPlayer::State)));
|
||||||
QSignalSpy ms(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
|
QSignalSpy ms(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
|
||||||
|
|
||||||
|
// playlist index is set to 0 when it is loaded into media player
|
||||||
player->setPlaylist(playlist);
|
player->setPlaylist(playlist);
|
||||||
player->play();
|
player->play();
|
||||||
QCOMPARE(ss.count(), 1);
|
QCOMPARE(ss.count(), 1);
|
||||||
@@ -888,7 +895,7 @@ void tst_QMediaPlayer::testPlaylist()
|
|||||||
QCOMPARE(ms.count(), 1);
|
QCOMPARE(ms.count(), 1);
|
||||||
|
|
||||||
// NOTE: status should begin transitioning through to BufferedMedia.
|
// NOTE: status should begin transitioning through to BufferedMedia.
|
||||||
QCOMPARE(player->media(), content2);
|
QCOMPARE(player->currentMedia(), content1);
|
||||||
}
|
}
|
||||||
|
|
||||||
delete playlist;
|
delete playlist;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <private/qlocalmediaplaylistprovider_p.h>
|
#include <private/qmedianetworkplaylistprovider_p.h>
|
||||||
#include <private/qmediaplaylistnavigator_p.h>
|
#include <private/qmediaplaylistnavigator_p.h>
|
||||||
|
|
||||||
QT_USE_NAMESPACE
|
QT_USE_NAMESPACE
|
||||||
@@ -84,7 +84,7 @@ void tst_QMediaPlaylistNavigator::cleanup()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::construction()
|
void tst_QMediaPlaylistNavigator::construction()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QCOMPARE(playlist.mediaCount(), 0);
|
QCOMPARE(playlist.mediaCount(), 0);
|
||||||
|
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
@@ -100,7 +100,7 @@ void tst_QMediaPlaylistNavigator::setPlaylist()
|
|||||||
QCOMPARE(navigator.playlist()->media(0), QMediaContent());
|
QCOMPARE(navigator.playlist()->media(0), QMediaContent());
|
||||||
QVERIFY(navigator.playlist()->isReadOnly() );
|
QVERIFY(navigator.playlist()->isReadOnly() );
|
||||||
|
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QCOMPARE(playlist.mediaCount(), 0);
|
QCOMPARE(playlist.mediaCount(), 0);
|
||||||
|
|
||||||
navigator.setPlaylist(&playlist);
|
navigator.setPlaylist(&playlist);
|
||||||
@@ -111,7 +111,7 @@ void tst_QMediaPlaylistNavigator::setPlaylist()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::linearPlayback()
|
void tst_QMediaPlaylistNavigator::linearPlayback()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
|
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Sequential);
|
navigator.setPlaybackMode(QMediaPlaylist::Sequential);
|
||||||
@@ -165,7 +165,7 @@ void tst_QMediaPlaylistNavigator::linearPlayback()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::loopPlayback()
|
void tst_QMediaPlaylistNavigator::loopPlayback()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
|
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Loop);
|
navigator.setPlaybackMode(QMediaPlaylist::Loop);
|
||||||
@@ -216,7 +216,7 @@ void tst_QMediaPlaylistNavigator::loopPlayback()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::currentItemOnce()
|
void tst_QMediaPlaylistNavigator::currentItemOnce()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
|
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
|
navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
|
||||||
@@ -247,7 +247,7 @@ void tst_QMediaPlaylistNavigator::currentItemOnce()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::currentItemInLoop()
|
void tst_QMediaPlaylistNavigator::currentItemInLoop()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
|
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
|
navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
|
||||||
@@ -275,7 +275,7 @@ void tst_QMediaPlaylistNavigator::currentItemInLoop()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::randomPlayback()
|
void tst_QMediaPlaylistNavigator::randomPlayback()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
|
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
@@ -326,7 +326,7 @@ void tst_QMediaPlaylistNavigator::randomPlayback()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testItemAt()
|
void tst_QMediaPlaylistNavigator::testItemAt()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -348,7 +348,7 @@ void tst_QMediaPlaylistNavigator::testItemAt()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testNextIndex()
|
void tst_QMediaPlaylistNavigator::testNextIndex()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -383,7 +383,7 @@ void tst_QMediaPlaylistNavigator::testNextIndex()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testPreviousIndex()
|
void tst_QMediaPlaylistNavigator::testPreviousIndex()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -413,7 +413,7 @@ void tst_QMediaPlaylistNavigator::testPreviousIndex()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testCurrentIndexChangedSignal()
|
void tst_QMediaPlaylistNavigator::testCurrentIndexChangedSignal()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -441,7 +441,7 @@ void tst_QMediaPlaylistNavigator::testCurrentIndexChangedSignal()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testPlaybackModeChangedSignal()
|
void tst_QMediaPlaylistNavigator::testPlaybackModeChangedSignal()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -467,7 +467,7 @@ void tst_QMediaPlaylistNavigator::testPlaybackModeChangedSignal()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testSurroundingItemsChangedSignal()
|
void tst_QMediaPlaylistNavigator::testSurroundingItemsChangedSignal()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
@@ -493,7 +493,7 @@ void tst_QMediaPlaylistNavigator::testSurroundingItemsChangedSignal()
|
|||||||
|
|
||||||
void tst_QMediaPlaylistNavigator::testActivatedSignal()
|
void tst_QMediaPlaylistNavigator::testActivatedSignal()
|
||||||
{
|
{
|
||||||
QLocalMediaPlaylistProvider playlist;
|
QMediaNetworkPlaylistProvider playlist;
|
||||||
QMediaPlaylistNavigator navigator(&playlist);
|
QMediaPlaylistNavigator navigator(&playlist);
|
||||||
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
navigator.setPlaybackMode(QMediaPlaylist::Random);
|
||||||
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
|
||||||
|
|||||||
Reference in New Issue
Block a user