diff options
Diffstat (limited to 'src/plugins/winrt/qwinrtmediaplayercontrol.cpp')
-rw-r--r-- | src/plugins/winrt/qwinrtmediaplayercontrol.cpp | 900 |
1 files changed, 0 insertions, 900 deletions
diff --git a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp b/src/plugins/winrt/qwinrtmediaplayercontrol.cpp deleted file mode 100644 index 0ed9f027e..000000000 --- a/src/plugins/winrt/qwinrtmediaplayercontrol.cpp +++ /dev/null @@ -1,900 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwinrtmediaplayercontrol.h" -#include "qwinrtplayerrenderercontrol.h" - -#include <QtCore/QCoreApplication> -#include <QtCore/QFile> -#include <QtCore/qfunctions_winrt.h> -#include <QtCore/QSize> -#include <QtCore/QTimerEvent> -#include <QtCore/QUrl> -#include <QtMultimedia/QMediaPlaylist> -#include <QtConcurrent/QtConcurrentRun> - -#include <dxgi.h> -#include <OleAuto.h> -#include <mfapi.h> -#include <mfmediaengine.h> - -#include <wrl.h> -using namespace Microsoft::WRL; - -QT_BEGIN_NAMESPACE - -#define QT_WINRT_MEDIAPLAYER_STREAM_ID "__qtmultimedia_winrt_player_stream" - -class MediaEngineNotify; -class MediaEngineSources; -class MediaEngineByteStream; -class QWinRTMediaPlayerControlPrivate -{ -public: - QMediaPlayer::State state; - QMediaPlayer::MediaStatus mediaStatus; - qint64 duration; - qint64 position; - qreal playbackRate; - int volume; - bool muted; - int bufferStatus; - bool seekable; - bool hasVideo; - bool hasAudio; - - QMediaContent media; - QScopedPointer<QIODevice, QWinRTMediaPlayerControlPrivate> stream; - QWinRTPlayerRendererControl *videoRenderer; - - ComPtr<MediaEngineNotify> notifier; - ComPtr<MediaEngineSources> sources; - ComPtr<MediaEngineByteStream> streamProvider; - ComPtr<IMFAttributes> configuration; - ComPtr<IMFMediaEngineEx> engine; - - quint32 resetToken; - ComPtr<IMFDXGIDeviceManager> manager; - - // Automatically delete streams created by the player - static inline void cleanup(QIODevice *device) - { - if (device && device->property(QT_WINRT_MEDIAPLAYER_STREAM_ID).toBool()) - device->deleteLater(); - } - - // Allows for deferred cleanup of the engine, which tends to block on shutdown - static void cleanup(QWinRTMediaPlayerControlPrivate *d); - static void shutdown(QWinRTMediaPlayerControlPrivate *d); -}; - -class MediaEngineNotify : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IMFMediaEngineNotify> -{ -public: - MediaEngineNotify(QWinRTMediaPlayerControl *q_ptr, QWinRTMediaPlayerControlPrivate *d_ptr) - : q(q_ptr), d(d_ptr) - { - } - - HRESULT __stdcall EventNotify(DWORD event, DWORD_PTR param1, DWORD param2) - { - QMediaPlayer::State newState = d->state; - QMediaPlayer::MediaStatus newStatus = d->mediaStatus; - - switch (event) { - // Media change events - case MF_MEDIA_ENGINE_EVENT_LOADEDMETADATA: { - const bool hasAudio = d->engine->HasAudio(); - if (d->hasAudio != hasAudio) { - d->hasAudio = hasAudio; - emit q->audioAvailableChanged(d->hasAudio); - } - - const bool hasVideo = d->engine->HasVideo(); - if (d->hasVideo != hasVideo) { - d->hasVideo = hasVideo; - emit q->audioAvailableChanged(d->hasAudio); - } - - if (hasVideo) { - HRESULT hr; - DWORD width, height; - hr = d->engine->GetNativeVideoSize(&width, &height); - if (FAILED(hr)) - break; - d->videoRenderer->setSize(QSize(int(width), int(height))); - } - - newStatus = QMediaPlayer::LoadedMedia; - break; - } - case MF_MEDIA_ENGINE_EVENT_LOADSTART: - case MF_MEDIA_ENGINE_EVENT_PROGRESS: { - newStatus = QMediaPlayer::LoadingMedia; - break; - } - case MF_MEDIA_ENGINE_EVENT_CANPLAY: - d->bufferStatus = 100; // Fired when buffering is not used - newStatus = d->state == QMediaPlayer::StoppedState ? QMediaPlayer::LoadedMedia - : QMediaPlayer::BufferedMedia; - break; - case MF_MEDIA_ENGINE_EVENT_BUFFERINGSTARTED: - case MF_MEDIA_ENGINE_EVENT_BUFFERINGENDED: { - PROPVARIANT stat; - HRESULT hr = d->engine->GetStatistics(MF_MEDIA_ENGINE_STATISTIC_BUFFER_PROGRESS, &stat); - if (SUCCEEDED(hr)) { - d->bufferStatus = stat.lVal; - PropVariantClear(&stat); - } - newStatus = d->state == QMediaPlayer::StoppedState ? QMediaPlayer::LoadedMedia - : (d->bufferStatus == 100 ? QMediaPlayer::BufferedMedia : QMediaPlayer::BufferingMedia); - break; - } - //case MF_MEDIA_ENGINE_EVENT_SUSPEND: ??? - //case MF_MEDIA_ENGINE_EVENT_ABORT: ??? - case MF_MEDIA_ENGINE_EVENT_EMPTIED: { - newState = QMediaPlayer::StoppedState; - break; - } - // Transport controls - case MF_MEDIA_ENGINE_EVENT_PLAY: { - // If the media is already loaded, the playing event may not occur after stop - if (d->mediaStatus != QMediaPlayer::LoadedMedia) - break; - Q_FALLTHROUGH(); - } - case MF_MEDIA_ENGINE_EVENT_PLAYING: { - newState = QMediaPlayer::PlayingState; - newStatus = d->bufferStatus < 100 ? QMediaPlayer::BufferingMedia - : QMediaPlayer::BufferedMedia; - break; - } - case MF_MEDIA_ENGINE_EVENT_PAUSE: { - newState = QMediaPlayer::PausedState; - break; - } - case MF_MEDIA_ENGINE_EVENT_STALLED: { - newStatus = QMediaPlayer::StalledMedia; - break; - } - case MF_MEDIA_ENGINE_EVENT_WAITING: { - newStatus = QMediaPlayer::StalledMedia; - break; - } - case MF_MEDIA_ENGINE_EVENT_ENDED: { - newState = QMediaPlayer::StoppedState; - newStatus = QMediaPlayer::EndOfMedia; - break; - } - // Media attributes - case MF_MEDIA_ENGINE_EVENT_DURATIONCHANGE: { - double duration = d->engine->GetDuration() * 1000; - if (!qFuzzyCompare(d->duration, duration)) { - d->duration = qint64(duration); - emit q->durationChanged(d->duration); - } - break; - } - case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE: { - double position = d->engine->GetCurrentTime() * 1000; - if (!qFuzzyCompare(d->position, position)) { - d->position = qint64(position); - emit q->positionChanged(d->position); - } - // Stopped state: paused at beginning - if (qFuzzyIsNull(position) && d->state == QMediaPlayer::PausedState) - newState = QMediaPlayer::StoppedState; - break; - } - case MF_MEDIA_ENGINE_EVENT_RATECHANGE: { - double playbackRate = d->engine->GetPlaybackRate(); - if (!qFuzzyCompare(d->playbackRate, playbackRate)) { - d->playbackRate = playbackRate; - emit q->playbackRateChanged(d->playbackRate); - } - break; - } - // Error handling - case MF_MEDIA_ENGINE_EVENT_ERROR: { - newState = QMediaPlayer::StoppedState; - newStatus = QMediaPlayer::InvalidMedia; - switch (param1) { - default: - case MF_MEDIA_ENGINE_ERR_NOERROR: - newStatus = QMediaPlayer::UnknownMediaStatus; - emit q->error(QMediaPlayer::ResourceError, qt_error_string(int(param2))); - break; - case MF_MEDIA_ENGINE_ERR_ABORTED: - if (d->mediaStatus == QMediaPlayer::StalledMedia || d->mediaStatus == QMediaPlayer::BufferingMedia) - d->mediaStatus = QMediaPlayer::LoadedMedia; - emit q->error(QMediaPlayer::ResourceError, QStringLiteral("The process of fetching the media resource was stopped at the user's request.")); - break; - case MF_MEDIA_ENGINE_ERR_NETWORK: - if (d->mediaStatus == QMediaPlayer::StalledMedia || d->mediaStatus == QMediaPlayer::BufferingMedia) - d->mediaStatus = QMediaPlayer::LoadedMedia; - emit q->error(QMediaPlayer::NetworkError, QStringLiteral("A network error occurred while fetching the media resource.")); - break; - case MF_MEDIA_ENGINE_ERR_DECODE: - emit q->error(QMediaPlayer::FormatError, QStringLiteral("An error occurred while decoding the media resource.")); - break; - case MF_MEDIA_ENGINE_ERR_SRC_NOT_SUPPORTED: - emit q->error(QMediaPlayer::FormatError, QStringLiteral("The media resource is not supported.")); - break; - case MF_MEDIA_ENGINE_ERR_ENCRYPTED: - emit q->error(QMediaPlayer::FormatError, QStringLiteral("An error occurred while encrypting the media resource.")); - break; - } - break; - } - default: - break; - } - - if (d->videoRenderer) - d->videoRenderer->setActive(d->state == QMediaPlayer::PlayingState && - d->videoRenderer->size().isValid()); - - const QMediaPlayer::MediaStatus oldMediaStatus = d->mediaStatus; - const QMediaPlayer::State oldState = d->state; - d->mediaStatus = newStatus; - d->state = newState; - - if (d->mediaStatus != oldMediaStatus) - emit q->mediaStatusChanged(d->mediaStatus); - - if (d->state != oldState) - emit q->stateChanged(d->state); - - return S_OK; - } - -private: - QWinRTMediaPlayerControl *q; - QWinRTMediaPlayerControlPrivate *d; -}; - -class MediaEngineSources : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IMFMediaEngineSrcElements> -{ -public: - MediaEngineSources(QWinRTMediaPlayerControlPrivate *d_ptr) - : d(d_ptr) - { - } - - DWORD __stdcall GetLength() - { - return 1; - } - - HRESULT __stdcall GetURL(DWORD index, BSTR *url) - { - Q_UNUSED(index); - const QString resourceUrl = d->media.request().url().toString(); - *url = SysAllocString((const OLECHAR *)resourceUrl.utf16()); - return S_OK; - } - - HRESULT __stdcall GetType(DWORD index, BSTR *type) - { - Q_UNUSED(index); - *type = SysAllocString(L""); - return S_OK; - } - - HRESULT __stdcall GetMedia(DWORD index, BSTR *media) - { - Q_UNUSED(index); - *media = nullptr; - return S_OK; - } - - HRESULT __stdcall AddElement(BSTR url, BSTR type, BSTR media) - { - Q_UNUSED(url); - Q_UNUSED(type); - Q_UNUSED(media); - return E_NOTIMPL; - } - - HRESULT __stdcall RemoveAllElements() - { - return E_NOTIMPL; - } - -private: - QWinRTMediaPlayerControlPrivate *d; -}; - -class MediaEngineReadResult : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IUnknown> -{ -public: - MediaEngineReadResult(BYTE *bytes, ULONG maxLength) - : bytes(bytes), maxLength(maxLength) { } - - void read(QIODevice *device) - { - bytesRead = ULONG(device->read(reinterpret_cast<char *>(bytes), maxLength)); - } - - BYTE *bytes; - ULONG maxLength; - ULONG bytesRead; -}; - -class MediaEngineByteStream : public RuntimeClass<RuntimeClassFlags<ClassicCom>, IMFByteStream> -{ -public: - MediaEngineByteStream(QWinRTMediaPlayerControlPrivate *d_ptr) - : d(d_ptr) - { - } - - HRESULT __stdcall GetCapabilities(DWORD *capabilities) - { - *capabilities |= MFBYTESTREAM_IS_READABLE; - if (!d->stream->isSequential()) - *capabilities |= MFBYTESTREAM_IS_SEEKABLE; - return S_OK; - } - - HRESULT __stdcall GetLength(QWORD *length) - { - *length = QWORD(d->stream->size()); - return S_OK; - } - - HRESULT __stdcall SetLength(QWORD length) - { - Q_UNUSED(length); - return E_NOTIMPL; - } - - HRESULT __stdcall GetCurrentPosition(QWORD *position) - { - *position = QWORD(d->stream->pos()); - return S_OK; - } - - HRESULT __stdcall SetCurrentPosition(QWORD position) - { - const qint64 pos = qint64(position); - if (pos >= d->stream->size()) { - // MSDN states we should return E_INVALIDARG, but that immediately - // stops playback and does not play remaining buffers in the queue. - // For some formats this can cause losing up to 5 seconds of the - // end of the stream. - return S_FALSE; - } - - const bool ok = d->stream->seek(pos); - return ok ? S_OK : S_FALSE; - } - - HRESULT __stdcall IsEndOfStream(BOOL *endOfStream) - { - *endOfStream = d->stream->atEnd() ? TRUE : FALSE; - return S_OK; - } - - HRESULT __stdcall Read(BYTE *bytes, ULONG maxlen, ULONG *bytesRead) - { - *bytesRead = ULONG(d->stream->read(reinterpret_cast<char *>(bytes), maxlen)); - return S_OK; - } - - HRESULT __stdcall BeginRead(BYTE *bytes, ULONG maxLength, IMFAsyncCallback *callback, IUnknown *state) - { - ComPtr<MediaEngineReadResult> readResult = Make<MediaEngineReadResult>(bytes, maxLength); - HRESULT hr; - hr = MFCreateAsyncResult(readResult.Get(), callback, state, &asyncResult); - RETURN_HR_IF_FAILED("Failed to create read callback result"); - finishRead(); - return S_OK; - } - - HRESULT __stdcall EndRead(IMFAsyncResult *result, ULONG *bytesRead) - { - HRESULT hr; - ComPtr<MediaEngineReadResult> readResult; - hr = result->GetObject(&readResult); - RETURN_HR_IF_FAILED("Failed to get read result"); - - *bytesRead = readResult->bytesRead; - return S_OK; - } - - HRESULT __stdcall Write(const BYTE *bytes, ULONG maxlen, ULONG *bytesWritten) - { - Q_UNUSED(bytes); - Q_UNUSED(maxlen); - Q_UNUSED(bytesWritten); - return E_NOTIMPL; - } - - HRESULT __stdcall BeginWrite(const BYTE *bytes, ULONG maxlen, IMFAsyncCallback *callback, IUnknown *state) - { - Q_UNUSED(bytes); - Q_UNUSED(maxlen); - Q_UNUSED(callback); - Q_UNUSED(state); - return E_NOTIMPL; - } - - HRESULT __stdcall EndWrite(IMFAsyncResult *result, ULONG *bytesWritten) - { - Q_UNUSED(result); - Q_UNUSED(bytesWritten); - return E_NOTIMPL; - } - - HRESULT __stdcall Seek(MFBYTESTREAM_SEEK_ORIGIN origin, LONGLONG offset, DWORD flags, QWORD *position) - { - Q_UNUSED(flags); - - qint64 pos = offset; - if (origin == msoCurrent) - pos += d->stream->pos(); - - const bool ok = d->stream->seek(pos); - *position = QWORD(d->stream->pos()); - - return ok ? S_OK : E_FAIL; - } - - HRESULT __stdcall Flush() - { - return E_NOTIMPL; - } - - HRESULT __stdcall Close() - { - if (asyncResult) - finishRead(); - - if (d->stream->property(QT_WINRT_MEDIAPLAYER_STREAM_ID).toBool()) - d->stream->close(); - - return S_OK; - } - - void finishRead() - { - if (!asyncResult) - return; - - HRESULT hr; - ComPtr<MediaEngineReadResult> readResult; - hr = asyncResult->GetObject(&readResult); - RETURN_VOID_IF_FAILED("Failed to get read result object"); - readResult->read(d->stream.data()); - hr = MFInvokeCallback(asyncResult.Get()); - RETURN_VOID_IF_FAILED("Failed to invoke read callback"); - asyncResult.Reset(); - } - -private: - QWinRTMediaPlayerControlPrivate *d; - - ComPtr<IMFAsyncResult> asyncResult; -}; - -void QWinRTMediaPlayerControlPrivate::cleanup(QWinRTMediaPlayerControlPrivate *d) -{ - QtConcurrent::run(&QWinRTMediaPlayerControlPrivate::shutdown, d); -} - -void QWinRTMediaPlayerControlPrivate::shutdown(QWinRTMediaPlayerControlPrivate *d) -{ - d->engine->Shutdown(); - delete d; -} - -QWinRTMediaPlayerControl::QWinRTMediaPlayerControl(IMFMediaEngineClassFactory *factory, QObject *parent) - : QMediaPlayerControl(parent), d_ptr(new QWinRTMediaPlayerControlPrivate) -{ - Q_D(QWinRTMediaPlayerControl); - - d->state = QMediaPlayer::StoppedState; - d->mediaStatus = QMediaPlayer::NoMedia; - d->duration = 0; - d->position = 0; - d->playbackRate = 1.0; - d->volume = 100; - d->bufferStatus = 0; - d->muted = false; - d->seekable = false; - d->hasAudio = false; - d->hasVideo = false; - d->videoRenderer = nullptr; - d->notifier = Make<MediaEngineNotify>(this, d); - - HRESULT hr; - hr = MFCreateDXGIDeviceManager(&d->resetToken, &d->manager); - RETURN_VOID_IF_FAILED("Failed to create DXGI device manager"); - - hr = MFCreateAttributes(&d->configuration, 1); - Q_ASSERT_SUCCEEDED(hr); - hr = d->configuration->SetUnknown(MF_MEDIA_ENGINE_CALLBACK, d->notifier.Get()); - Q_ASSERT_SUCCEEDED(hr); - hr = d->configuration->SetUnknown(MF_MEDIA_ENGINE_DXGI_MANAGER, d->manager.Get()); - Q_ASSERT_SUCCEEDED(hr); - hr = d->configuration->SetUINT32(MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT, DXGI_FORMAT_B8G8R8A8_UNORM); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr<IMFMediaEngine> engine; - hr = factory->CreateInstance(0, d->configuration.Get(), &engine); - Q_ASSERT_SUCCEEDED(hr); - hr = engine.As(&d->engine); - Q_ASSERT_SUCCEEDED(hr); - - hr = d->engine->SetVolume(1.0); - Q_ASSERT_SUCCEEDED(hr); - - d->sources = Make<MediaEngineSources>(d); - hr = d->engine->SetSourceElements(d->sources.Get()); - Q_ASSERT_SUCCEEDED(hr); - - d->streamProvider = Make<MediaEngineByteStream>(d); -} - -QMediaPlayer::State QWinRTMediaPlayerControl::state() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->state; -} - -QMediaPlayer::MediaStatus QWinRTMediaPlayerControl::mediaStatus() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->mediaStatus; -} - -qint64 QWinRTMediaPlayerControl::duration() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->duration; -} - -qint64 QWinRTMediaPlayerControl::position() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->position; -} - -void QWinRTMediaPlayerControl::setPosition(qint64 position) -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->position == position) - return; - - HRESULT hr; - hr = d->engine->SetCurrentTime(double(position)/1000); - RETURN_VOID_IF_FAILED("Failed to seek to new position"); - - d->position = position; - emit positionChanged(d->position); - - if (d->mediaStatus == QMediaPlayer::EndOfMedia) { - d->mediaStatus = QMediaPlayer::LoadedMedia; - emit mediaStatusChanged(d->mediaStatus); - } -} - -int QWinRTMediaPlayerControl::volume() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->volume; -} - -void QWinRTMediaPlayerControl::setVolume(int volume) -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->volume == volume) - return; - - HRESULT hr; - hr = d->engine->SetVolume(double(volume)/100); - RETURN_VOID_IF_FAILED("Failed to set volume"); - - d->volume = volume; - emit volumeChanged(d->volume); -} - -bool QWinRTMediaPlayerControl::isMuted() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->muted; -} - -void QWinRTMediaPlayerControl::setMuted(bool muted) -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->muted == muted) - return; - - HRESULT hr; - hr = d->engine->SetMuted(muted); - RETURN_VOID_IF_FAILED("Failed to mute volume"); - - d->muted = muted; - emit mutedChanged(d->muted); -} - -int QWinRTMediaPlayerControl::bufferStatus() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->bufferStatus; -} - -bool QWinRTMediaPlayerControl::isAudioAvailable() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->hasAudio; -} - -bool QWinRTMediaPlayerControl::isVideoAvailable() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->hasVideo; -} - -bool QWinRTMediaPlayerControl::isSeekable() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->seekable; -} - -QMediaTimeRange QWinRTMediaPlayerControl::availablePlaybackRanges() const -{ - Q_D(const QWinRTMediaPlayerControl); - return QMediaTimeRange(0, d->duration); -} - -qreal QWinRTMediaPlayerControl::playbackRate() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->playbackRate; -} - -void QWinRTMediaPlayerControl::setPlaybackRate(qreal rate) -{ - Q_D(QWinRTMediaPlayerControl); - - if (qFuzzyCompare(d->playbackRate, rate)) - return; - - HRESULT hr; - hr = d->engine->SetPlaybackRate(rate); - RETURN_VOID_IF_FAILED("Failed to set playback rate"); -} - -QMediaContent QWinRTMediaPlayerControl::media() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->media; -} - -const QIODevice *QWinRTMediaPlayerControl::mediaStream() const -{ - Q_D(const QWinRTMediaPlayerControl); - return d->stream.data(); -} - -void QWinRTMediaPlayerControl::setMedia(const QMediaContent &media, QIODevice *stream) -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->media == media && d->stream.data() == stream) - return; - - d->media = media; - d->stream.reset(stream); - if (d->hasAudio != false) { - d->hasAudio = false; - emit audioAvailableChanged(d->hasAudio); - } - if (d->hasVideo != false) { - d->hasVideo = false; - emit videoAvailableChanged(d->hasVideo); - } - if (d->seekable != false) { - d->seekable = false; - emit seekableChanged(d->seekable); - } - if (d->bufferStatus != 0) { - d->bufferStatus = 0; - emit bufferStatusChanged(d->bufferStatus); - } - if (d->position != 0) { - d->position = 0; - emit positionChanged(d->position); - } - if (d->duration != 0) { - d->duration = 0; - emit durationChanged(d->duration); - } - QMediaPlayer::MediaStatus mediaStatus = media.isNull() ? QMediaPlayer::NoMedia - : QMediaPlayer::LoadingMedia; - if (d->mediaStatus != mediaStatus) { - d->mediaStatus = mediaStatus; - emit mediaStatusChanged(d->mediaStatus); - } - emit mediaChanged(media); - - QString urlString = media.request().url().toString(); - if (!d->stream) { - // If we can read the file via Qt, use the byte stream approach - if (media.request().url().isLocalFile()) { - urlString = media.request().url().toLocalFile(); - QScopedPointer<QFile> file(new QFile(urlString)); - if (file->open(QFile::ReadOnly)) { - file->setProperty(QT_WINRT_MEDIAPLAYER_STREAM_ID, true); - d->stream.reset(file.take()); - } - } - } - - HRESULT hr; - if (d->stream) { - hr = d->engine->SetSourceFromByteStream(d->streamProvider.Get(), - reinterpret_cast<BSTR>(urlString.data())); - if (FAILED(hr)) { - emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); - return; - } - if (d->videoRenderer) - d->videoRenderer->ensureReady(); - return; - } - - // Let Windows handle all other URLs - hr = d->engine->SetSource(nullptr); // Resets the byte stream - Q_ASSERT_SUCCEEDED(hr); - hr = d->engine->Load(); - if (FAILED(hr)) - emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); - - if (d->media.isNull() && d->stream.isNull()) - return; - - // Resume play/pause/stop - switch (d->state) { - case QMediaPlayer::StoppedState: - stop(); - break; - case QMediaPlayer::PlayingState: - play(); - break; - case QMediaPlayer::PausedState: - pause(); - break; - } -} - -void QWinRTMediaPlayerControl::play() -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->state != QMediaPlayer::PlayingState) { - d->state = QMediaPlayer::PlayingState; - emit stateChanged(d->state); - } - - if (d->media.isNull() && d->stream.isNull()) - return; - - if (d->videoRenderer) - d->videoRenderer->ensureReady(); - - HRESULT hr = d->engine->Play(); - if (FAILED(hr)) { - emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); - return; - } -} - -void QWinRTMediaPlayerControl::pause() -{ - Q_D(QWinRTMediaPlayerControl); - - if (d->state != QMediaPlayer::PausedState) { - d->state = QMediaPlayer::PausedState; - emit stateChanged(d->state); - } - - if (d->media.isNull() && d->stream.isNull()) - return; - - HRESULT hr; - hr = d->engine->Pause(); - if (FAILED(hr)) { - emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); - return; - } -} - -void QWinRTMediaPlayerControl::stop() -{ - Q_D(QWinRTMediaPlayerControl); - - const QMediaPlayer::MediaStatus oldMediaStatus = d->mediaStatus; - const QMediaPlayer::State oldState = d->state; - - d->state = QMediaPlayer::StoppedState; - - if (d->mediaStatus == QMediaPlayer::BufferedMedia - || d->mediaStatus == QMediaPlayer::BufferingMedia) { - d->mediaStatus = QMediaPlayer::LoadedMedia; - } - - if (d->mediaStatus != oldMediaStatus) - emit mediaStatusChanged(d->mediaStatus); - - if (d->state != oldState) - emit stateChanged(d->state); - - if (d->media.isNull() && d->stream.isNull()) - return; - - setPosition(0); - - HRESULT hr; - hr = d->engine->Pause(); - if (FAILED(hr)) { - emit error(QMediaPlayer::ResourceError, qt_error_string(hr)); - return; - } -} - -QVideoRendererControl *QWinRTMediaPlayerControl::videoRendererControl() -{ - Q_D(QWinRTMediaPlayerControl); - - if (!d->videoRenderer) { - d->videoRenderer = new QWinRTPlayerRendererControl(d->engine.Get(), d->manager.Get(), - d->resetToken, this); - } - - return d->videoRenderer; -} - -QT_END_NAMESPACE |