src/multimedia/qmediaimageviewerservice.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qmediaimageviewerservice_p.h"
       
    43 
       
    44 #include "qmediacontrol_p.h"
       
    45 #include "qmediaservice_p.h"
       
    46 
       
    47 #include <qmediacontent.h>
       
    48 #include <qmediaresource.h>
       
    49 #include <qmediaobject_p.h>
       
    50 #include <qvideorenderercontrol.h>
       
    51 #include <qvideowidgetcontrol.h>
       
    52 
       
    53 #include <QtCore/qdebug.h>
       
    54 
       
    55 #include <QtCore/qurl.h>
       
    56 #include <QtGui/qimagereader.h>
       
    57 #include <QtGui/qpainter.h>
       
    58 
       
    59 #include <QtNetwork/qnetworkaccessmanager.h>
       
    60 #include <QtNetwork/qnetworkreply.h>
       
    61 #include <QtNetwork/qnetworkrequest.h>
       
    62 
       
    63 #include <qabstractvideosurface.h>
       
    64 #include <qvideosurfaceformat.h>
       
    65 
       
    66 QT_BEGIN_NAMESPACE
       
    67 
       
    68 class QMediaImageViewerServicePrivate : public QMediaServicePrivate
       
    69 {
       
    70 public:
       
    71     QMediaImageViewerServicePrivate()
       
    72         : viewerControl(0)
       
    73         , rendererControl(0)
       
    74         , network(0)
       
    75         , internalNetwork(0)
       
    76     {
       
    77     }
       
    78 
       
    79     bool load(QIODevice *device);
       
    80     void clear();
       
    81 
       
    82     QMediaImageViewerControl *viewerControl;
       
    83     QMediaImageViewerRenderer *rendererControl;
       
    84     QNetworkAccessManager *network;
       
    85     QNetworkAccessManager *internalNetwork;
       
    86     QImage m_image;
       
    87 };
       
    88 
       
    89 
       
    90 QMediaImageViewerRenderer::QMediaImageViewerRenderer(QObject *parent)
       
    91     : QVideoRendererControl(parent)
       
    92     , m_surface(0)
       
    93 {
       
    94 }
       
    95 
       
    96 QMediaImageViewerRenderer::~QMediaImageViewerRenderer()
       
    97 {
       
    98     if (m_surface)
       
    99         m_surface->stop();
       
   100 }
       
   101 
       
   102 QAbstractVideoSurface *QMediaImageViewerRenderer::surface() const
       
   103 {
       
   104     return m_surface;
       
   105 }
       
   106 
       
   107 void QMediaImageViewerRenderer::setSurface(QAbstractVideoSurface *surface)
       
   108 {
       
   109     if (m_surface)
       
   110         m_surface->stop();
       
   111 
       
   112     m_surface = surface;
       
   113 
       
   114     if (m_surface && !m_image.isNull()) {
       
   115         QVideoSurfaceFormat format(
       
   116                 m_image.size(), QVideoFrame::pixelFormatFromImageFormat(m_image.format()));
       
   117 
       
   118         if (surface->start(format))
       
   119             surface->present(QVideoFrame(m_image));
       
   120     }
       
   121 }
       
   122 
       
   123 void QMediaImageViewerRenderer::showImage(const QImage &image)
       
   124 {
       
   125     m_image = image;
       
   126 
       
   127     if (m_surface) {
       
   128         if (m_image.isNull()) {
       
   129             m_surface->stop();
       
   130         } else {
       
   131             QVideoSurfaceFormat format(
       
   132                     image.size(), QVideoFrame::pixelFormatFromImageFormat(image.format()));
       
   133 
       
   134             if (m_surface->start(format))
       
   135                 m_surface->present(QVideoFrame(image));
       
   136         }
       
   137     }
       
   138 }
       
   139 
       
   140 bool QMediaImageViewerServicePrivate::load(QIODevice *device)
       
   141 {
       
   142     QImageReader reader(device);
       
   143 
       
   144     if (!reader.canRead()) {
       
   145         m_image = QImage();
       
   146     } else {
       
   147         m_image = reader.read();
       
   148     }
       
   149 
       
   150     if (rendererControl)
       
   151         rendererControl->showImage(m_image);
       
   152 
       
   153     return !m_image.isNull();
       
   154 }
       
   155 
       
   156 void QMediaImageViewerServicePrivate::clear()
       
   157 {
       
   158     m_image = QImage();
       
   159 
       
   160     if (rendererControl)
       
   161         rendererControl->showImage(m_image);
       
   162 }
       
   163 
       
   164 /*!
       
   165     \class QMediaImageViewerService
       
   166     \internal
       
   167 */
       
   168 
       
   169 /*!
       
   170 */
       
   171 QMediaImageViewerService::QMediaImageViewerService(QObject *parent)
       
   172     : QMediaService(*new QMediaImageViewerServicePrivate, parent)
       
   173 {
       
   174     Q_D(QMediaImageViewerService);
       
   175 
       
   176     d->viewerControl = new QMediaImageViewerControl(this);
       
   177 }
       
   178 
       
   179 /*!
       
   180 */
       
   181 QMediaImageViewerService::~QMediaImageViewerService()
       
   182 {
       
   183     Q_D(QMediaImageViewerService);
       
   184 
       
   185     delete d->rendererControl;
       
   186     delete d->viewerControl;
       
   187 }
       
   188 
       
   189 /*!
       
   190 */
       
   191 QMediaControl *QMediaImageViewerService::requestControl(const char *name)
       
   192 {
       
   193     Q_D(QMediaImageViewerService);
       
   194 
       
   195     if (qstrcmp(name, QMediaImageViewerControl_iid) == 0) {
       
   196         return d->viewerControl;
       
   197     } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
       
   198         if (!d->rendererControl) {
       
   199             d->rendererControl = new QMediaImageViewerRenderer;
       
   200             d->rendererControl->showImage(d->m_image);
       
   201 
       
   202             return d->rendererControl;
       
   203         }
       
   204     }
       
   205     return 0;
       
   206 }
       
   207 
       
   208 void QMediaImageViewerService::releaseControl(QMediaControl *control)
       
   209 {
       
   210     Q_D(QMediaImageViewerService);
       
   211 
       
   212     if (!control) {
       
   213         qWarning("QMediaService::releaseControl():"
       
   214                 " Attempted release of null control");
       
   215     } else if (control == d->rendererControl) {
       
   216         delete d->rendererControl;
       
   217 
       
   218         d->rendererControl = 0;
       
   219     }
       
   220 }
       
   221 
       
   222 /*!
       
   223 */
       
   224 QNetworkAccessManager *QMediaImageViewerService::networkManager() const
       
   225 {
       
   226     Q_D(const QMediaImageViewerService);
       
   227 
       
   228     if (!d->network) {
       
   229         QMediaImageViewerServicePrivate *_d = const_cast<QMediaImageViewerServicePrivate *>(d);
       
   230 
       
   231         if (!_d->internalNetwork)
       
   232             _d->internalNetwork = new QNetworkAccessManager(
       
   233                     const_cast<QMediaImageViewerService *>(this));
       
   234 
       
   235         _d->network = d->internalNetwork;
       
   236     }
       
   237 
       
   238     return d->network;
       
   239 }
       
   240 
       
   241 
       
   242 void QMediaImageViewerService::setNetworkManager(QNetworkAccessManager *manager)
       
   243 {
       
   244     d_func()->network = manager;
       
   245 }
       
   246 
       
   247 class QMediaImageViewerControlPrivate : public QMediaControlPrivate
       
   248 {
       
   249     Q_DECLARE_NON_CONST_PUBLIC(QMediaImageViewerControl)
       
   250 public:
       
   251     QMediaImageViewerControlPrivate()
       
   252         : service(0)
       
   253         , getReply(0)
       
   254         , headReply(0)
       
   255         , status(QMediaImageViewer::NoMedia)
       
   256     {
       
   257     }
       
   258 
       
   259     bool isImageType(const QUrl &url, const QString &mimeType) const;
       
   260 
       
   261     void loadImage();
       
   262     void cancelRequests();
       
   263 
       
   264     void _q_getFinished();
       
   265     void _q_headFinished();
       
   266 
       
   267     QMediaImageViewerService *service;
       
   268     QNetworkReply *getReply;
       
   269     QNetworkReply *headReply;
       
   270     QMediaImageViewer::MediaStatus status;
       
   271     QMediaContent media;
       
   272     QMediaResource currentMedia;
       
   273     QList<QMediaResource> possibleResources;
       
   274 };
       
   275 
       
   276 bool QMediaImageViewerControlPrivate::isImageType(const QUrl &url, const QString &mimeType) const
       
   277 {
       
   278     if (!mimeType.isEmpty()) {
       
   279         return mimeType.startsWith(QLatin1String("image/"))
       
   280                 || mimeType == QLatin1String("application/xml+svg");
       
   281     } else if (url.scheme() == QLatin1String("file")) {
       
   282         QString path = url.path();
       
   283 
       
   284         return path.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)
       
   285                 || path.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive)
       
   286                 || path.endsWith(QLatin1String(".png"), Qt::CaseInsensitive)
       
   287                 || path.endsWith(QLatin1String(".bmp"), Qt::CaseInsensitive)
       
   288                 || path.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)
       
   289                 || path.endsWith(QLatin1String(".tiff"), Qt::CaseInsensitive);
       
   290     } else {
       
   291         return false;
       
   292     }
       
   293 }
       
   294 
       
   295 void QMediaImageViewerControlPrivate::loadImage()
       
   296 {
       
   297     cancelRequests();
       
   298 
       
   299     QMediaImageViewer::MediaStatus currentStatus = status;
       
   300     status = QMediaImageViewer::InvalidMedia;
       
   301 
       
   302     QNetworkAccessManager *network = service->networkManager();
       
   303 
       
   304     while (!possibleResources.isEmpty() && !headReply && !getReply) {
       
   305         currentMedia = possibleResources.takeFirst();
       
   306 
       
   307         QUrl url = currentMedia.url();
       
   308         QString mimeType = currentMedia.mimeType();
       
   309 
       
   310         if (isImageType(url, mimeType)) {
       
   311             getReply = network->get(QNetworkRequest(url));
       
   312             QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
       
   313 
       
   314             status = QMediaImageViewer::LoadingMedia;
       
   315         } else if (mimeType.isEmpty() && url.scheme() != QLatin1String("file")) {
       
   316             headReply = network->head(QNetworkRequest(currentMedia.url()));
       
   317             QObject::connect(headReply, SIGNAL(finished()), q_func(), SLOT(_q_headFinished()));
       
   318 
       
   319             status = QMediaImageViewer::LoadingMedia;
       
   320         }
       
   321     }
       
   322 
       
   323     if (status == QMediaImageViewer::InvalidMedia)
       
   324         currentMedia = QMediaResource();
       
   325 
       
   326     if (status != currentStatus)
       
   327         emit q_func()->mediaStatusChanged(status);
       
   328 }
       
   329 
       
   330 void QMediaImageViewerControlPrivate::cancelRequests()
       
   331 {
       
   332     if (getReply) {
       
   333         getReply->abort();
       
   334         getReply->deleteLater();
       
   335         getReply = 0;
       
   336     }
       
   337 
       
   338     if (headReply) {
       
   339         headReply->abort();
       
   340         headReply->deleteLater();
       
   341         headReply = 0;
       
   342     }
       
   343 }
       
   344 
       
   345 void QMediaImageViewerControlPrivate::_q_getFinished()
       
   346 {
       
   347     if (getReply != q_func()->sender())
       
   348         return;
       
   349 
       
   350     QImage image;
       
   351 
       
   352     if (service->d_func()->load(getReply)) {
       
   353         possibleResources.clear();
       
   354 
       
   355         status = QMediaImageViewer::LoadedMedia;
       
   356 
       
   357         emit q_func()->mediaStatusChanged(status);
       
   358     } else {
       
   359         loadImage();
       
   360     }
       
   361 }
       
   362 
       
   363 void QMediaImageViewerControlPrivate::_q_headFinished()
       
   364 {
       
   365     if (headReply != q_func()->sender())
       
   366         return;
       
   367 
       
   368     QString mimeType = headReply->header(QNetworkRequest::ContentTypeHeader)
       
   369             .toString().section(QLatin1Char(';'), 0, 0);
       
   370     QUrl url = headReply->url();
       
   371     if (url.isEmpty())
       
   372         url = headReply->request().url();
       
   373 
       
   374     headReply->deleteLater();
       
   375     headReply = 0;
       
   376 
       
   377     if (isImageType(url, mimeType) || mimeType.isEmpty()) {
       
   378         QNetworkAccessManager *network = service->networkManager();
       
   379 
       
   380         getReply = network->get(QNetworkRequest(url));
       
   381 
       
   382         QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
       
   383     } else {
       
   384         loadImage();
       
   385     }
       
   386 }
       
   387 
       
   388 /*!
       
   389     \class QMediaImageViewerControl
       
   390     \internal
       
   391 */
       
   392 QMediaImageViewerControl::QMediaImageViewerControl(QMediaImageViewerService *parent)
       
   393     : QMediaControl(*new QMediaImageViewerControlPrivate, parent)
       
   394 {
       
   395     Q_D(QMediaImageViewerControl);
       
   396 
       
   397     d->service = parent;
       
   398 }
       
   399 
       
   400 /*!
       
   401 */
       
   402 QMediaImageViewerControl::~QMediaImageViewerControl()
       
   403 {
       
   404     Q_D(QMediaImageViewerControl);
       
   405 
       
   406     delete d->getReply;
       
   407 }
       
   408 
       
   409 /*!
       
   410 */
       
   411 QMediaImageViewer::MediaStatus QMediaImageViewerControl::mediaStatus() const
       
   412 {
       
   413     return d_func()->status;
       
   414 }
       
   415 
       
   416 /*!
       
   417     \fn QMediaImageViewerControl::mediaStatusChanged(QMediaImageViewer::MediaStatus status);
       
   418 */
       
   419 
       
   420 /*!
       
   421 */
       
   422 void QMediaImageViewerControl::showMedia(const QMediaContent &media)
       
   423 {
       
   424     Q_D(QMediaImageViewerControl);
       
   425 
       
   426     d->media = media;
       
   427     d->currentMedia = QMediaResource();
       
   428     d->cancelRequests();
       
   429 
       
   430     if (media.isNull()) {
       
   431         d->service->d_func()->clear();
       
   432         if (d->status != QMediaImageViewer::NoMedia) {
       
   433             d->status = QMediaImageViewer::NoMedia;
       
   434             emit mediaStatusChanged(d->status);
       
   435         }
       
   436     } else {
       
   437         d->possibleResources = media.resources();
       
   438         d->loadImage();
       
   439     }
       
   440 }
       
   441 
       
   442 
       
   443 #include "moc_qmediaimageviewerservice_p.cpp"
       
   444 QT_END_NAMESPACE
       
   445