qtmobility/src/multimedia/qmediaimageviewerservice.cpp
changeset 1 2b40d63a9c3d
child 4 90517678cc4f
equal deleted inserted replaced
0:cfcbf08528c4 1:2b40d63a9c3d
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 <qvideooutputcontrol.h>
       
    50 #include <qmediaobject_p.h>
       
    51 #include <qvideorenderercontrol.h>
       
    52 #include <qvideowidgetcontrol.h>
       
    53 
       
    54 #include <QtCore/qdebug.h>
       
    55 
       
    56 #include <QtCore/qurl.h>
       
    57 #include <QtGui/qimagereader.h>
       
    58 #include <QtGui/qpainter.h>
       
    59 
       
    60 #include <QtNetwork/qnetworkaccessmanager.h>
       
    61 #include <QtNetwork/qnetworkreply.h>
       
    62 #include <QtNetwork/qnetworkrequest.h>
       
    63 
       
    64 #include <QtMultimedia/qabstractvideosurface.h>
       
    65 #include <QtMultimedia/qvideosurfaceformat.h>
       
    66 
       
    67 QTM_BEGIN_NAMESPACE
       
    68 
       
    69 class QMediaImageViewerServicePrivate : public QMediaServicePrivate
       
    70 {
       
    71 public:
       
    72     QMediaImageViewerServicePrivate()
       
    73         : viewerControl(0)
       
    74         , outputControl(0)
       
    75         , rendererControl(0)
       
    76         , network(0)
       
    77         , internalNetwork(0)
       
    78     {
       
    79     }
       
    80 
       
    81     bool load(QIODevice *device);
       
    82     void clear();
       
    83     void _q_outputChanged(QVideoOutputControl::Output output);
       
    84 
       
    85     QMediaImageViewerControl *viewerControl;
       
    86     QMediaImageViewerOutputControl *outputControl;
       
    87     QMediaImageViewerRenderer *rendererControl;
       
    88     QNetworkAccessManager *network;
       
    89     QNetworkAccessManager *internalNetwork;
       
    90     QImage m_image;
       
    91 };
       
    92 
       
    93 
       
    94 QMediaImageViewerRenderer::QMediaImageViewerRenderer(QObject *parent)
       
    95     : QVideoRendererControl(parent)
       
    96     , m_surface(0)
       
    97 {
       
    98 }
       
    99 
       
   100 QMediaImageViewerRenderer::~QMediaImageViewerRenderer()
       
   101 {
       
   102     if (m_surface)
       
   103         m_surface->stop();
       
   104 }
       
   105 
       
   106 QAbstractVideoSurface *QMediaImageViewerRenderer::surface() const
       
   107 {
       
   108     return m_surface;
       
   109 }
       
   110 
       
   111 void QMediaImageViewerRenderer::setSurface(QAbstractVideoSurface *surface)
       
   112 {
       
   113     if (m_surface)
       
   114         m_surface->stop();
       
   115 
       
   116     m_surface = surface;
       
   117 
       
   118     if (m_surface && !m_image.isNull()) {
       
   119         QVideoSurfaceFormat format(
       
   120                 m_image.size(), QVideoFrame::pixelFormatFromImageFormat(m_image.format()));
       
   121 
       
   122         if (surface->start(format))
       
   123             surface->present(QVideoFrame(m_image));
       
   124     }
       
   125 }
       
   126 
       
   127 void QMediaImageViewerRenderer::showImage(const QImage &image)
       
   128 {
       
   129     m_image = image;
       
   130 
       
   131     if (m_surface) {
       
   132         if (m_image.isNull()) {
       
   133             m_surface->stop();
       
   134         } else {
       
   135             QVideoSurfaceFormat format(
       
   136                     image.size(), QVideoFrame::pixelFormatFromImageFormat(image.format()));
       
   137 
       
   138             if (m_surface->start(format))
       
   139                 m_surface->present(QVideoFrame(image));
       
   140         }
       
   141     }
       
   142 }
       
   143 
       
   144 QMediaImageViewerOutputControl::QMediaImageViewerOutputControl(QObject *parent)
       
   145     : QVideoOutputControl(parent)
       
   146     , m_output(NoOutput)
       
   147 {
       
   148 }
       
   149 
       
   150 QList<QVideoOutputControl::Output> QMediaImageViewerOutputControl::availableOutputs() const
       
   151 {
       
   152     return QList<Output>()
       
   153             << RendererOutput;
       
   154 }
       
   155 
       
   156 void QMediaImageViewerOutputControl::setOutput(Output output)
       
   157 {
       
   158     switch (output) {
       
   159     case RendererOutput:
       
   160         emit m_output = output;
       
   161         break;
       
   162     default:
       
   163         m_output = NoOutput;
       
   164     }
       
   165     emit outputChanged(m_output);
       
   166 }
       
   167 
       
   168 bool QMediaImageViewerServicePrivate::load(QIODevice *device)
       
   169 {
       
   170     QImageReader reader(device);
       
   171 
       
   172     if (!reader.canRead()) {
       
   173         m_image = QImage();
       
   174     } else {
       
   175         m_image = reader.read();
       
   176     }
       
   177 
       
   178     if (outputControl->output() == QVideoOutputControl::RendererOutput)
       
   179         rendererControl->showImage(m_image);
       
   180 
       
   181     return !m_image.isNull();
       
   182 }
       
   183 
       
   184 void QMediaImageViewerServicePrivate::clear()
       
   185 {
       
   186     m_image = QImage();
       
   187 
       
   188     if (outputControl->output() == QVideoOutputControl::RendererOutput)
       
   189         rendererControl->showImage(m_image);
       
   190 }
       
   191 
       
   192 void QMediaImageViewerServicePrivate::_q_outputChanged(QVideoOutputControl::Output output)
       
   193 {
       
   194     if (output != QVideoOutputControl::RendererOutput)
       
   195         rendererControl->showImage(QImage());
       
   196 
       
   197     if (output == QVideoOutputControl::RendererOutput)
       
   198         rendererControl->showImage(m_image);
       
   199 }
       
   200 
       
   201 /*!
       
   202     \class QMediaImageViewerService
       
   203     \internal
       
   204 */
       
   205 
       
   206 /*!
       
   207 */
       
   208 QMediaImageViewerService::QMediaImageViewerService(QObject *parent)
       
   209     : QMediaService(*new QMediaImageViewerServicePrivate, parent)
       
   210 {
       
   211     Q_D(QMediaImageViewerService);
       
   212 
       
   213     d->viewerControl = new QMediaImageViewerControl(this);
       
   214     d->outputControl = new QMediaImageViewerOutputControl;
       
   215     connect(d->outputControl, SIGNAL(outputChanged(QVideoOutputControl::Output)),
       
   216             SLOT(_q_outputChanged(QVideoOutputControl::Output)));
       
   217 
       
   218     d->rendererControl = new QMediaImageViewerRenderer;
       
   219 }
       
   220 
       
   221 /*!
       
   222 */
       
   223 QMediaImageViewerService::~QMediaImageViewerService()
       
   224 {
       
   225     Q_D(QMediaImageViewerService);
       
   226 
       
   227     delete d->rendererControl;
       
   228     delete d->outputControl;
       
   229     delete d->viewerControl;
       
   230 }
       
   231 
       
   232 /*!
       
   233 */
       
   234 QMediaControl *QMediaImageViewerService::control(const char *name) const
       
   235 {
       
   236     Q_D(const QMediaImageViewerService);
       
   237 
       
   238     if (qstrcmp(name, QMediaImageViewerControl_iid) == 0) {
       
   239         return d->viewerControl;
       
   240     } else if (qstrcmp(name, QVideoOutputControl_iid) == 0) {
       
   241         return d->outputControl;
       
   242     } else if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
       
   243         return d->rendererControl;
       
   244     } else {
       
   245         return 0;
       
   246     }
       
   247 }
       
   248 
       
   249 /*!
       
   250 */
       
   251 QNetworkAccessManager *QMediaImageViewerService::networkManager() const
       
   252 {
       
   253     Q_D(const QMediaImageViewerService);
       
   254 
       
   255     if (!d->network) {
       
   256         QMediaImageViewerServicePrivate *_d = const_cast<QMediaImageViewerServicePrivate *>(d);
       
   257 
       
   258         if (!_d->internalNetwork)
       
   259             _d->internalNetwork = new QNetworkAccessManager(
       
   260                     const_cast<QMediaImageViewerService *>(this));
       
   261 
       
   262         _d->network = d->internalNetwork;
       
   263     }
       
   264 
       
   265     return d->network;
       
   266 }
       
   267 
       
   268 
       
   269 void QMediaImageViewerService::setNetworkManager(QNetworkAccessManager *manager)
       
   270 {
       
   271     d_func()->network = manager;
       
   272 }
       
   273 
       
   274 class QMediaImageViewerControlPrivate : public QMediaControlPrivate
       
   275 {
       
   276     Q_DECLARE_NON_CONST_PUBLIC(QMediaImageViewerControl)
       
   277 public:
       
   278     QMediaImageViewerControlPrivate()
       
   279         : service(0)
       
   280         , getReply(0)
       
   281         , headReply(0)
       
   282         , status(QMediaImageViewer::NoMedia)
       
   283     {
       
   284     }
       
   285 
       
   286     bool isImageType(const QUrl &url, const QString &mimeType) const;
       
   287 
       
   288     void loadImage();
       
   289     void cancelRequests();
       
   290 
       
   291     void _q_getFinished();
       
   292     void _q_headFinished();
       
   293 
       
   294     QMediaImageViewerService *service;
       
   295     QNetworkReply *getReply;
       
   296     QNetworkReply *headReply;
       
   297     QMediaImageViewer::MediaStatus status;
       
   298     QMediaContent media;
       
   299     QMediaResource currentMedia;
       
   300     QList<QMediaResource> possibleResources;
       
   301 };
       
   302 
       
   303 bool QMediaImageViewerControlPrivate::isImageType(const QUrl &url, const QString &mimeType) const
       
   304 {
       
   305     if (!mimeType.isEmpty()) {
       
   306         return mimeType.startsWith(QLatin1String("image/"))
       
   307                 || mimeType == QLatin1String("application/xml+svg");
       
   308     } else if (url.scheme() == QLatin1String("file")) {
       
   309         QString path = url.path();
       
   310 
       
   311         return path.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive)
       
   312                 || path.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive)
       
   313                 || path.endsWith(QLatin1String(".png"), Qt::CaseInsensitive)
       
   314                 || path.endsWith(QLatin1String(".bmp"), Qt::CaseInsensitive)
       
   315                 || path.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)
       
   316                 || path.endsWith(QLatin1String(".tiff"), Qt::CaseInsensitive);
       
   317     } else {
       
   318         return false;
       
   319     }
       
   320 }
       
   321 
       
   322 void QMediaImageViewerControlPrivate::loadImage()
       
   323 {
       
   324     cancelRequests();
       
   325 
       
   326     QMediaImageViewer::MediaStatus currentStatus = status;
       
   327     status = QMediaImageViewer::InvalidMedia;
       
   328 
       
   329     QNetworkAccessManager *network = service->networkManager();
       
   330 
       
   331     while (!possibleResources.isEmpty() && !headReply && !getReply) {
       
   332         currentMedia = possibleResources.takeFirst();
       
   333 
       
   334         QUrl url = currentMedia.url();
       
   335         QString mimeType = currentMedia.mimeType();
       
   336 
       
   337         if (isImageType(url, mimeType)) {
       
   338             getReply = network->get(QNetworkRequest(url));
       
   339             QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
       
   340 
       
   341             status = QMediaImageViewer::LoadingMedia;
       
   342         } else if (mimeType.isEmpty() && url.scheme() != QLatin1String("file")) {
       
   343             headReply = network->head(QNetworkRequest(currentMedia.url()));
       
   344             QObject::connect(headReply, SIGNAL(finished()), q_func(), SLOT(_q_headFinished()));
       
   345 
       
   346             status = QMediaImageViewer::LoadingMedia;
       
   347         }
       
   348     }
       
   349 
       
   350     if (status == QMediaImageViewer::InvalidMedia)
       
   351         currentMedia = QMediaResource();
       
   352 
       
   353     if (status != currentStatus)
       
   354         emit q_func()->mediaStatusChanged(status);
       
   355 }
       
   356 
       
   357 void QMediaImageViewerControlPrivate::cancelRequests()
       
   358 {
       
   359     if (getReply) {
       
   360         getReply->abort();
       
   361         getReply->deleteLater();
       
   362         getReply = 0;
       
   363     }
       
   364 
       
   365     if (headReply) {
       
   366         headReply->abort();
       
   367         headReply->deleteLater();
       
   368         headReply = 0;
       
   369     }
       
   370 }
       
   371 
       
   372 void QMediaImageViewerControlPrivate::_q_getFinished()
       
   373 {
       
   374     if (getReply != q_func()->sender())
       
   375         return;
       
   376 
       
   377     QImage image;
       
   378 
       
   379     if (service->d_func()->load(getReply)) {
       
   380         possibleResources.clear();
       
   381 
       
   382         status = QMediaImageViewer::LoadedMedia;
       
   383 
       
   384         emit q_func()->mediaStatusChanged(status);
       
   385     } else {
       
   386         loadImage();
       
   387     }
       
   388 }
       
   389 
       
   390 void QMediaImageViewerControlPrivate::_q_headFinished()
       
   391 {
       
   392     if (headReply != q_func()->sender())
       
   393         return;
       
   394 
       
   395     QString mimeType = headReply->header(QNetworkRequest::ContentTypeHeader)
       
   396             .toString().section(QLatin1Char(';'), 0, 0);
       
   397     QUrl url = headReply->url();
       
   398     if (url.isEmpty())
       
   399         url = headReply->request().url();
       
   400 
       
   401     headReply->deleteLater();
       
   402     headReply = 0;
       
   403 
       
   404     if (isImageType(url, mimeType) || mimeType.isEmpty()) {
       
   405         QNetworkAccessManager *network = service->networkManager();
       
   406 
       
   407         getReply = network->get(QNetworkRequest(url));
       
   408 
       
   409         QObject::connect(getReply, SIGNAL(finished()), q_func(), SLOT(_q_getFinished()));
       
   410     } else {
       
   411         loadImage();
       
   412     }
       
   413 }
       
   414 
       
   415 /*!
       
   416     \class QMediaImageViewerControl
       
   417     \internal
       
   418 */
       
   419 QMediaImageViewerControl::QMediaImageViewerControl(QMediaImageViewerService *parent)
       
   420     : QMediaControl(*new QMediaImageViewerControlPrivate, parent)
       
   421 {
       
   422     Q_D(QMediaImageViewerControl);
       
   423 
       
   424     d->service = parent;
       
   425 }
       
   426 
       
   427 /*!
       
   428 */
       
   429 QMediaImageViewerControl::~QMediaImageViewerControl()
       
   430 {
       
   431     Q_D(QMediaImageViewerControl);
       
   432 
       
   433     delete d->getReply;
       
   434 }
       
   435 
       
   436 /*!
       
   437 */
       
   438 QMediaImageViewer::MediaStatus QMediaImageViewerControl::mediaStatus() const
       
   439 {
       
   440     return d_func()->status;
       
   441 }
       
   442 
       
   443 /*!
       
   444     \fn QMediaImageViewerControl::mediaStatusChanged(QMediaImageViewer::MediaStatus status);
       
   445 */
       
   446 
       
   447 /*!
       
   448 */
       
   449 void QMediaImageViewerControl::showMedia(const QMediaContent &media)
       
   450 {
       
   451     Q_D(QMediaImageViewerControl);
       
   452 
       
   453     d->media = media;
       
   454     d->currentMedia = QMediaResource();
       
   455     d->cancelRequests();
       
   456 
       
   457     if (media.isNull()) {
       
   458         d->service->d_func()->clear();
       
   459 
       
   460         d->status = QMediaImageViewer::NoMedia;
       
   461 
       
   462         emit mediaStatusChanged(d->status);
       
   463     } else {
       
   464         d->possibleResources = media.resources();
       
   465         d->loadImage();
       
   466     }
       
   467 }
       
   468 
       
   469 
       
   470 #include "moc_qmediaimageviewerservice_p.cpp"
       
   471 QTM_END_NAMESPACE
       
   472