dd4b6e614e38b5aa3d52669aea9d548d4c69b13a
[WebKit-https.git] / Source / WebCore / platform / graphics / qt / MediaPlayerPrivateQt.cpp
1 /*
2     Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #include "MediaPlayerPrivateQt.h"
22
23 #include "FrameLoaderClientQt.h"
24 #include "FrameView.h"
25 #include "GraphicsContext.h"
26 #include "HTMLMediaElement.h"
27 #include "HTMLVideoElement.h"
28 #include "QtNAMThreadSafeProxy.h"
29 #include "NetworkingContext.h"
30 #include "NotImplemented.h"
31 #include "RenderVideo.h"
32 #include "TimeRanges.h"
33 #include "Widget.h"
34 #include "qwebframe.h"
35 #include "qwebpage.h"
36
37 #include <QGraphicsScene>
38 #include <QGraphicsVideoItem>
39 #include <QMediaPlayerControl>
40 #include <QMediaService>
41 #include <QNetworkAccessManager>
42 #include <QNetworkCookieJar>
43 #include <QNetworkRequest>
44 #include <QPainter>
45 #include <QPoint>
46 #include <QRect>
47 #include <QStyleOptionGraphicsItem>
48 #include <QTime>
49 #include <QTimer>
50 #include <QUrl>
51 #include <limits>
52 #include <wtf/HashSet.h>
53 #include <wtf/text/CString.h>
54
55 #if USE(ACCELERATED_COMPOSITING)
56 #include "texmap/TextureMapperPlatformLayer.h"
57 #endif
58
59 using namespace WTF;
60
61 namespace WebCore {
62
63 MediaPlayerPrivateInterface* MediaPlayerPrivateQt::create(MediaPlayer* player)
64 {
65     return new MediaPlayerPrivateQt(player);
66 }
67
68 void MediaPlayerPrivateQt::registerMediaEngine(MediaEngineRegistrar registrar)
69 {
70     registrar(create, getSupportedTypes, supportsType);
71 }
72
73 void MediaPlayerPrivateQt::getSupportedTypes(HashSet<String> &supported)
74 {
75     QStringList types = QMediaPlayer::supportedMimeTypes();
76
77     for (int i = 0; i < types.size(); i++) {
78         QString mime = types.at(i);
79         if (mime.startsWith("audio/") || mime.startsWith("video/"))
80             supported.add(mime);
81     }
82 }
83
84 MediaPlayer::SupportsType MediaPlayerPrivateQt::supportsType(const String& mime, const String& codec)
85 {
86     if (!mime.startsWith("audio/") && !mime.startsWith("video/"))
87         return MediaPlayer::IsNotSupported;
88
89     if (QMediaPlayer::hasSupport(mime, QStringList(codec)) >= QtMultimediaKit::ProbablySupported)
90         return MediaPlayer::IsSupported;
91
92     return MediaPlayer::MayBeSupported;
93 }
94
95 MediaPlayerPrivateQt::MediaPlayerPrivateQt(MediaPlayer* player)
96     : m_webCorePlayer(player)
97     , m_mediaPlayer(new QMediaPlayer)
98     , m_mediaPlayerControl(0)
99     , m_videoItem(new QGraphicsVideoItem)
100     , m_videoScene(new QGraphicsScene)
101     , m_networkState(MediaPlayer::Empty)
102     , m_readyState(MediaPlayer::HaveNothing)
103     , m_currentSize(0, 0)
104     , m_naturalSize(RenderVideo::defaultSize())
105     , m_isVisible(false)
106     , m_isSeeking(false)
107     , m_composited(false)
108     , m_queuedSeek(-1)
109     , m_preload(MediaPlayer::Auto)
110 {
111     m_mediaPlayer->bind(m_videoItem);
112     m_videoScene->addItem(m_videoItem);
113
114     // Signal Handlers
115     connect(m_mediaPlayer, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
116             this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
117     connect(m_mediaPlayer, SIGNAL(stateChanged(QMediaPlayer::State)),
118             this, SLOT(stateChanged(QMediaPlayer::State)));
119     connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)),
120             this, SLOT(handleError(QMediaPlayer::Error)));
121     connect(m_mediaPlayer, SIGNAL(bufferStatusChanged(int)),
122             this, SLOT(bufferStatusChanged(int)));
123     connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)),
124             this, SLOT(durationChanged(qint64)));
125     connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)),
126             this, SLOT(positionChanged(qint64)));
127     connect(m_mediaPlayer, SIGNAL(volumeChanged(int)),
128             this, SLOT(volumeChanged(int)));
129     connect(m_mediaPlayer, SIGNAL(mutedChanged(bool)),
130             this, SLOT(mutedChanged(bool)));
131     connect(m_videoScene, SIGNAL(changed(QList<QRectF>)),
132             this, SLOT(repaint()));
133     connect(m_videoItem, SIGNAL(nativeSizeChanged(QSizeF)),
134            this, SLOT(nativeSizeChanged(QSizeF)));
135
136     // Grab the player control
137     if (QMediaService* service = m_mediaPlayer->service()) {
138         m_mediaPlayerControl = qobject_cast<QMediaPlayerControl *>(
139                 service->requestControl(QMediaPlayerControl_iid));
140     }
141 }
142
143 MediaPlayerPrivateQt::~MediaPlayerPrivateQt()
144 {
145     m_mediaPlayer->disconnect(this);
146     m_mediaPlayer->stop();
147     m_mediaPlayer->setMedia(QMediaContent());
148
149     delete m_mediaPlayer;
150     delete m_videoScene;
151 }
152
153 bool MediaPlayerPrivateQt::hasVideo() const
154 {
155     return m_mediaPlayer->isVideoAvailable();
156 }
157
158 bool MediaPlayerPrivateQt::hasAudio() const
159 {
160     return true;
161 }
162
163 void MediaPlayerPrivateQt::load(const String& url)
164 {
165     m_mediaUrl = url;
166
167     // QtMultimedia does not have an API to throttle loading
168     // so we handle this ourselves by delaying the load
169     if (m_preload == MediaPlayer::None) {
170         m_delayingLoad = true;
171         return;
172     }
173
174     commitLoad(url);
175 }
176
177 void MediaPlayerPrivateQt::commitLoad(const String& url)
178 {
179     // We are now loading
180     if (m_networkState != MediaPlayer::Loading) {
181         m_networkState = MediaPlayer::Loading;
182         m_webCorePlayer->networkStateChanged();
183     }
184
185     // And we don't have any data yet
186     if (m_readyState != MediaPlayer::HaveNothing) {
187         m_readyState = MediaPlayer::HaveNothing;
188         m_webCorePlayer->readyStateChanged();
189     }
190
191     const QUrl rUrl = QUrl(QString(url));
192     const QString scheme = rUrl.scheme().toLower();
193
194     // Grab the client media element
195     HTMLMediaElement* element = static_cast<HTMLMediaElement*>(m_webCorePlayer->mediaPlayerClient());
196
197     // Construct the media content with a network request if the resource is http[s]
198     if (scheme == "http" || scheme == "https") {
199         QNetworkRequest request = QNetworkRequest(rUrl);
200
201         // Grab the current document
202         Document* document = element->document();
203         if (!document)
204             document = element->ownerDocument();
205
206         // Grab the frame and network manager
207         Frame* frame = document ? document->frame() : 0;
208         QNetworkAccessManager* manager = frame ? frame->loader()->networkingContext()->networkAccessManager() : 0;
209         FrameLoaderClientQt* frameLoader =  frame ? static_cast<FrameLoaderClientQt*>(frame->loader()->client()) : 0;
210
211         if (document && manager) {
212             // Set the cookies
213             QtNAMThreadSafeProxy managerProxy(manager);
214             QList<QNetworkCookie> cookies = managerProxy.cookiesForUrl(rUrl);
215
216             // Don't set the header if there are no cookies.
217             // This prevents a warning from being emitted.
218             if (!cookies.isEmpty())
219                 request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
220
221             // Set the refferer, but not when requesting insecure content from a secure page
222             QUrl documentUrl = QUrl(QString(document->documentURI()));
223             if (documentUrl.scheme().toLower() == "http" || scheme == "https")
224                 request.setRawHeader("Referer", documentUrl.toEncoded());
225
226             // Set the user agent
227             request.setRawHeader("User-Agent", frameLoader->userAgent(rUrl).utf8().data());
228         }
229
230         m_mediaPlayer->setMedia(QMediaContent(request));
231     } else {
232         // Otherwise, just use the URL
233         m_mediaPlayer->setMedia(QMediaContent(rUrl));
234     }
235
236     // Set the current volume and mute status
237     // We get these from the element, rather than the player, in case we have
238     // transitioned from a media engine which doesn't support muting, to a media
239     // engine which does.
240     m_mediaPlayer->setMuted(element->muted());
241     m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0));
242
243     // Setting a media source will start loading the media, but we need
244     // to pre-roll as well to get video size-hints and buffer-status
245     if (element->paused())
246         m_mediaPlayer->pause();
247     else
248         m_mediaPlayer->play();
249 }
250
251 void MediaPlayerPrivateQt::resumeLoad()
252 {
253     m_delayingLoad = false;
254
255     if (!m_mediaUrl.isNull())
256         commitLoad(m_mediaUrl);
257 }
258
259 void MediaPlayerPrivateQt::cancelLoad()
260 {
261     m_mediaPlayer->setMedia(QMediaContent());
262     updateStates();
263 }
264
265 void MediaPlayerPrivateQt::prepareToPlay()
266 {
267     if (m_mediaPlayer->media().isNull() || m_delayingLoad)
268         resumeLoad();
269 }
270
271 void MediaPlayerPrivateQt::play()
272 {
273     if (m_mediaPlayer->state() != QMediaPlayer::PlayingState)
274         m_mediaPlayer->play();
275 }
276
277 void MediaPlayerPrivateQt::pause()
278 {
279     if (m_mediaPlayer->state() == QMediaPlayer::PlayingState)
280         m_mediaPlayer->pause();
281 }
282
283 bool MediaPlayerPrivateQt::paused() const
284 {
285     return (m_mediaPlayer->state() != QMediaPlayer::PlayingState);
286 }
287
288 void MediaPlayerPrivateQt::seek(float position)
289 {
290     if (!m_mediaPlayer->isSeekable())
291         return;
292
293     if (m_mediaPlayerControl && !m_mediaPlayerControl->availablePlaybackRanges().contains(position * 1000))
294         return;
295
296     if (m_isSeeking)
297         return;
298
299     if (position > duration())
300         position = duration();
301
302     // Seeking is most reliable when we're paused.
303     // Webkit will try to pause before seeking, but due to the asynchronous nature
304     // of the backend, the player may not actually be paused yet.
305     // In this case, we should queue the seek and wait until pausing has completed
306     // before attempting to seek.
307     if (m_mediaPlayer->state() == QMediaPlayer::PlayingState) {
308         m_mediaPlayer->pause();
309         m_isSeeking = true;
310         m_queuedSeek = static_cast<qint64>(position * 1000);
311
312         // Set a timeout, so that in the event that we don't get a state changed
313         // signal, we still attempt the seek.
314         QTimer::singleShot(1000, this, SLOT(queuedSeekTimeout()));
315     } else {
316         m_isSeeking = true;
317         m_mediaPlayer->setPosition(static_cast<qint64>(position * 1000));
318
319         // Set a timeout, in case we don't get a position changed signal
320         QTimer::singleShot(10000, this, SLOT(seekTimeout()));
321     }
322 }
323
324 bool MediaPlayerPrivateQt::seeking() const
325 {
326     return m_isSeeking;
327 }
328
329 float MediaPlayerPrivateQt::duration() const
330 {
331     if (m_readyState < MediaPlayer::HaveMetadata)
332         return 0.0f;
333
334     float duration = m_mediaPlayer->duration() / 1000.0f;
335
336     // We are streaming
337     if (duration <= 0.0f)
338         duration = std::numeric_limits<float>::infinity();
339
340     return duration;
341 }
342
343 float MediaPlayerPrivateQt::currentTime() const
344 {
345     return m_mediaPlayer->position() / 1000.0f;
346 }
347
348 PassRefPtr<TimeRanges> MediaPlayerPrivateQt::buffered() const
349 {
350     RefPtr<TimeRanges> buffered = TimeRanges::create();
351
352     if (!m_mediaPlayerControl)
353         return buffered;
354
355     QMediaTimeRange playbackRanges = m_mediaPlayerControl->availablePlaybackRanges();
356
357     foreach (const QMediaTimeInterval interval, playbackRanges.intervals()) {
358         float rangeMin = static_cast<float>(interval.start()) / 1000.0f;
359         float rangeMax = static_cast<float>(interval.end()) / 1000.0f;
360         buffered->add(rangeMin, rangeMax);
361     }
362
363     return buffered.release();
364 }
365
366 float MediaPlayerPrivateQt::maxTimeSeekable() const
367 {
368     if (!m_mediaPlayerControl)
369         return 0;
370
371     return static_cast<float>(m_mediaPlayerControl->availablePlaybackRanges().latestTime()) / 1000.0f;
372 }
373
374 unsigned MediaPlayerPrivateQt::bytesLoaded() const
375 {
376     QLatin1String bytesLoadedKey("bytes-loaded");
377     if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey))
378         return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt();
379
380     return m_mediaPlayer->bufferStatus();
381 }
382
383 unsigned MediaPlayerPrivateQt::totalBytes() const
384 {
385     if (m_mediaPlayer->availableMetaData().contains(QtMultimediaKit::Size))
386         return m_mediaPlayer->metaData(QtMultimediaKit::Size).toInt();
387
388     return 100;
389 }
390
391 void MediaPlayerPrivateQt::setPreload(MediaPlayer::Preload preload)
392 {
393     m_preload = preload;
394     if (m_delayingLoad && m_preload != MediaPlayer::None)
395         resumeLoad();
396 }
397
398 void MediaPlayerPrivateQt::setRate(float rate)
399 {
400     m_mediaPlayer->setPlaybackRate(rate);
401 }
402
403 void MediaPlayerPrivateQt::setVolume(float volume)
404 {
405     m_mediaPlayer->setVolume(static_cast<int>(volume * 100.0));
406 }
407
408 bool MediaPlayerPrivateQt::supportsMuting() const
409 {
410     return true;
411 }
412
413 void MediaPlayerPrivateQt::setMuted(bool muted)
414 {
415     m_mediaPlayer->setMuted(muted);
416 }
417
418 MediaPlayer::NetworkState MediaPlayerPrivateQt::networkState() const
419 {
420     return m_networkState;
421 }
422
423 MediaPlayer::ReadyState MediaPlayerPrivateQt::readyState() const
424 {
425     return m_readyState;
426 }
427
428 void MediaPlayerPrivateQt::setVisible(bool visible)
429 {
430     m_isVisible = visible;
431 }
432
433 void MediaPlayerPrivateQt::mediaStatusChanged(QMediaPlayer::MediaStatus)
434 {
435     updateStates();
436 }
437
438 void MediaPlayerPrivateQt::handleError(QMediaPlayer::Error)
439 {
440     updateStates();
441 }
442
443 void MediaPlayerPrivateQt::stateChanged(QMediaPlayer::State state)
444 {
445     if (state != QMediaPlayer::PlayingState && m_isSeeking && m_queuedSeek >= 0) {
446         m_mediaPlayer->setPosition(m_queuedSeek);
447         m_queuedSeek = -1;
448     }
449 }
450
451 void MediaPlayerPrivateQt::nativeSizeChanged(const QSizeF& size)
452 {
453     LOG(Media, "MediaPlayerPrivateQt::naturalSizeChanged(%dx%d)",
454             size.toSize().width(), size.toSize().height());
455
456     if (!size.isValid())
457         return;
458
459     m_naturalSize = size.toSize();
460     m_webCorePlayer->sizeChanged();
461 }
462
463 void MediaPlayerPrivateQt::queuedSeekTimeout()
464 {
465     // If we haven't heard anything, assume the player is now paused
466     // and we can attempt the seek
467     if (m_isSeeking && m_queuedSeek >= 0) {
468         m_mediaPlayer->setPosition(m_queuedSeek);
469         m_queuedSeek = -1;
470
471         // Set a timeout, in case we don't get a position changed signal
472         QTimer::singleShot(10000, this, SLOT(seekTimeout()));
473     }
474 }
475
476 void MediaPlayerPrivateQt::seekTimeout()
477 {
478     // If we haven't heard anything, assume the seek succeeded
479     if (m_isSeeking) {
480         m_webCorePlayer->timeChanged();
481         m_isSeeking = false;
482     }
483 }
484
485 void MediaPlayerPrivateQt::positionChanged(qint64)
486 {
487     // Only propagate this event if we are seeking
488     if (m_isSeeking && m_queuedSeek == -1) {
489         m_webCorePlayer->timeChanged();
490         m_isSeeking = false;
491     }
492 }
493
494 void MediaPlayerPrivateQt::bufferStatusChanged(int)
495 {
496     notImplemented();
497 }
498
499 void MediaPlayerPrivateQt::durationChanged(qint64)
500 {
501     m_webCorePlayer->durationChanged();
502 }
503
504 void MediaPlayerPrivateQt::volumeChanged(int volume)
505 {
506     m_webCorePlayer->volumeChanged(static_cast<float>(volume) / 100.0);
507 }
508
509 void MediaPlayerPrivateQt::mutedChanged(bool muted)
510 {
511     m_webCorePlayer->muteChanged(muted);
512 }
513
514 void MediaPlayerPrivateQt::updateStates()
515 {
516     // Store the old states so that we can detect a change and raise change events
517     MediaPlayer::NetworkState oldNetworkState = m_networkState;
518     MediaPlayer::ReadyState oldReadyState = m_readyState;
519
520     QMediaPlayer::MediaStatus currentStatus = m_mediaPlayer->mediaStatus();
521     QMediaPlayer::Error currentError = m_mediaPlayer->error();
522
523     if (currentError != QMediaPlayer::NoError) {
524         m_readyState = MediaPlayer::HaveNothing;
525         if (currentError == QMediaPlayer::FormatError)
526             m_networkState = MediaPlayer::FormatError;
527         else
528             m_networkState = MediaPlayer::NetworkError;
529     } else if (currentStatus == QMediaPlayer::UnknownMediaStatus
530                || currentStatus == QMediaPlayer::NoMedia) {
531         m_networkState = MediaPlayer::Idle;
532         m_readyState = MediaPlayer::HaveNothing;
533     } else if (currentStatus == QMediaPlayer::LoadingMedia) {
534         m_networkState = MediaPlayer::Loading;
535         m_readyState = MediaPlayer::HaveNothing;
536     } else if (currentStatus == QMediaPlayer::LoadedMedia) {
537         m_networkState = MediaPlayer::Loading;
538         m_readyState = MediaPlayer::HaveMetadata;
539     } else if (currentStatus == QMediaPlayer::BufferingMedia) {
540         m_networkState = MediaPlayer::Loading;
541         m_readyState = MediaPlayer::HaveFutureData;
542     } else if (currentStatus == QMediaPlayer::StalledMedia) {
543         m_networkState = MediaPlayer::Loading;
544         m_readyState = MediaPlayer::HaveCurrentData;
545     } else if (currentStatus == QMediaPlayer::BufferedMedia
546                || currentStatus == QMediaPlayer::EndOfMedia) {
547         m_networkState = MediaPlayer::Idle;
548         m_readyState = MediaPlayer::HaveEnoughData;
549     } else if (currentStatus == QMediaPlayer::InvalidMedia) {
550         m_networkState = MediaPlayer::NetworkError;
551         m_readyState = MediaPlayer::HaveNothing;
552     }
553
554     // Log the state changes and raise the state change events
555     // NB: The readyStateChanged event must come before the networkStateChanged event.
556     // Breaking this invariant will cause the resource selection algorithm for multiple
557     // sources to fail.
558     if (m_readyState != oldReadyState)
559         m_webCorePlayer->readyStateChanged();
560
561     if (m_networkState != oldNetworkState)
562         m_webCorePlayer->networkStateChanged();
563 }
564
565 void MediaPlayerPrivateQt::setSize(const IntSize& size)
566 {
567     LOG(Media, "MediaPlayerPrivateQt::setSize(%dx%d)",
568             size.width(), size.height());
569
570     if (size == m_currentSize)
571         return;
572
573     m_currentSize = size;
574     m_videoItem->setSize(QSizeF(QSize(size)));
575 }
576
577 IntSize MediaPlayerPrivateQt::naturalSize() const
578 {
579     if (!hasVideo() ||  m_readyState < MediaPlayer::HaveMetadata) {
580         LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> 0x0 (!hasVideo || !haveMetaData)");
581         return IntSize();
582     }
583
584     LOG(Media, "MediaPlayerPrivateQt::naturalSize() -> %dx%d (m_naturalSize)",
585             m_naturalSize.width(), m_naturalSize.height());
586
587     return m_naturalSize;
588 }
589
590 void MediaPlayerPrivateQt::paint(GraphicsContext* context, const IntRect& rect)
591 {
592 #if USE(ACCELERATED_COMPOSITING)
593     if (m_composited)
594         return;
595 #endif
596     if (context->paintingDisabled())
597         return;
598
599     if (!m_isVisible)
600         return;
601
602     QPainter* painter = context->platformContext();
603     m_videoScene->render(painter, QRectF(QRect(rect)), m_videoItem->sceneBoundingRect());
604 }
605
606 void MediaPlayerPrivateQt::repaint()
607 {
608     m_webCorePlayer->repaint();
609 }
610
611 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER)
612
613 class TextureMapperVideoLayerQt : public virtual TextureMapperVideoLayer {
614 public:
615     TextureMapperVideoLayerQt(QGraphicsVideoItem* videoItem)
616         : m_videoItem(videoItem)
617     {
618     }
619
620     virtual void setPlatformLayerClient(TextureMapperLayerClient* client)
621     {
622         m_client = client;
623     }
624
625     virtual void paint(GraphicsContext* context)
626     {
627         if (!m_videoItem)
628             return;
629
630         QStyleOptionGraphicsItem opt;
631         opt.exposedRect = m_videoItem.data()->sceneBoundingRect();
632         opt.rect = opt.exposedRect.toRect();
633         m_videoItem.data()->paint(context->platformContext(), &opt);
634     }
635
636     virtual IntSize size() const
637     {
638         return m_videoItem ? IntSize(m_videoItem.data()->size().width(), m_videoItem.data()->size().height()) : IntSize();
639     }
640
641     QWeakPointer<QGraphicsVideoItem> m_videoItem;
642     TextureMapperLayerClient* m_client;
643 };
644
645
646 void MediaPlayerPrivateQt::acceleratedRenderingStateChanged()
647 {
648     MediaPlayerClient* client = m_webCorePlayer->mediaPlayerClient();
649     bool composited = client->mediaPlayerRenderingCanBeAccelerated(m_webCorePlayer);
650     if (composited == m_composited)
651         return;
652
653     m_composited = composited;
654     if (composited)
655         m_platformLayer = new TextureMapperVideoLayerQt(m_videoItem);
656 }
657
658 PlatformLayer* MediaPlayerPrivateQt::platformLayer() const
659 {
660     return m_composited ? m_platformLayer.get() : 0;
661 }
662 #endif
663
664 PlatformMedia MediaPlayerPrivateQt::platformMedia() const
665 {
666     PlatformMedia pm;
667     pm.type = PlatformMedia::QtMediaPlayerType;
668     pm.media.qtMediaPlayer = const_cast<MediaPlayerPrivateQt*>(this);
669     return pm;
670 }
671
672 } // namespace WebCore
673
674 #include "moc_MediaPlayerPrivateQt.cpp"