Jim Hodapp has proposed merging 
lp:~phablet-team/kubuntu-packaging/qtmultimedia-opensource-src-playlist-support 
into lp:~kubuntu-packagers/kubuntu-packaging/qtmultimedia-opensource-src.

Commit message:
* Called bind() on playlist definition so that mediaObject is correctly set.
* Added support for declarative playlists.

Requested reviews:
  Kubuntu Packagers (kubuntu-packagers)

For more details, see:
https://code.launchpad.net/~phablet-team/kubuntu-packaging/qtmultimedia-opensource-src-playlist-support/+merge/262229

* Called bind() on playlist definition so that mediaObject is correctly set.
* Added support for declarative playlists.
-- 
Your team Kubuntu Packagers is requested to review the proposed merge of 
lp:~phablet-team/kubuntu-packaging/qtmultimedia-opensource-src-playlist-support 
into lp:~kubuntu-packagers/kubuntu-packaging/qtmultimedia-opensource-src.
=== added file 'debian/patches/add_qdeclarativeplaylist_support.patch'
--- debian/patches/add_qdeclarativeplaylist_support.patch	1970-01-01 00:00:00 +0000
+++ debian/patches/add_qdeclarativeplaylist_support.patch	2015-06-17 14:32:58 +0000
@@ -0,0 +1,1124 @@
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/multimedia.cpp
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/imports/multimedia/multimedia.cpp
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/multimedia.cpp
+@@ -44,6 +44,7 @@
+ #include "qdeclarativeaudio_p.h"
+ #include "qdeclarativeradio_p.h"
+ #include "qdeclarativeradiodata_p.h"
++#include "qdeclarativeplaylist_p.h"
+ #include "qdeclarativecamera_p.h"
+ #include "qdeclarativecamerapreviewprovider_p.h"
+ #include "qdeclarativecameraexposure_p.h"
+@@ -109,6 +110,11 @@ public:
+         qmlRegisterUncreatableType<QDeclarativeCameraViewfinder>(uri, 5, 4, "CameraViewfinder",
+                                 trUtf8("CameraViewfinder is provided by Camera"));
+ 
++        // 5.5 types
++        qmlRegisterRevision<QDeclarativeAudio, 1>(uri, 5, 5);
++        qmlRegisterType<QDeclarativePlaylist>(uri, 5, 5, "Playlist");
++        qmlRegisterType<QDeclarativePlaylistItem>(uri, 5, 5, "PlaylistItem");
++
+         qmlRegisterType<QDeclarativeMediaMetaData>();
+     }
+ 
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/multimedia.pro
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/imports/multimedia/multimedia.pro
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/multimedia.pro
+@@ -3,6 +3,7 @@ QT += qml quick network multimedia-priva
+ HEADERS += \
+         qdeclarativeaudio_p.h \
+         qdeclarativemediametadata_p.h \
++        qdeclarativeplaylist_p.h \
+         qdeclarativeradio_p.h \
+         qdeclarativeradiodata_p.h \
+         qdeclarativecamera_p.h \
+@@ -20,6 +21,7 @@ HEADERS += \
+ SOURCES += \
+         multimedia.cpp \
+         qdeclarativeaudio.cpp \
++        qdeclarativeplaylist.cpp \
+         qdeclarativeradio.cpp \
+         qdeclarativeradiodata.cpp \
+         qdeclarativecamera.cpp \
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeaudio.cpp
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/imports/multimedia/qdeclarativeaudio.cpp
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeaudio.cpp
+@@ -42,6 +42,7 @@
+ #include <qmetadatareadercontrol.h>
+ #include <qmediaavailabilitycontrol.h>
+ 
++#include "qdeclarativeplaylist_p.h"
+ #include "qdeclarativemediametadata_p.h"
+ 
+ #include <QTimerEvent>
+@@ -99,6 +100,7 @@ void QDeclarativeAudio::_q_availabilityC
+ 
+ QDeclarativeAudio::QDeclarativeAudio(QObject *parent)
+     : QObject(parent)
++    , m_playlist(0)
+     , m_autoPlay(false)
+     , m_autoLoad(true)
+     , m_loaded(false)
+@@ -175,6 +177,40 @@ QUrl QDeclarativeAudio::source() const
+     return m_source;
+ }
+ 
++QDeclarativePlaylist *QDeclarativeAudio::playlist() const
++{
++    return m_playlist;
++}
++
++void QDeclarativeAudio::setPlaylist(QDeclarativePlaylist *playlist)
++{
++    if (playlist == m_playlist && m_source.isEmpty())
++        return;
++
++    m_source.clear();
++    m_playlist = playlist;
++    m_content = m_playlist ?
++        QMediaContent(qobject_cast<QMediaPlaylist*>(m_playlist->mediaObject()), QUrl(), false) :
++        QMediaContent();
++    m_loaded = false;
++    if (m_complete && (m_autoLoad || m_content.isNull() || m_autoPlay)) {
++        if (m_error != QMediaPlayer::ServiceMissingError && m_error != QMediaPlayer::NoError) {
++            m_error = QMediaPlayer::NoError;
++            m_errorString = QString();
++
++            emit errorChanged();
++        }
++
++        m_player->setMedia(m_content, 0);
++        m_loaded = true;
++    }
++    else
++        emit playlistChanged();
++
++    if (m_autoPlay)
++        m_player->play();
++}
++
+ bool QDeclarativeAudio::autoPlay() const
+ {
+     return m_autoPlay;
+@@ -192,9 +228,10 @@ void QDeclarativeAudio::setAutoPlay(bool
+ 
+ void QDeclarativeAudio::setSource(const QUrl &url)
+ {
+-    if (url == m_source)
++    if (url == m_source && m_playlist == NULL)
+         return;
+ 
++    m_playlist = NULL;
+     m_source = url;
+     m_content = m_source.isEmpty() ? QMediaContent() : m_source;
+     m_loaded = false;
+@@ -676,8 +713,8 @@ void QDeclarativeAudio::classBegin()
+             this, SLOT(_q_statusChanged()));
+     connect(m_player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+             this, SLOT(_q_statusChanged()));
+-    connect(m_player, SIGNAL(mediaChanged(QMediaContent)),
+-            this, SIGNAL(sourceChanged()));
++    connect(m_player, SIGNAL(mediaChanged(const QMediaContent&)),
++            this, SLOT(_q_mediaChanged(const QMediaContent&)));
+     connect(m_player, SIGNAL(durationChanged(qint64)),
+             this, SIGNAL(durationChanged()));
+     connect(m_player, SIGNAL(positionChanged(qint64)),
+@@ -778,6 +815,15 @@ void QDeclarativeAudio::_q_statusChanged
+     }
+ }
+ 
++void QDeclarativeAudio::_q_mediaChanged(const QMediaContent &media)
++{
++    if (!media.playlist()) {
++        emit sourceChanged();
++    } else {
++        emit playlistChanged();
++    }
++}
++
+ /*!
+     \qmlproperty string QtMultimedia::Audio::errorString
+ 
+@@ -1271,6 +1317,16 @@ void QDeclarativeAudio::_q_statusChanged
+     \qmlproperty url QtMultimedia::MediaPlayer::source
+ 
+     This property holds the source URL of the media.
++
++    Sets the \l playlist property to \c null.
++*/
++
++/*!
++    \qmlproperty variant QtMultimedia::MediaPlayer::playlist
++
++    This property holds the playlist used by the media player.
++
++    Sets the \l source property to the empty string.
+ */
+ 
+ /*!
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeaudio_p.h
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/imports/multimedia/qdeclarativeaudio_p.h
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeaudio_p.h
+@@ -58,6 +58,7 @@ class QMediaPlayerControl;
+ class QMediaService;
+ class QMediaServiceProvider;
+ class QMetaDataReaderControl;
++class QDeclarativePlaylist;
+ class QDeclarativeMediaBaseAnimation;
+ class QDeclarativeMediaMetaData;
+ class QMediaAvailabilityControl;
+@@ -66,6 +67,7 @@ class QDeclarativeAudio : public QObject
+ {
+     Q_OBJECT
+     Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
++    Q_PROPERTY(QDeclarativePlaylist *playlist READ playlist WRITE setPlaylist NOTIFY playlistChanged REVISION 1)
+     Q_PROPERTY(int loops READ loopCount WRITE setLoopCount NOTIFY loopCountChanged)
+     Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged)
+     Q_PROPERTY(bool autoPlay READ autoPlay WRITE setAutoPlay NOTIFY autoPlayChanged)
+@@ -167,6 +169,9 @@ public:
+     QUrl source() const;
+     void setSource(const QUrl &url);
+ 
++    QDeclarativePlaylist *playlist() const;
++    void setPlaylist(QDeclarativePlaylist *playlist);
++
+     int loopCount() const;
+     void setLoopCount(int loopCount);
+ 
+@@ -204,6 +209,8 @@ public Q_SLOTS:
+     void seek(int position);
+ 
+ Q_SIGNALS:
++    Q_REVISION(1) void playlistChanged();
++
+     void sourceChanged();
+     void autoLoadChanged();
+     void loopCountChanged();
+@@ -241,10 +248,12 @@ private Q_SLOTS:
+     void _q_error(QMediaPlayer::Error);
+     void _q_availabilityChanged(QMultimedia::AvailabilityStatus);
+     void _q_statusChanged();
++    void _q_mediaChanged(const QMediaContent&);
+ 
+ private:
+     Q_DISABLE_COPY(QDeclarativeAudio)
+ 
++    QDeclarativePlaylist *m_playlist;
+     bool m_autoPlay;
+     bool m_autoLoad;
+     bool m_loaded;
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeplaylist.cpp
+===================================================================
+--- /dev/null
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeplaylist.cpp
+@@ -0,0 +1,682 @@
++/****************************************************************************
++**
++** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL21$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 or version 3 as published by the Free
++** Software Foundation and appearing in the file LICENSE.LGPLv21 and
++** LICENSE.LGPLv3 included in the packaging of this file. Please review the
++** following information to ensure the GNU Lesser General Public License
++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++// FIXME(loicm)
++// - Doc import statement still indicates 5.4.
++// - Add unit tests.
++
++#include "qdeclarativeplaylist_p.h"
++
++QT_BEGIN_NAMESPACE
++
++/*!
++    \qmltype PlaylistItem
++    \instantiates QDeclarativePlaylistItem
++    \since 5.5
++
++    \inqmlmodule QtMultimedia
++    \ingroup multimedia_qml
++    \ingroup multimedia_audio_qml
++    \brief Defines an item in a Playlist.
++
++    \sa Playlist
++*/
++
++/*!
++    \qmlproperty url QtMultimedia::PlaylistItem::source
++
++    This property holds the source URL of the item.
++
++    \sa Playlist
++*/
++QDeclarativePlaylistItem::QDeclarativePlaylistItem(QObject *parent)
++    : QObject(parent)
++{
++}
++
++QUrl QDeclarativePlaylistItem::source() const
++{
++    return m_source;
++}
++
++void QDeclarativePlaylistItem::setSource(const QUrl &source)
++{
++    m_source = source;
++}
++
++/*!
++    \qmltype Playlist
++    \instantiates QDeclarativePlaylist
++    \since 5.5
++    \brief Add playlist support to a media player.
++
++    \inqmlmodule QtMultimedia
++    \ingroup multimedia_qml
++    \ingroup multimedia_audio_qml
++
++    To use this element, you will need to import the module with the following line:
++    \code
++    import QtMultimedia 5.5
++    \endcode
++
++    The Playlist element provides playlist support to the MediaPlayer element (also exposed as
++    Audio). It can be used as a data source for view elements (such as ListView) and other elements
++    that interact with model data (such as Repeater).
++
++    \qml
++    import QtQuick 2.0
++    import QtMultimedia 5.5
++
++    Item {
++        width: 400;
++        height: 300;
++
++        Audio {
++            id: player;
++            playlist: Playlist {
++                id: playlist
++                PlaylistItem { source: "song1.ogg"; }
++                PlaylistItem { source: "song2.ogg"; }
++                PlaylistItem { source: "song3.ogg"; }
++            }
++        }
++
++        ListView {
++            model: playlist;
++            delegate: Text {
++                font.pixelSize: 16;
++                text: source;
++            }
++        }
++
++        MouseArea {
++            anchors.fill: parent;
++            onPressed: {
++                if (player.playbackState != Audio.PlayingState) {
++                    player.play();
++                } else {
++                    player.pause();
++                }
++            }
++        }
++    }
++    \endqml
++
++    \sa Audio
++*/
++
++void QDeclarativePlaylist::_q_mediaAboutToBeInserted(int start, int end)
++{
++    emit mediaAboutToBeInserted(start, end);
++
++    beginInsertRows(QModelIndex(), start, end);
++}
++
++void QDeclarativePlaylist::_q_mediaInserted(int start, int end)
++{
++    endInsertRows();
++
++    emit mediaCountChanged();
++    if (m_empty) {
++        m_empty = false;
++        emit emptyChanged();
++    }
++
++    emit mediaInserted(start, end);
++}
++
++void QDeclarativePlaylist::_q_mediaAboutToBeRemoved(int start, int end)
++{
++    emit mediaAboutToBeRemoved(start, end);
++
++    beginRemoveRows(QModelIndex(), start, end);
++}
++
++void QDeclarativePlaylist::_q_mediaRemoved(int start, int end)
++{
++    endRemoveRows();
++
++    emit mediaCountChanged();
++    if (!m_empty && m_playlist->mediaCount() == 0) {
++        m_empty = true;
++        emit emptyChanged();
++    }
++
++    emit mediaRemoved(start, end);
++}
++
++void QDeclarativePlaylist::_q_mediaChanged(int start, int end)
++{
++    emit dataChanged(createIndex(start, 0), createIndex(end, 0));
++    emit mediaChanged(start, end);
++}
++
++void QDeclarativePlaylist::_q_loadFailed()
++{
++    m_error = m_playlist->error();
++    m_errorString = m_playlist->errorString();
++
++    emit error(Error(m_error), m_errorString);
++    emit errorChanged();
++    emit loadFailed();
++}
++
++QDeclarativePlaylist::QDeclarativePlaylist(QObject *parent)
++    : QAbstractListModel(parent)
++    , m_playlist(0)
++    , m_currentIndex(-1)
++    , m_error(QMediaPlaylist::NoError)
++    , m_playbackMode(QMediaPlaylist::Sequential)
++    , m_empty(true)
++    , m_readOnly(false)
++    , m_componentComplete(false)
++{
++}
++
++QDeclarativePlaylist::~QDeclarativePlaylist()
++{
++    delete m_playlist;
++}
++
++/*!
++    \qmlproperty enumeration QtMultimedia::Playlist::playbackMode
++
++    This property holds the order in which items in the playlist are played.
++
++    \table
++    \header \li Value \li Description
++    \row \li CurrentItemOnce
++        \li The current item is played only once.
++    \row \li CurrentItemInLoop
++        \li The current item is played repeatedly in a loop.
++    \row \li Sequential
++        \li Playback starts from the current and moves through each successive item until the last
++           is reached and then stops. The next item is a null item when the last one is currently
++           playing.
++    \row \li Loop
++        \li Playback restarts at the first item after the last has finished playing.
++    \row \li Random
++        \li Play items in random order.
++    \endtable
++ */
++QDeclarativePlaylist::PlaybackMode QDeclarativePlaylist::playbackMode() const
++{
++    return m_componentComplete ?
++        PlaybackMode(m_playlist->playbackMode()) : PlaybackMode(m_playbackMode);
++}
++
++void QDeclarativePlaylist::setPlaybackMode(PlaybackMode mode)
++{
++    if (playbackMode() == mode)
++        return;
++
++    if (m_componentComplete) {
++        m_playlist->setPlaybackMode(QMediaPlaylist::PlaybackMode(mode));
++    } else {
++        m_playbackMode = QMediaPlaylist::PlaybackMode(mode);
++        emit playbackModeChanged();
++    }
++}
++
++/*!
++    \qmlproperty url QtMultimedia::Playlist::currentsource
++
++    This property holds the source URL of the current item in the playlist.
++ */
++QUrl QDeclarativePlaylist::currentSource() const
++{
++    return m_playlist->currentMedia().canonicalUrl();
++}
++
++/*!
++    \qmlproperty int QtMultimedia::Playlist::currentIndex
++
++    This property holds the position of the current item in the playlist.
++ */
++int QDeclarativePlaylist::currentIndex() const
++{
++    return m_componentComplete ? m_playlist->currentIndex() : m_currentIndex;
++}
++
++void QDeclarativePlaylist::setCurrentIndex(int index)
++{
++    if (currentIndex() == index)
++        return;
++
++    if (m_componentComplete) {
++        m_playlist->setCurrentIndex(index);
++    } else {
++        m_currentIndex = index;
++        emit currentIndexChanged();
++    }
++}
++
++/*!
++    \qmlproperty int QtMultimedia::Playlist::mediaCount
++
++    This property holds the number of items in the playlist.
++ */
++int QDeclarativePlaylist::mediaCount() const
++{
++    return m_playlist->mediaCount();
++}
++
++/*!
++    \qmlproperty bool QtMultimedia::Playlist::empty
++
++    This property indicates if the playlist contains no items.
++ */
++bool QDeclarativePlaylist::empty() const
++{
++    return m_empty;
++}
++
++/*!
++    \qmlproperty bool QtMultimedia::Playlist::empty
++
++    This property indicates if the playlist can be modified.
++ */
++bool QDeclarativePlaylist::readOnly() const
++{
++    // There's no signal to tell whether or not the read only state changed, so we consider it fixed
++    // after its initial retrieval in componentComplete().
++    return m_readOnly;
++}
++
++/*!
++    \qmlproperty enumeration QtMultimedia::Playlist::error
++
++    This property holds the error condition of the playlist.
++
++    \table
++    \header \li Value \li Description
++    \row \li NoError
++        \li No errors
++    \row \li FormatError
++        \li Format error.
++    \row \li FormatNotSupportedError
++        \li Format not supported.
++    \row \li NetworkError
++        \li Network error.
++    \row \li AccessDeniedError
++        \li Access denied error.
++    \endtable
++ */
++QDeclarativePlaylist::Error QDeclarativePlaylist::error() const
++{
++    return Error(m_error);
++}
++
++/*!
++    \qmlproperty string QtMultimedia::Playlist::errorString
++
++    This property holds a string describing the current error condition of the playlist.
++*/
++QString QDeclarativePlaylist::errorString() const
++{
++    return m_errorString;
++}
++
++QQmlListProperty<QDeclarativePlaylistItem> QDeclarativePlaylist::defaultItems()
++{
++    return QQmlListProperty<QDeclarativePlaylistItem>(this, m_defaultItems);
++}
++
++/*!
++    \qmlmethod url QtMultimedia::Playlist::source(index)
++
++    Returns the source URL of the item at the given \a index in the playlist.
++*/
++QUrl QDeclarativePlaylist::source(int index)
++{
++    if (!m_componentComplete)
++        return QUrl();
++
++    return m_playlist->media(index).canonicalUrl();
++}
++
++/*!
++    \qmlmethod int QtMultimedia::Playlist::nextIndex(steps)
++
++    Returns the index of the item in the playlist which would be current after calling next()
++    \a steps times.
++
++    Returned value depends on the size of the playlist, the current position and the playback mode.
++
++    \sa playbackMode, previousIndex()
++*/
++int QDeclarativePlaylist::nextIndex(int steps)
++{
++    if (!m_componentComplete)
++        return -1;
++
++    return m_playlist->nextIndex(steps);
++}
++
++/*!
++    \qmlmethod int QtMultimedia::Playlist::previousIndex(steps)
++
++    Returns the index of the item in the playlist which would be current after calling previous()
++    \a steps times.
++
++    Returned value depends on the size of the playlist, the current position and the playback mode.
++
++    \sa playbackMode, nextIndex()
++*/
++int QDeclarativePlaylist::previousIndex(int steps)
++{
++    if (!m_componentComplete)
++        return -1;
++
++    return m_playlist->previousIndex(steps);
++}
++
++/*!
++    \qmlmethod QtMultimedia::Playlist::next()
++
++    Advances to the next item in the playlist.
++*/
++void QDeclarativePlaylist::next()
++{
++    if (!m_componentComplete)
++        return;
++
++    m_playlist->next();
++}
++
++/*!
++    \qmlmethod QtMultimedia::Playlist::previous()
++
++    Returns to the previous item in the playlist.
++*/
++void QDeclarativePlaylist::previous()
++{
++    if (!m_componentComplete)
++        return;
++
++    m_playlist->previous();
++}
++
++/*!
++    \qmlmethod QtMultimedia::Playlist::shuffle()
++
++    Shuffles items in the playlist.
++*/
++void QDeclarativePlaylist::shuffle()
++{
++    if (!m_componentComplete)
++        return;
++
++    m_playlist->shuffle();
++}
++
++/*!
++    \qmlmethod QtMultimedia::Playlist::load(location, format)
++
++    Loads a playlist from the given \a location. If \a format is specified, it is used, otherwise
++    the format is guessed from the location name and the data.
++
++    New items are appended to the playlist.
++
++    \c onloaded() is emitted if the playlist loads successfully, otherwise \c onLoadFailed() is
++    emitted with \l error and \l errorString defined accordingly.
++*/
++void QDeclarativePlaylist::load(const QUrl &location, const QString &format)
++{
++    if (!m_componentComplete)
++        return;
++
++    m_error = QMediaPlaylist::NoError;
++    m_errorString = QString();
++    emit errorChanged();
++    m_playlist->load(location, format.toLatin1().constData());
++}
++
++/*!
++    \qmlmethod bool QtMultimedia::Playlist::save(location, format)
++
++    Saves the playlist to the given \a location. If \a format is specified, it is used, otherwise
++    the format is guessed from the location name.
++
++    Returns true if the playlist is saved successfully.
++*/
++bool QDeclarativePlaylist::save(const QUrl &location, const QString &format)
++{
++    if (!m_componentComplete)
++        return false;
++
++    return m_playlist->save(location, format.toLatin1().constData());
++}
++
++/*!
++    \qmlmethod bool QtMultimedia::Playlist::addSource(source)
++
++    Appends the \a source URL to the playlist.
++
++    Returns true if the \a source is added successfully.
++*/
++bool QDeclarativePlaylist::addSource(const QUrl &source)
++{
++    if (!m_componentComplete)
++        return false;
++
++    return m_playlist->addMedia(QMediaContent(source));
++}
++
++/*!
++    \qmlmethod bool QtMultimedia::Playlist::insertSource(index, source)
++
++    Inserts the \a source URL to the playlist at the given \a index.
++
++    Returns true if the \a source is added successfully.
++*/
++bool QDeclarativePlaylist::insertSource(int index, const QUrl &source)
++{
++    if (!m_componentComplete)
++        return false;
++
++    return m_playlist->insertMedia(index, QMediaContent(source));
++}
++
++/*!
++    \qmlmethod bool QtMultimedia::Playlist::removeSource(index)
++
++    Removed the item at the given \a index from the playlist.
++
++    Returns true if the \a source is removed successfully.
++*/
++bool QDeclarativePlaylist::removeSource(int index)
++{
++    if (!m_componentComplete)
++        return false;
++
++    return m_playlist->removeMedia(index);
++}
++
++/*!
++    \qmlmethod bool QtMultimedia::Playlist::clear()
++
++    Removes all the items from the playlist.
++
++    Returns true if the operation is successful.
++*/
++bool QDeclarativePlaylist::clear()
++{
++    if (!m_componentComplete)
++        return false;
++
++    return m_playlist->clear();
++}
++
++int QDeclarativePlaylist::rowCount(const QModelIndex &parent) const
++{
++    if (!m_componentComplete || parent.isValid())
++        return 0;
++
++    return m_playlist->mediaCount();
++}
++
++QVariant QDeclarativePlaylist::data(const QModelIndex &index, int role) const
++{
++    Q_UNUSED(role);
++
++    if (!m_componentComplete || !index.isValid())
++        return QVariant();
++
++    return m_playlist->media(index.row()).canonicalUrl();
++}
++
++QHash<int, QByteArray> QDeclarativePlaylist::roleNames() const
++{
++    QHash<int, QByteArray> roleNames;
++    roleNames[SourceRole] = "source";
++    return roleNames;
++}
++
++void QDeclarativePlaylist::classBegin()
++{
++    m_playlist = new QMediaPlaylist(this);
++
++    connect(m_playlist, SIGNAL(currentIndexChanged(int)),
++            this, SIGNAL(currentIndexChanged()));
++    connect(m_playlist, SIGNAL(playbackModeChanged(QMediaPlaylist::PlaybackMode)),
++            this, SIGNAL(playbackModeChanged()));
++    connect(m_playlist, SIGNAL(currentMediaChanged(QMediaContent)),
++            this, SIGNAL(currentSourceChanged()));
++    connect(m_playlist, SIGNAL(mediaAboutToBeInserted(int,int)),
++            this, SLOT(_q_mediaAboutToBeInserted(int,int)));
++    connect(m_playlist, SIGNAL(mediaInserted(int,int)),
++            this, SLOT(_q_mediaInserted(int,int)));
++    connect(m_playlist, SIGNAL(mediaAboutToBeRemoved(int,int)),
++            this, SLOT(_q_mediaAboutToBeRemoved(int,int)));
++    connect(m_playlist, SIGNAL(mediaRemoved(int,int)),
++            this, SLOT(_q_mediaRemoved(int,int)));
++    connect(m_playlist, SIGNAL(mediaChanged(int,int)),
++            this, SLOT(_q_mediaChanged(int,int)));
++    connect(m_playlist, SIGNAL(loaded()),
++            this, SIGNAL(loaded()));
++    connect(m_playlist, SIGNAL(loadFailed()),
++            this, SLOT(_q_loadFailed()));
++
++    emit mediaObjectChanged();
++}
++
++void QDeclarativePlaylist::componentComplete()
++{
++    // Insert default items.
++    QList<QMediaContent> medias;
++    const int defaultItemsSize = m_defaultItems.size();
++    medias.reserve(defaultItemsSize);
++    for (int i = 0; i < defaultItemsSize; ++i) {
++        medias.append(QMediaContent(m_defaultItems[i]->source()));
++    }
++    m_playlist->addMedia(medias);
++    m_defaultItems.clear();
++
++    // Set properties potentially defined by user.
++    m_playlist->setPlaybackMode(m_playbackMode);
++    m_playlist->setCurrentIndex(m_currentIndex);
++
++    if (m_playlist->isReadOnly()) {
++        m_readOnly = true;
++        emit readOnlyChanged();
++    }
++
++    m_componentComplete = true;
++}
++
++/*!
++    \qmlsignal QtMultimedia::Audio::mediaAboutToBeInserted(start, end)
++
++    This signal is emitted when items are to be inserted into the playlist at \a start and ending at
++    \a end.
++
++    The corresponding handler is \c onMediaAboutToBeInserted.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::mediaInserted(start, end)
++
++    This signal is emitted after media has been inserted into the playlist. The new items are those
++    between \a start and \a end inclusive.
++
++    The corresponding handler is \c onMediaInserted.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::mediaAboutToBeRemoved(start, end)
++
++    This signal emitted when items are to be deleted from the playlist at \a start and ending at
++    \a end.
++
++    The corresponding handler is \c onMediaAboutToBeRemoved.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::mediaRemoved(start, end)
++
++    This signal is emitted after media has been removed from the playlist. The removed items are
++    those between \a start and \a end inclusive.
++
++    The corresponding handler is \c onMediaRemoved.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::mediaChanged(start, end)
++
++    This signal is emitted after media has been changed in the playlist between \a start and
++    \a end positions inclusive.
++
++    The corresponding handler is \c onMediaChanged.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::loaded()
++
++    This signal is emitted when the playlist loading succeeded.
++
++    The corresponding handler is \c onLoaded.
++*/
++
++/*!
++    \qmlsignal QtMultimedia::Audio::loadFailed()
++
++    This signal is emitted when the playlist loading failed. \l error and \l errorString can be
++    checked for more information on the failure.
++
++    The corresponding handler is \c onLoadFailed.
++*/
++
++QT_END_NAMESPACE
++
++#include "moc_qdeclarativeplaylist_p.cpp"
+Index: qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeplaylist_p.h
+===================================================================
+--- /dev/null
++++ qtmultimedia-opensource-src-5.4.2/src/imports/multimedia/qdeclarativeplaylist_p.h
+@@ -0,0 +1,195 @@
++/****************************************************************************
++**
++** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
++** Contact: http://www.qt-project.org/legal
++**
++** This file is part of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL21$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and Digia. For licensing terms and
++** conditions see http://qt.digia.com/licensing. For further information
++** use the contact form at http://qt.digia.com/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 or version 3 as published by the Free
++** Software Foundation and appearing in the file LICENSE.LGPLv21 and
++** LICENSE.LGPLv3 included in the packaging of this file. Please review the
++** following information to ensure the GNU Lesser General Public License
++** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
++** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Digia gives you certain additional
++** rights. These rights are described in the Digia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#ifndef QDECLARATIVEPLAYLIST_P_H
++#define QDECLARATIVEPLAYLIST_P_H
++
++//
++//  W A R N I N G
++//  -------------
++//
++// This file is not part of the Qt API.  It exists for the convenience
++// of other Qt classes.  This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#include <QtCore/QAbstractListModel>
++#include <QtQml/qqmlparserstatus.h>
++#include <QtQml/qqml.h>
++
++#include <qmediaplaylist.h>
++
++QT_BEGIN_NAMESPACE
++
++class QDeclarativePlaylistItem : public QObject
++{
++    Q_OBJECT
++    Q_PROPERTY(QUrl source READ source WRITE setSource)
++
++public:
++    QDeclarativePlaylistItem(QObject *parent = 0);
++
++    QUrl source() const;
++    void setSource(const QUrl &source);
++
++private:
++    QUrl m_source;
++};
++
++class QDeclarativePlaylist : public QAbstractListModel, public QQmlParserStatus
++{
++    Q_OBJECT
++    Q_PROPERTY(PlaybackMode playbackMode READ playbackMode WRITE setPlaybackMode NOTIFY playbackModeChanged)
++    Q_PROPERTY(QUrl currentSource READ currentSource NOTIFY currentSourceChanged)
++    Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
++    Q_PROPERTY(int mediaCount READ mediaCount NOTIFY mediaCountChanged)
++    Q_PROPERTY(bool empty READ empty NOTIFY emptyChanged)
++    Q_PROPERTY(bool readOnly READ readOnly NOTIFY readOnlyChanged)
++    Q_PROPERTY(Error error READ error NOTIFY errorChanged)
++    Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
++    Q_PROPERTY(QQmlListProperty<QDeclarativePlaylistItem> defaultItems READ defaultItems DESIGNABLE false)
++    Q_PROPERTY(QObject *mediaObject READ mediaObject NOTIFY mediaObjectChanged SCRIPTABLE false DESIGNABLE false)
++    Q_ENUMS(PlaybackMode)
++    Q_ENUMS(Error)
++    Q_INTERFACES(QQmlParserStatus)
++    Q_CLASSINFO("DefaultProperty", "defaultItems")
++
++public:
++    enum PlaybackMode
++    {
++        CurrentItemOnce = QMediaPlaylist::CurrentItemOnce,
++        CurrentItemInLoop = QMediaPlaylist::CurrentItemInLoop,
++        Sequential = QMediaPlaylist::Sequential,
++        Loop = QMediaPlaylist::Loop,
++        Random = QMediaPlaylist::Random
++    };
++    enum Error
++    {
++        NoError = QMediaPlaylist::NoError,
++        FormatError = QMediaPlaylist::FormatError,
++        FormatNotSupportedError = QMediaPlaylist::FormatNotSupportedError,
++        NetworkError = QMediaPlaylist::NetworkError,
++        AccessDeniedError = QMediaPlaylist::AccessDeniedError
++    };
++    enum Roles
++    {
++        SourceRole = Qt::UserRole + 1
++    };
++
++    QDeclarativePlaylist(QObject *parent = 0);
++    ~QDeclarativePlaylist();
++
++    PlaybackMode playbackMode() const;
++    void setPlaybackMode(PlaybackMode playbackMode);
++    QUrl currentSource() const;
++    int currentIndex() const;
++    void setCurrentIndex(int currentIndex);
++    int mediaCount() const;
++    bool empty() const;
++    bool readOnly() const;
++    Error error() const;
++    QString errorString() const;
++    QQmlListProperty<QDeclarativePlaylistItem> defaultItems();
++    QObject *mediaObject() const { return m_playlist; }
++
++    int rowCount(const QModelIndex &parent = QModelIndex()) const;
++    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
++    QHash<int, QByteArray> roleNames() const;
++
++    void classBegin();
++    void componentComplete();
++
++public Q_SLOTS:
++    QUrl source(int index);
++    int nextIndex(int steps = 1);
++    int previousIndex(int steps = 1);
++    void next();
++    void previous();
++    void shuffle();
++    void load(const QUrl &location, const QString &format = QString());
++    bool save(const QUrl &location, const QString &format = QString());
++    bool addSource(const QUrl &source);
++    bool insertSource(int index, const QUrl &source);
++    bool removeSource(int index);
++    bool clear();
++
++Q_SIGNALS:
++    void playbackModeChanged();
++    void currentSourceChanged();
++    void currentIndexChanged();
++    void mediaCountChanged();
++    void emptyChanged();
++    void readOnlyChanged();
++    void errorChanged();
++    void mediaObjectChanged();
++
++    void mediaAboutToBeInserted(int start, int end);
++    void mediaInserted(int start, int end);
++    void mediaAboutToBeRemoved(int start, int end);
++    void mediaRemoved(int start, int end);
++    void mediaChanged(int start, int end);
++    void loaded();
++    void loadFailed();
++
++    void error(QDeclarativePlaylist::Error error, const QString &errorString);
++
++private Q_SLOTS:
++    void _q_mediaAboutToBeInserted(int start, int end);
++    void _q_mediaInserted(int start, int end);
++    void _q_mediaAboutToBeRemoved(int start, int end);
++    void _q_mediaRemoved(int start, int end);
++    void _q_mediaChanged(int start, int end);
++    void _q_loadFailed();
++
++private:
++    Q_DISABLE_COPY(QDeclarativePlaylist)
++
++    QMediaPlaylist *m_playlist;
++    QList<QDeclarativePlaylistItem*> m_defaultItems;
++    int m_currentIndex;
++    QString m_errorString;
++    QMediaPlaylist::Error m_error;
++    QMediaPlaylist::PlaybackMode m_playbackMode;
++    bool m_empty;
++    bool m_readOnly;
++    bool m_componentComplete;
++};
++
++QT_END_NAMESPACE
++
++QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePlaylistItem))
++QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePlaylist))
++
++#endif
+Index: qtmultimedia-opensource-src-5.4.2/src/multimedia/doc/src/qtmultimedia-index.qdoc
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/multimedia/doc/src/qtmultimedia-index.qdoc
++++ qtmultimedia-opensource-src-5.4.2/src/multimedia/doc/src/qtmultimedia-index.qdoc
+@@ -79,6 +79,9 @@
+      \li \l {QtMultimedia::Audio}{Audio}
+      \li Add audio playback functionality to a scene
+     \row
++     \li \l {QtMultimedia::Playlist}{Playlist}
++     \li Add playlist functionality
++    \row
+      \li \l {QtMultimedia::Camera}{Camera}
+      \li Access camera viewfinder frames
+     \row
+@@ -111,6 +114,9 @@
+      \li QMediaPlayer
+      \li Playback media from a source.
+     \row
++     \li QMediaPlaylist
++     \li List of media to be played.
++    \row
+      \li QRadioTuner
+      \li Access radio device.
+     \row

=== added file 'debian/patches/call_bind_when_playlist_is_set.patch'
--- debian/patches/call_bind_when_playlist_is_set.patch	1970-01-01 00:00:00 +0000
+++ debian/patches/call_bind_when_playlist_is_set.patch	2015-06-17 14:32:58 +0000
@@ -0,0 +1,14 @@
+Index: qtmultimedia-opensource-src-5.4.2/src/multimedia/playback/qmediaplayer.cpp
+===================================================================
+--- qtmultimedia-opensource-src-5.4.2.orig/src/multimedia/playback/qmediaplayer.cpp
++++ qtmultimedia-opensource-src-5.4.2/src/multimedia/playback/qmediaplayer.cpp
+@@ -575,6 +575,9 @@ QMediaContent QMediaPlayer::currentMedia
+ 
+ void QMediaPlayer::setPlaylist(QMediaPlaylist *playlist)
+ {
++    // Make sure that QMediaPlaylist::setMediaObject gets called with new QMediaPlaylist instance
++    bind(playlist);
++
+     QMediaContent m(playlist, QUrl(), false);
+     setMedia(m);
+ }

=== modified file 'debian/patches/series'
--- debian/patches/series	2015-04-21 05:22:27 +0000
+++ debian/patches/series	2015-06-17 14:32:58 +0000
@@ -2,3 +2,5 @@
 skip_failing_tests.patch
 adding_media_role_property.patch
 qgstreamercapturesession_avoid_race_eos.patch
+add_qdeclarativeplaylist_support.patch
+call_bind_when_playlist_is_set.patch

-- 
kubuntu-devel mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/kubuntu-devel

Reply via email to