qtmobility/src/multimedia/qmediaimageviewerservice.cpp
changeset 1 2b40d63a9c3d
child 4 90517678cc4f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qtmobility/src/multimedia/qmediaimageviewerservice.cpp	Fri Apr 16 15:51:22 2010 +0300
@@ -0,0 +1,472 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qmediaimageviewerservice_p.h>
+
+#include <qmediacontrol_p.h>
+#include <qmediaservice_p.h>
+
+#include <qmediacontent.h>
+#include <qmediaresource.h>
+#include <qvideooutputcontrol.h>
+#include <qmediaobject_p.h>
+#include <qvideorenderercontrol.h>
+#include <qvideowidgetcontrol.h>
+
+#include <QtCore/qdebug.h>
+
+#include <QtCore/qurl.h>
+#include <QtGui/qimagereader.h>
+#include <QtGui/qpainter.h>
+
+#include <QtNetwork/qnetworkaccessmanager.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtNetwork/qnetworkrequest.h>
+
+#include <QtMultimedia/qabstractvideosurface.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+QTM_BEGIN_NAMESPACE
+
+class QMediaImageViewerServicePrivate : public QMediaServicePrivate
+{
+public:
+    QMediaImageViewerServicePrivate()
+        : viewerControl(0)
+        , outputControl(0)
+        , rendererControl(0)
+        , network(0)
+        , internalNetwork(0)
+    {
+    }
+
+    bool load(QIODevice *device);
+    void clear();
+    void _q_outputChanged(QVideoOutputControl::Output output);
+
+    QMediaImageViewerControl *viewerControl;
+    QMediaImageViewerOutputControl *outputControl;
+    QMediaImageViewerRenderer *rendererControl;
+    QNetworkAccessManager *network;
+    QNetworkAccessManager *internalNetwork;
+    QImage m_image;
+};
+
+
+QMediaImageViewerRenderer::QMediaImageViewerRenderer(QObject *parent)
+    : QVideoRendererControl(parent)
+    , m_surface(0)
+{
+}
+
+QMediaImageViewerRenderer::~QMediaImageViewerRenderer()
+{
+    if (m_surface)
+        m_surface->stop();
+}
+
+QAbstractVideoSurface *QMediaImageViewerRenderer::surface() const
+{
+    return m_surface;
+}
+
+void QMediaImageViewerRenderer::setSurface(QAbstractVideoSurface *surface)
+{
+    if (m_surface)
+        m_surface->stop();
+
+    m_surface = surface;
+
+    if (m_surface && !m_image.isNull()) {
+        QVideoSurfaceFormat format(
+                m_image.size(), QVideoFrame::pixelFormatFromImageFormat(m_image.format()));
+
+        if (surface->start(format))
+            surface->present(QVideoFrame(m_image));
+    }
+}
+
+void QMediaImageViewerRenderer::showImage(const QImage &image)
+{
+    m_image = image;
+
+    if (m_surface) {
+        if (m_image.isNull()) {
+            m_surface->stop();
+        } else {
+            QVideoSurfaceFormat format(
+                    image.size(), QVideoFrame::pixelFormatFromImageFormat(image.format()));
+
+            if (m_surface->start(format))
+                m_surface->present(QVideoFrame(image));
+        }
+    }
+}
+
+QMediaImageViewerOutputControl::QMediaImageViewerOutputControl(QObject *parent)
+    : QVideoOutputControl(parent)
+    , m_output(NoOutput)
+{
+}
+
+QList<QVideoOutputControl::Output> QMediaImageViewerOutputControl::availableOutputs() const
+{
+    return QList<Output>()
+            << RendererOutput;
+}
+
+void QMediaImageViewerOutputControl::setOutput(Output output)
+{
+    switch (output) {
+    case RendererOutput:
+        emit m_output = output;
+        break;
+    default:
+        m_output = NoOutput;
+    }
+    emit outputChanged(m_output);
+}
+
+bool QMediaImageViewerServicePrivate::load(QIODevice *device)
+{
+    QImageReader reader(device);
+
+    if (!reader.canRead()) {
+        m_image = QImage();
+    } else {
+        m_image = reader.read();
+    }
+
+    if (outputControl->output() == QVideoOutputControl::RendererOutput)
+        rendererControl->showImage(m_image);
+
+    return !m_image.isNull();
+}
+
+void QMediaImageViewerServicePrivate::clear()
+{
+    m_image = QImage();
+
+    if (outputControl->output() == QVideoOutputControl::RendererOutput)
+        rendererControl->showImage(m_image);
+}
+
+void QMediaImageViewerServicePrivate::_q_outputChanged(QVideoOutputControl::Output output)
+{
+    if (output != QVideoOutputControl::RendererOutput)
+        rendererControl->showImage(QImage());
+
+    if (output == QVideoOutputControl::RendererOutput)
+        rendererControl->showImage(m_image);
+}
+
+/*!
+    \class QMediaImageViewerService
+    \internal
+*/
+
+/*!
+*/
+QMediaImageViewerService::QMediaImageViewerService(QObject *parent)
+    : QMediaService(*new QMediaImageViewerServicePrivate, parent)
+{
+    Q_D(QMediaImageViewerService);
+
+    d->viewerControl = new QMediaImageViewerControl(this);
+    d->outputControl = new QMediaImageViewerOutputControl;
+    connect(d->outputControl, SIGNAL(outputChanged(QVideoOutputControl::Output)),
+            SLOT(_q_outputChanged(QVideoOutputControl::Output)));
+
+    d->rendererControl = new QMediaImageViewerRenderer;
+}
+
+/*!
+*/
+QMediaImageViewerService::~QMediaImageViewerService()
+{
+    Q_D(QMediaImageViewerService);
+
+    delete d->rendererControl;
+    delete d->outputControl;
+    delete d->viewerControl;
+}
+
+/*!
+*/
+QMediaControl *QMediaImageViewerService::control(const char *name) const
+{
+    Q_D(const QMediaImageViewerService);
+
+    if (qstrcmp(name, QMediaImageViewerControl_iid) == 0) {
+        return d->viewerControl;
+    } else if (qstrcmp(name, QVideoOutputControl_iid) == 0) {
+        return d->outputControl;
+    } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
+        return d->rendererControl;
+    } else {
+        return 0;
+    }
+}
+
+/*!
+*/
+QNetworkAccessManager *QMediaImageViewerService::networkManager() const
+{
+    Q_D(const QMediaImageViewerService);
+
+    if (!d->network) {
+        QMediaImageViewerServicePrivate *_d = const_cast<QMediaImageViewerServicePrivate *>(d);
+
+        if (!_d->internalNetwork)
+            _d->internalNetwork = new QNetworkAccessManager(
+                    const_cast<QMediaImageViewerService *>(this));
+
+        _d->network = d->internalNetwork;
+    }
+
+    return d->network;
+}
+
+
+void QMediaImageViewerService::setNetworkManager(QNetworkAccessManager *manager)
+{
+    d_func()->network = manager;
+}
+
+class QMediaImageViewerControlPrivate : public QMediaControlPrivate
+{
+    Q_DECLARE_NON_CONST_PUBLIC(QMediaImageViewerControl)
+public:
+    QMediaImageViewerControlPrivate()
+        : service(0)
+        , getReply(0)
+        , headReply(0)
+        , status(QMediaImageViewer::NoMedia)
+    {
+    }
+
+    bool isImageType(const QUrl &url, const QString &mimeType) const;
+
+    void loadImage();
+    void cancelRequests();
+
+    void _q_getFinished();
+    void _q_headFinished();
+
+    QMediaImageViewerService *service;
+    QNetworkReply *getReply;
+    QNetworkReply *headReply;
+    QMediaImageViewer::MediaStatus status;
+    QMediaContent media;
+    QMediaResource currentMedia;
+    QList<QMediaResource> possibleResources;
+};
+
+bool QMediaImageViewerControlPrivate::isImageType(const QUrl &url, const QString &mimeType) const
+{
+    if (!mimeType.isEmpty()) {
+        return mimeType.startsWith(QLatin1String("image/"))
+                || mimeType == QLatin1String("application/xml+svg");
+    } else if (url.scheme() == QLatin1String("file")) {
+        QString path = url.path();
+
+        return path.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)
+                || path.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive)
+                || path.endsWith(QLatin1String(".png"), Qt::CaseInsensitive)
+                || path.endsWith(QLatin1String(".bmp"), Qt::CaseInsensitive)
+                || path.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)
+                || path.endsWith(QLatin1String(".tiff"), Qt::CaseInsensitive);
+    } else {
+        return false;
+    }
+}
+
+void QMediaImageViewerControlPrivate::loadImage()
+{
+    cancelRequests();
+
+    QMediaImageViewer::MediaStatus currentStatus = status;
+    status = QMediaImageViewer::InvalidMedia;
+
+    QNetworkAccessManager *network = service->networkManager();
+
+    while (!possibleResources.isEmpty() && !headReply && !getReply) {
+        currentMedia = possibleResources.takeFirst();
+
+        QUrl url = currentMedia.url();
+        QString mimeType = currentMedia.mimeType();
+
+        if (isImageType(url, mimeType)) {
+            getReply = network->get(QNetworkRequest(url));
+            QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
+
+            status = QMediaImageViewer::LoadingMedia;
+        } else if (mimeType.isEmpty() && url.scheme() != QLatin1String("file")) {
+            headReply = network->head(QNetworkRequest(currentMedia.url()));
+            QObject::connect(headReply, SIGNAL(finished()), q_func(), SLOT(_q_headFinished()));
+
+            status = QMediaImageViewer::LoadingMedia;
+        }
+    }
+
+    if (status == QMediaImageViewer::InvalidMedia)
+        currentMedia = QMediaResource();
+
+    if (status != currentStatus)
+        emit q_func()->mediaStatusChanged(status);
+}
+
+void QMediaImageViewerControlPrivate::cancelRequests()
+{
+    if (getReply) {
+        getReply->abort();
+        getReply->deleteLater();
+        getReply = 0;
+    }
+
+    if (headReply) {
+        headReply->abort();
+        headReply->deleteLater();
+        headReply = 0;
+    }
+}
+
+void QMediaImageViewerControlPrivate::_q_getFinished()
+{
+    if (getReply != q_func()->sender())
+        return;
+
+    QImage image;
+
+    if (service->d_func()->load(getReply)) {
+        possibleResources.clear();
+
+        status = QMediaImageViewer::LoadedMedia;
+
+        emit q_func()->mediaStatusChanged(status);
+    } else {
+        loadImage();
+    }
+}
+
+void QMediaImageViewerControlPrivate::_q_headFinished()
+{
+    if (headReply != q_func()->sender())
+        return;
+
+    QString mimeType = headReply->header(QNetworkRequest::ContentTypeHeader)
+            .toString().section(QLatin1Char(';'), 0, 0);
+    QUrl url = headReply->url();
+    if (url.isEmpty())
+        url = headReply->request().url();
+
+    headReply->deleteLater();
+    headReply = 0;
+
+    if (isImageType(url, mimeType) || mimeType.isEmpty()) {
+        QNetworkAccessManager *network = service->networkManager();
+
+        getReply = network->get(QNetworkRequest(url));
+
+        QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
+    } else {
+        loadImage();
+    }
+}
+
+/*!
+    \class QMediaImageViewerControl
+    \internal
+*/
+QMediaImageViewerControl::QMediaImageViewerControl(QMediaImageViewerService *parent)
+    : QMediaControl(*new QMediaImageViewerControlPrivate, parent)
+{
+    Q_D(QMediaImageViewerControl);
+
+    d->service = parent;
+}
+
+/*!
+*/
+QMediaImageViewerControl::~QMediaImageViewerControl()
+{
+    Q_D(QMediaImageViewerControl);
+
+    delete d->getReply;
+}
+
+/*!
+*/
+QMediaImageViewer::MediaStatus QMediaImageViewerControl::mediaStatus() const
+{
+    return d_func()->status;
+}
+
+/*!
+    \fn QMediaImageViewerControl::mediaStatusChanged(QMediaImageViewer::MediaStatus status);
+*/
+
+/*!
+*/
+void QMediaImageViewerControl::showMedia(const QMediaContent &media)
+{
+    Q_D(QMediaImageViewerControl);
+
+    d->media = media;
+    d->currentMedia = QMediaResource();
+    d->cancelRequests();
+
+    if (media.isNull()) {
+        d->service->d_func()->clear();
+
+        d->status = QMediaImageViewer::NoMedia;
+
+        emit mediaStatusChanged(d->status);
+    } else {
+        d->possibleResources = media.resources();
+        d->loadImage();
+    }
+}
+
+
+#include "moc_qmediaimageviewerservice_p.cpp"
+QTM_END_NAMESPACE
+