diff options
Diffstat (limited to 'src/plugins/wmp')
23 files changed, 4379 insertions, 0 deletions
diff --git a/src/plugins/wmp/qevrvideooverlay.cpp b/src/plugins/wmp/qevrvideooverlay.cpp new file mode 100644 index 000000000..ff301d109 --- /dev/null +++ b/src/plugins/wmp/qevrvideooverlay.cpp @@ -0,0 +1,357 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qevrvideooverlay.h" + +#include <d3d9.h> +#include <wmp.h> + +QEvrVideoOverlay::QEvrVideoOverlay(HINSTANCE evrHwnd) + : m_ref(1) + , m_evrHwnd(evrHwnd) + , ptrMFCreateVideoPresenter(0) + , m_presenter(0) + , m_displayControl(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_winId(0) + , m_fullScreen(0) +{ + ptrMFCreateVideoPresenter = reinterpret_cast<PtrMFCreateVideoPresenter>( + GetProcAddress(m_evrHwnd, "MFCreateVideoPresenter")); +} + +QEvrVideoOverlay::~QEvrVideoOverlay() +{ + FreeLibrary(m_evrHwnd); +} + +WId QEvrVideoOverlay::winId() const +{ + return m_winId; +} + +void QEvrVideoOverlay::setWinId(WId id) +{ + m_winId = id; + + if (QWidget *widget = QWidget::find(m_winId)) { + const QColor color = widget->palette().color(QPalette::Window); + + m_windowColor = RGB(color.red(), color.green(), color.blue()); + } + + if (m_displayControl) { + m_displayControl->SetVideoWindow(id); + m_displayControl->SetAspectRatioMode(m_aspectRatioMode == Qt::KeepAspectRatio + ? MFVideoARMode_PreservePicture + : MFVideoARMode_None); + m_displayControl->SetBorderColor(m_windowColor); + + setDisplayRect(m_displayRect); + } +} + +QRect QEvrVideoOverlay::displayRect() const +{ + return m_displayRect; +} + +void QEvrVideoOverlay::setDisplayRect(const QRect &rect) +{ + if (m_displayControl) { + RECT displayRect = { rect.left(), rect.top(), rect.right() + 1, rect.bottom() + 1 }; + + if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) { + SIZE size; + m_displayControl->GetNativeVideoSize(&size, 0); + + QSize clippedSize = rect.size(); + clippedSize.scale(size.cx, size.cy, Qt::KeepAspectRatio); + + long x = (size.cx - clippedSize.width()) / 2; + long y = (size.cy - clippedSize.height()) / 2; + + MFVideoNormalizedRect sourceRect = + { + float(x) / size.cx, + float(y) / size.cy, + float(x + clippedSize.width()) / size.cx, + float(y + clippedSize.height()) / size.cy + }; + m_displayControl->SetVideoPosition(&sourceRect, &displayRect); + } else { + m_displayControl->SetVideoPosition(0, &displayRect); + } + } + + m_displayRect = rect; +} + +bool QEvrVideoOverlay::isFullScreen() const +{ + return m_fullScreen; +} + +void QEvrVideoOverlay::setFullScreen(bool fullScreen) +{ + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +QSize QEvrVideoOverlay::nativeSize() const +{ + SIZE size; + + if (m_displayControl && m_displayControl->GetNativeVideoSize(&size, 0) == S_OK) { + return QSize(size.cx, size.cy); + } else { + return QSize(); + } +} + +Qt::AspectRatioMode QEvrVideoOverlay::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QEvrVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + + if (m_displayControl) { + m_displayControl->SetAspectRatioMode(mode == Qt::KeepAspectRatio + ? MFVideoARMode_PreservePicture + : MFVideoARMode_None); + setDisplayRect(m_displayRect); + } +} + +void QEvrVideoOverlay::repaint() +{ + PAINTSTRUCT paint; + + if (HDC dc = ::BeginPaint(m_winId, &paint)) { + if (m_displayControl) { + m_displayControl->RepaintVideo(); + } else { + HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor); + HBRUSH brush = ::CreateSolidBrush(m_windowColor); + ::SelectObject(dc, pen); + ::SelectObject(dc, brush); + + ::Rectangle( + dc, + paint.rcPaint.left, + paint.rcPaint.top, + paint.rcPaint.right, + paint.rcPaint.bottom); + + ::DeleteObject(pen); + ::DeleteObject(brush); + } + + ::EndPaint(m_winId, &paint); + } +} + +int QEvrVideoOverlay::brightness() const +{ + return 0; +} + +void QEvrVideoOverlay::setBrightness(int) +{ +} + +int QEvrVideoOverlay::contrast() const +{ + return 0; +} + +void QEvrVideoOverlay::setContrast(int) +{ +} + +int QEvrVideoOverlay::hue() const +{ + return 0; +} + +void QEvrVideoOverlay::setHue(int) +{ +} + +int QEvrVideoOverlay::saturation() const +{ + return 0; +} + +void QEvrVideoOverlay::setSaturation(int) +{ +} + +void QEvrVideoOverlay::setDisplayControl(IMFVideoDisplayControl *control) +{ + if (m_displayControl) + m_displayControl->Release(); + + m_displayControl = control; + + if (m_displayControl) { + m_displayControl->AddRef(); + m_displayControl->SetVideoWindow(m_winId); + m_displayControl->SetAspectRatioMode(m_aspectRatioMode == Qt::KeepAspectRatio + ? MFVideoARMode_PreservePicture + : MFVideoARMode_None); + m_displayControl->SetBorderColor(m_windowColor); + + setDisplayRect(m_displayRect); + } +} + +void QEvrVideoOverlay::openStateChanged(long state) +{ + if (state == wmposMediaOpen) { + setDisplayRect(m_displayRect); + + emit nativeSizeChanged(); + } +}; + +// IUnknown +HRESULT QEvrVideoOverlay::QueryInterface(REFIID riid, void **object) +{ + if (!object) { + return E_POINTER; + } else if (riid == __uuidof(IUnknown) + || riid == __uuidof(IMFAttributes) + || riid == __uuidof(IMFActivate)) { + *object = static_cast<IMFActivate *>(this); + } else { + return E_NOINTERFACE; + } + + AddRef(); + + return S_OK; +} + +ULONG QEvrVideoOverlay::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG QEvrVideoOverlay::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + Q_ASSERT(ref != 0); + + return ref; +} + +// IMFActivate +HRESULT QEvrVideoOverlay::ActivateObject(REFIID riid, void **ppv) +{ + if (riid != __uuidof(IMFVideoPresenter)) { + return E_NOINTERFACE; + } else if (!ptrMFCreateVideoPresenter) { + return E_NOINTERFACE; + } else if (m_presenter) { + *ppv = m_presenter; + + return S_OK; + } else { + IMFVideoDisplayControl *displayControl = 0; + + IMFGetService *service; + HRESULT hr; + if ((hr = (*ptrMFCreateVideoPresenter)( + 0, + __uuidof(IDirect3DDevice9), + __uuidof(IMFVideoPresenter), + reinterpret_cast<void **>(&m_presenter))) != S_OK) { + qWarning("failed to create video presenter"); + } else if ((hr = m_presenter->QueryInterface( + __uuidof(IMFGetService), reinterpret_cast<void **>(&service))) != S_OK) { + qWarning("failed to query IMFGetService interface"); + } else { + if ((hr = service->GetService( + MR_VIDEO_RENDER_SERVICE, + __uuidof(IMFVideoDisplayControl), + reinterpret_cast<void **>(&displayControl))) != S_OK) { + qWarning("failed to get IMFVideoDisplayControl service"); + } + service->Release(); + } + + setDisplayControl(displayControl); + + if (m_presenter && hr != S_OK) { + m_presenter->Release(); + m_presenter = 0; + } + + *ppv = m_presenter; + + return hr; + } +} + +HRESULT QEvrVideoOverlay::ShutdownObject() +{ + setDisplayControl(0); + + if (m_presenter) { + m_presenter->Release(); + m_presenter = 0; + } + return S_OK; +} + +HRESULT QEvrVideoOverlay::DetachObject() +{ + if (m_presenter) { + m_presenter->Release(); + m_presenter = 0; + } + + return S_OK; +} diff --git a/src/plugins/wmp/qevrvideooverlay.h b/src/plugins/wmp/qevrvideooverlay.h new file mode 100644 index 000000000..247b16e96 --- /dev/null +++ b/src/plugins/wmp/qevrvideooverlay.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QEVRVIDEOOVERLAY_H +#define QEVRVIDEOOVERLAY_H + +#include <qvideowindowcontrol.h> + +#include "qmfactivate.h" + +#include <evr.h> + +QT_USE_NAMESPACE + +class QEvrVideoOverlay : public QVideoWindowControl, public QMFActivate +{ + Q_OBJECT +public: + QEvrVideoOverlay(HINSTANCE evrHwnd); + ~QEvrVideoOverlay(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + QSize nativeSize() const; + + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode mode); + + void repaint(); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + void setDisplayControl(IMFVideoDisplayControl *control); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IMFActivate + HRESULT STDMETHODCALLTYPE ActivateObject(REFIID riid, void **ppv); + HRESULT STDMETHODCALLTYPE ShutdownObject(); + HRESULT STDMETHODCALLTYPE DetachObject(); + +public Q_SLOTS: + void openStateChanged(long state); + +private: + typedef HRESULT (WINAPI *PtrMFCreateVideoPresenter)(IUnknown*, REFIID, REFIID, void**); + + volatile LONG m_ref; + HINSTANCE m_evrHwnd; + PtrMFCreateVideoPresenter ptrMFCreateVideoPresenter; + IMFVideoPresenter *m_presenter; + IMFVideoDisplayControl *m_displayControl; + Qt::AspectRatioMode m_aspectRatioMode; + QSize m_sizeHint; + QRect m_displayRect; + WId m_winId; + COLORREF m_windowColor; + bool m_fullScreen; +}; + +#endif diff --git a/src/plugins/wmp/qmfactivate.cpp b/src/plugins/wmp/qmfactivate.cpp new file mode 100644 index 000000000..8cd64b0e4 --- /dev/null +++ b/src/plugins/wmp/qmfactivate.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qmfactivate.h" + +#include <QtCore/qglobal.h> + +#include <Mferror.h> + + +// IMFAttributes + +HRESULT QMFActivate::GetItem(REFGUID guidKey, PROPVARIANT *pValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pType); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult) +{ + Q_UNUSED(guidKey); + Q_UNUSED(Value); + Q_UNUSED(pbResult); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult) +{ + Q_UNUSED(pTheirs); + Q_UNUSED(MatchType); + Q_UNUSED(pbResult); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::GetUINT32(REFGUID guidKey, UINT32 *punValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(punValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetUINT64(REFGUID guidKey, UINT64 *punValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(punValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetDouble(REFGUID guidKey, double *pfValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pfValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetGUID(REFGUID guidKey, GUID *pguidValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pguidValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetStringLength(REFGUID guidKey, UINT32 *pcchLength) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pcchLength); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pwszValue); + Q_UNUSED(cchBufSize); + Q_UNUSED(pcchLength); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength) +{ + Q_UNUSED(guidKey); + Q_UNUSED(ppwszValue); + Q_UNUSED(pcchLength); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pcbBlobSize); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pBuf); + Q_UNUSED(cbBufSize); + Q_UNUSED(pcbBlobSize); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize) +{ + Q_UNUSED(guidKey); + Q_UNUSED(ppBuf); + Q_UNUSED(pcbSize); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv) +{ + Q_UNUSED(guidKey); + Q_UNUSED(riid); + Q_UNUSED(ppv); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::SetItem(REFGUID guidKey, REFPROPVARIANT Value) +{ + Q_UNUSED(guidKey); + Q_UNUSED(Value); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::DeleteItem(REFGUID guidKey) +{ + Q_UNUSED(guidKey); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::DeleteAllItems() +{ + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetUINT32(REFGUID guidKey, UINT32 unValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(unValue); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetUINT64(REFGUID guidKey, UINT64 unValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(unValue); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetDouble(REFGUID guidKey, double fValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(fValue); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetGUID(REFGUID guidKey, REFGUID guidValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(guidValue); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetString(REFGUID guidKey, LPCWSTR wszValue) +{ + Q_UNUSED(guidKey); + Q_UNUSED(wszValue); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pBuf); + Q_UNUSED(cbBufSize); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::SetUnknown(REFGUID guidKey, IUnknown *pUnknown) +{ + Q_UNUSED(guidKey); + Q_UNUSED(pUnknown); + + return E_NOTIMPL; +} + +HRESULT QMFActivate::LockStore() +{ + m_mutex.lock(); + + return S_OK; +} + +HRESULT QMFActivate::UnlockStore() +{ + m_mutex.unlock(); + + return S_OK; +} + +HRESULT QMFActivate::GetCount(UINT32 *pcItems) +{ + if (!pcItems) { + return E_POINTER; + } else { + *pcItems = 0; + + return S_OK; + } +} + +HRESULT QMFActivate::GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue) +{ + Q_UNUSED(unIndex); + Q_UNUSED(pguidKey); + Q_UNUSED(pValue); + + return MF_E_ATTRIBUTENOTFOUND; +} + +HRESULT QMFActivate::CopyAllItems(IMFAttributes *pDest) +{ + Q_UNUSED(pDest); + + return MF_E_ATTRIBUTENOTFOUND; +} diff --git a/src/plugins/wmp/qmfactivate.h b/src/plugins/wmp/qmfactivate.h new file mode 100644 index 000000000..0e1692689 --- /dev/null +++ b/src/plugins/wmp/qmfactivate.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QMFACTIVATE_H +#define QMFACTIVATE_H + +#include <QtCore/qmutex.h> + +#include <evr.h> + +class QMFActivate : public IMFActivate +{ +public: + // IMFAttributes + HRESULT STDMETHODCALLTYPE GetItem(REFGUID guidKey, PROPVARIANT *pValue); + HRESULT STDMETHODCALLTYPE GetItemType(REFGUID guidKey, MF_ATTRIBUTE_TYPE *pType); + HRESULT STDMETHODCALLTYPE CompareItem(REFGUID guidKey, REFPROPVARIANT Value, BOOL *pbResult); + HRESULT STDMETHODCALLTYPE Compare(IMFAttributes *pTheirs, MF_ATTRIBUTES_MATCH_TYPE MatchType, BOOL *pbResult); + HRESULT STDMETHODCALLTYPE GetUINT32(REFGUID guidKey, UINT32 *punValue); + HRESULT STDMETHODCALLTYPE GetUINT64(REFGUID guidKey, UINT64 *punValue); + HRESULT STDMETHODCALLTYPE GetDouble(REFGUID guidKey, double *pfValue); + HRESULT STDMETHODCALLTYPE GetGUID(REFGUID guidKey, GUID *pguidValue); + HRESULT STDMETHODCALLTYPE GetStringLength(REFGUID guidKey, UINT32 *pcchLength); + HRESULT STDMETHODCALLTYPE GetString(REFGUID guidKey, LPWSTR pwszValue, UINT32 cchBufSize, UINT32 *pcchLength); + HRESULT STDMETHODCALLTYPE GetAllocatedString(REFGUID guidKey, LPWSTR *ppwszValue, UINT32 *pcchLength); + HRESULT STDMETHODCALLTYPE GetBlobSize(REFGUID guidKey, UINT32 *pcbBlobSize); + HRESULT STDMETHODCALLTYPE GetBlob(REFGUID guidKey, UINT8 *pBuf, UINT32 cbBufSize, UINT32 *pcbBlobSize); + HRESULT STDMETHODCALLTYPE GetAllocatedBlob(REFGUID guidKey, UINT8 **ppBuf, UINT32 *pcbSize); + HRESULT STDMETHODCALLTYPE GetUnknown(REFGUID guidKey, REFIID riid, LPVOID *ppv); + HRESULT STDMETHODCALLTYPE SetItem(REFGUID guidKey, REFPROPVARIANT Value); + HRESULT STDMETHODCALLTYPE DeleteItem(REFGUID guidKey); + HRESULT STDMETHODCALLTYPE DeleteAllItems(); + HRESULT STDMETHODCALLTYPE SetUINT32(REFGUID guidKey, UINT32 unValue); + HRESULT STDMETHODCALLTYPE SetUINT64(REFGUID guidKey, UINT64 unValue); + HRESULT STDMETHODCALLTYPE SetDouble(REFGUID guidKey, double fValue); + HRESULT STDMETHODCALLTYPE SetGUID(REFGUID guidKey, REFGUID guidValue); + HRESULT STDMETHODCALLTYPE SetString(REFGUID guidKey, LPCWSTR wszValue); + HRESULT STDMETHODCALLTYPE SetBlob(REFGUID guidKey, const UINT8 *pBuf, UINT32 cbBufSize); + HRESULT STDMETHODCALLTYPE SetUnknown(REFGUID guidKey, IUnknown *pUnknown); + HRESULT STDMETHODCALLTYPE LockStore(); + HRESULT STDMETHODCALLTYPE UnlockStore(); + HRESULT STDMETHODCALLTYPE GetCount(UINT32 *pcItems); + HRESULT STDMETHODCALLTYPE GetItemByIndex(UINT32 unIndex, GUID *pguidKey, PROPVARIANT *pValue); + HRESULT STDMETHODCALLTYPE CopyAllItems(IMFAttributes *pDest); + +private: + volatile LONG m_ref; + QMutex m_mutex; +}; + + +#endif diff --git a/src/plugins/wmp/qwmpevents.cpp b/src/plugins/wmp/qwmpevents.cpp new file mode 100644 index 000000000..66df07b4a --- /dev/null +++ b/src/plugins/wmp/qwmpevents.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpevents.h" + +#include "qwmpglobal.h" + +QWmpEvents::QWmpEvents(IUnknown *source, QObject *parent) + : QObject(parent) + , m_ref(1) + , m_connectionPoint(0) + , m_adviseCookie(0) +{ + HRESULT hr; + IConnectionPointContainer *container = 0; + + if ((hr = source->QueryInterface( + IID_IConnectionPointContainer, reinterpret_cast<void **>(&container))) != S_OK) { + qWarning("No connection point container, %x: %d", hr, qwmp_error_string(hr)); + } else { + if ((hr = container->FindConnectionPoint( + __uuidof(IWMPEvents), &m_connectionPoint)) != S_OK) { + qWarning("No connection point for IWMPEvents %d", hr); + } else if ((hr = m_connectionPoint->Advise( + static_cast<IWMPEvents3 *>(this), &m_adviseCookie)) != S_OK) { + qWarning("Failed to link to connection point, %x, %s", hr, qwmp_error_string(hr)); + + m_connectionPoint->Release(); + m_connectionPoint = 0; + } + container->Release(); + } +} + +QWmpEvents::~QWmpEvents() +{ + if (m_connectionPoint) { + m_connectionPoint->Unadvise(m_adviseCookie); + m_connectionPoint->Release(); + } + + Q_ASSERT(m_ref == 1); +} + +// IUnknown +HRESULT QWmpEvents::QueryInterface(REFIID riid, void **object) +{ + if (!object) { + return E_POINTER; + } else if (riid == __uuidof(IUnknown) + || riid == __uuidof(IWMPEvents) + || riid == __uuidof(IWMPEvents2) + || riid == __uuidof(IWMPEvents3)) { + *object = static_cast<IWMPEvents3 *>(this); + + AddRef(); + + return S_OK; + } else { + return E_NOINTERFACE; + } +} + +ULONG QWmpEvents::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG QWmpEvents::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + Q_ASSERT(ref != 0); + + return ref; +} diff --git a/src/plugins/wmp/qwmpevents.h b/src/plugins/wmp/qwmpevents.h new file mode 100644 index 000000000..1fb40309d --- /dev/null +++ b/src/plugins/wmp/qwmpevents.h @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPEVENTS_H +#define QWMPEVENTS_H + +#include <QtCore/qobject.h> + +#include <wmp.h> + +class QWmpEvents : public QObject, public IWMPEvents3 +{ + Q_OBJECT +public: + QWmpEvents(IUnknown *source, QObject *parent = 0); + ~QWmpEvents(); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + +Q_SIGNALS: + +#ifndef Q_MOC_RUN + // IWMPEvents + void STDMETHODCALLTYPE OpenStateChange(long NewState); + void STDMETHODCALLTYPE PlayStateChange(long NewState); + void STDMETHODCALLTYPE AudioLanguageChange(long LangID); + void STDMETHODCALLTYPE StatusChange(); + void STDMETHODCALLTYPE ScriptCommand(BSTR scType, BSTR Param); + void STDMETHODCALLTYPE NewStream(); + void STDMETHODCALLTYPE Disconnect(long Result); + void STDMETHODCALLTYPE Buffering(VARIANT_BOOL Start); + void STDMETHODCALLTYPE Error(); + void STDMETHODCALLTYPE Warning(long WarningType, long Param, BSTR Description); + void STDMETHODCALLTYPE EndOfStream(long Result); + void STDMETHODCALLTYPE PositionChange(double oldPosition, double newPosition); + void STDMETHODCALLTYPE MarkerHit(long MarkerNum); + void STDMETHODCALLTYPE DurationUnitChange(long NewDurationUnit); + void STDMETHODCALLTYPE CdromMediaChange(long CdromNum); + void STDMETHODCALLTYPE PlaylistChange(IDispatch *Playlist, WMPPlaylistChangeEventType change); + void STDMETHODCALLTYPE CurrentPlaylistChange(WMPPlaylistChangeEventType change); + void STDMETHODCALLTYPE CurrentPlaylistItemAvailable(BSTR bstrItemName); + void STDMETHODCALLTYPE MediaChange(IDispatch *Item); + void STDMETHODCALLTYPE CurrentMediaItemAvailable(BSTR bstrItemName); + void STDMETHODCALLTYPE CurrentItemChange(IDispatch *pdispMedia); + void STDMETHODCALLTYPE MediaCollectionChange(); + void STDMETHODCALLTYPE MediaCollectionAttributeStringAdded( + BSTR bstrAttribName, BSTR bstrAttribVal); + void STDMETHODCALLTYPE MediaCollectionAttributeStringRemoved( + BSTR bstrAttribName, BSTR bstrAttribVal); + void STDMETHODCALLTYPE MediaCollectionAttributeStringChanged( + BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal); + void STDMETHODCALLTYPE PlaylistCollectionChange(); + void STDMETHODCALLTYPE PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName); + void STDMETHODCALLTYPE PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName); + void STDMETHODCALLTYPE PlaylistCollectionPlaylistSetAsDeleted( + BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted); + void STDMETHODCALLTYPE ModeChange(BSTR ModeName, VARIANT_BOOL NewValue); + void STDMETHODCALLTYPE MediaError(IDispatch *pMediaObject); + void STDMETHODCALLTYPE OpenPlaylistSwitch(IDispatch *pItem); + void STDMETHODCALLTYPE DomainChange(BSTR strDomain); + void STDMETHODCALLTYPE SwitchedToPlayerApplication(); + void STDMETHODCALLTYPE SwitchedToControl(); + void STDMETHODCALLTYPE PlayerDockedStateChange(); + void STDMETHODCALLTYPE PlayerReconnect(); + void STDMETHODCALLTYPE Click(short nButton, short nShiftState, long fX, long fY); + void STDMETHODCALLTYPE DoubleClick(short nButton, short nShiftState, long fX, long fY); + void STDMETHODCALLTYPE KeyDown(short nKeyCode, short nShiftState); + void STDMETHODCALLTYPE KeyPress(short nKeyAscii); + void STDMETHODCALLTYPE KeyUp(short nKeyCode, short nShiftState); + void STDMETHODCALLTYPE MouseDown(short nButton, short nShiftState, long fX, long fY); + void STDMETHODCALLTYPE MouseMove(short nButton, short nShiftState, long fX, long fY); + void STDMETHODCALLTYPE MouseUp(short nButton, short nShiftState, long fX, long fY); + + // IWMPEvents2 + void STDMETHODCALLTYPE DeviceConnect(IWMPSyncDevice *pDevice); + void STDMETHODCALLTYPE DeviceDisconnect(IWMPSyncDevice *pDevice); + void STDMETHODCALLTYPE DeviceStatusChange(IWMPSyncDevice *pDevice, WMPDeviceStatus NewStatus); + void STDMETHODCALLTYPE DeviceSyncStateChange(IWMPSyncDevice *pDevice, WMPSyncState NewState); + void STDMETHODCALLTYPE DeviceSyncError(IWMPSyncDevice *pDevice, IDispatch *pMedia); + void STDMETHODCALLTYPE CreatePartnershipComplete(IWMPSyncDevice *pDevice, HRESULT hrResult); + + // IWMPEvents3 + void STDMETHODCALLTYPE CdromRipStateChange(IWMPCdromRip *pCdromRip, WMPRipState wmprs); + void STDMETHODCALLTYPE CdromRipMediaError(IWMPCdromRip *pCdromRip, IDispatch *pMedia); + void STDMETHODCALLTYPE CdromBurnStateChange(IWMPCdromBurn *pCdromBurn, WMPBurnState wmpbs); + void STDMETHODCALLTYPE CdromBurnMediaError(IWMPCdromBurn *pCdromBurn, IDispatch *pMedia); + void STDMETHODCALLTYPE CdromBurnError(IWMPCdromBurn *pCdromBurn, HRESULT hrError); + void STDMETHODCALLTYPE LibraryConnect(IWMPLibrary *pLibrary); + void STDMETHODCALLTYPE LibraryDisconnect(IWMPLibrary *pLibrary); + void STDMETHODCALLTYPE FolderScanStateChange(WMPFolderScanState wmpfss); + void STDMETHODCALLTYPE StringCollectionChange( + IDispatch *pdispStringCollection, + WMPStringCollectionChangeEventType change, + long lCollectionIndex); + void STDMETHODCALLTYPE MediaCollectionMediaAdded(IDispatch *pdispMedia); + void STDMETHODCALLTYPE MediaCollectionMediaRemoved(IDispatch *pdispMedia); +#else + // Declare again without STDMETHODCALLTYPE for moc's benefit. + + // IWMPEvents + void OpenStateChange(long NewState); + void PlayStateChange(long NewState); + void AudioLanguageChange(long LangID); + void StatusChange(); + void ScriptCommand(BSTR scType, BSTR Param); + void NewStream(); + void Disconnect(long Result); + void Buffering(VARIANT_BOOL Start); + void Error(); + void Warning(long WarningType, long Param, BSTR Description); + void EndOfStream(long Result); + void PositionChange(double oldPosition, double newPosition); + void MarkerHit(long MarkerNum); + void DurationUnitChange(long NewDurationUnit); + void CdromMediaChange(long CdromNum); + void PlaylistChange(IDispatch *Playlist, WMPPlaylistChangeEventType change); + void CurrentPlaylistChange(WMPPlaylistChangeEventType change); + void CurrentPlaylistItemAvailable(BSTR bstrItemName); + void MediaChange(IDispatch *Item); + void CurrentMediaItemAvailable(BSTR bstrItemName); + void CurrentItemChange(IDispatch *pdispMedia); + void MediaCollectionChange(); + void MediaCollectionAttributeStringAdded( + BSTR bstrAttribName, BSTR bstrAttribVal); + void MediaCollectionAttributeStringRemoved( + BSTR bstrAttribName, BSTR bstrAttribVal); + void MediaCollectionAttributeStringChanged( + BSTR bstrAttribName, BSTR bstrOldAttribVal, BSTR bstrNewAttribVal); + void PlaylistCollectionChange(); + void PlaylistCollectionPlaylistAdded(BSTR bstrPlaylistName); + void PlaylistCollectionPlaylistRemoved(BSTR bstrPlaylistName); + void PlaylistCollectionPlaylistSetAsDeleted( + BSTR bstrPlaylistName, VARIANT_BOOL varfIsDeleted); + void ModeChange(BSTR ModeName, VARIANT_BOOL NewValue); + void MediaError(IDispatch *pMediaObject); + void OpenPlaylistSwitch(IDispatch *pItem); + void DomainChange(BSTR strDomain); + void SwitchedToPlayerApplication(); + void SwitchedToControl(); + void PlayerDockedStateChange(); + void PlayerReconnect(); + void Click(short nButton, short nShiftState, long fX, long fY); + void DoubleClick(short nButton, short nShiftState, long fX, long fY); + void KeyDown(short nKeyCode, short nShiftState); + void KeyPress(short nKeyAscii); + void KeyUp(short nKeyCode, short nShiftState); + void MouseDown(short nButton, short nShiftState, long fX, long fY); + void MouseMove(short nButton, short nShiftState, long fX, long fY); + void MouseUp(short nButton, short nShiftState, long fX, long fY); + + // IWMPEvents2 + void DeviceConnect(IWMPSyncDevice *pDevice); + void DeviceDisconnect(IWMPSyncDevice *pDevice); + void DeviceStatusChange(IWMPSyncDevice *pDevice, WMPDeviceStatus NewStatus); + void DeviceSyncStateChange(IWMPSyncDevice *pDevice, WMPSyncState NewState); + void DeviceSyncError(IWMPSyncDevice *pDevice, IDispatch *pMedia); + void CreatePartnershipComplete(IWMPSyncDevice *pDevice, HRESULT hrResult); + + // IWMPEvents3 + void CdromRipStateChange(IWMPCdromRip *pCdromRip, WMPRipState wmprs); + void CdromRipMediaError(IWMPCdromRip *pCdromRip, IDispatch *pMedia); + void CdromBurnStateChange(IWMPCdromBurn *pCdromBurn, WMPBurnState wmpbs); + void CdromBurnMediaError(IWMPCdromBurn *pCdromBurn, IDispatch *pMedia); + void CdromBurnError(IWMPCdromBurn *pCdromBurn, HRESULT hrError); + void LibraryConnect(IWMPLibrary *pLibrary); + void LibraryDisconnect(IWMPLibrary *pLibrary); + void FolderScanStateChange(WMPFolderScanState wmpfss); + void StringCollectionChange( + IDispatch *pdispStringCollection, + WMPStringCollectionChangeEventType change, + long lCollectionIndex); + void MediaCollectionMediaAdded(IDispatch *pdispMedia); + void MediaCollectionMediaRemoved(IDispatch *pdispMedia); +#endif +private: + volatile LONG m_ref; + IConnectionPoint *m_connectionPoint; + DWORD m_adviseCookie; +}; + +#endif diff --git a/src/plugins/wmp/qwmpglobal.cpp b/src/plugins/wmp/qwmpglobal.cpp new file mode 100644 index 000000000..4196bbc4f --- /dev/null +++ b/src/plugins/wmp/qwmpglobal.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpglobal.h" + +#include <QtCore/qdebug.h> + +const char *qwmp_error_string(HRESULT hr) +{ + switch (hr) { + case S_OK: + return "OK"; + case E_NOINTERFACE: + return "No such interface supported"; + case E_POINTER: + return "Invalid pointer"; + case E_FAIL: + return "Unspecified error"; + case E_NOTIMPL: + return "Not implemented"; + case CLASS_E_NOAGGREGATION: + return "Class does not support aggregation (or class object is remote)"; + case CLASS_E_CLASSNOTAVAILABLE: + return "ClassFactory cannot supply requested class"; + case CLASS_E_NOTLICENSED: + return "Class is not licensed for use"; + default: + return "unknown error code"; + } +} diff --git a/src/plugins/wmp/qwmpglobal.h b/src/plugins/wmp/qwmpglobal.h new file mode 100644 index 000000000..f8152903f --- /dev/null +++ b/src/plugins/wmp/qwmpglobal.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPGLOBAL_H +#define QWMPGLOBAL_H + +#include <wmp.h> + +#include <QtCore/qstring.h> +#include <QtCore/qurl.h> + +const char *qwmp_error_string(HRESULT hr); + +class QAutoBStr +{ +public: + inline QAutoBStr(const QString &string) + : m_string(::SysAllocString(static_cast<const wchar_t *>(string.utf16()))) + { + } + + inline QAutoBStr(const QUrl &url) + : m_string(::SysAllocString(static_cast<const wchar_t *>(url.toString().utf16()))) + { + } + + inline QAutoBStr(const wchar_t *string) + : m_string(::SysAllocString(string)) + { + } + + inline ~QAutoBStr() + { + ::SysFreeString(m_string); + } + + inline operator BSTR() const { return m_string; } + +private: + BSTR m_string; +}; + + + +#endif diff --git a/src/plugins/wmp/qwmpmetadata.cpp b/src/plugins/wmp/qwmpmetadata.cpp new file mode 100644 index 000000000..1f7cd0f88 --- /dev/null +++ b/src/plugins/wmp/qwmpmetadata.cpp @@ -0,0 +1,442 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpmetadata.h" + +#include "qwmpevents.h" +#include "qwmpglobal.h" + +#include <qmediacontent.h> + +#include <QtCore/qdatetime.h> +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qsize.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + + +struct QWmpMetaDataKeyLookup +{ + QtMultimediaKit::MetaData key; + const wchar_t *token; +}; + +static const QWmpMetaDataKeyLookup qt_wmpMetaDataKeys[] = +{ + { QtMultimediaKit::Title, L"Title" }, + { QtMultimediaKit::SubTitle, L"WM/SubTitle" }, + { QtMultimediaKit::Author, L"Author" }, + { QtMultimediaKit::Comment, L"Comment" }, + { QtMultimediaKit::Description, L"Description" }, + { QtMultimediaKit::Category, L"WM/Category" }, + { QtMultimediaKit::Genre, L"WM/Genre" }, + //{ QtMultimediaKit::Date, 0 }, + { QtMultimediaKit::Year, L"WM/Year" }, + { QtMultimediaKit::UserRating, L"UserRating" }, + //{ QtMultimediaKit::MetaDatawords, 0 }, + { QtMultimediaKit::Language, L"Language" }, + { QtMultimediaKit::Publisher, L"WM/Publisher" }, + { QtMultimediaKit::Copyright, L"Copyright" }, + { QtMultimediaKit::ParentalRating, L"ParentalRating" }, + { QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" }, + + // Media + { QtMultimediaKit::Size, L"FileSize" }, + { QtMultimediaKit::MediaType, L"MediaType" }, + { QtMultimediaKit::Duration, L"Duration" }, + + // Audio + { QtMultimediaKit::AudioBitRate, L"AudioBitrate" }, + { QtMultimediaKit::AudioCodec, L"AudioCodec" }, + { QtMultimediaKit::ChannelCount, L"Channels" }, + { QtMultimediaKit::SampleRate, L"Frequency" }, + + // Music + { QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" }, + { QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" }, + { QtMultimediaKit::ContributingArtist, L"Author" }, + { QtMultimediaKit::Composer, L"WM/Composer" }, + { QtMultimediaKit::Conductor, L"WM/Conductor" }, + { QtMultimediaKit::Lyrics, L"WM/Lyrics" }, + { QtMultimediaKit::Mood, L"WM/Mood" }, + { QtMultimediaKit::TrackNumber, L"WM/TrackNumber" }, + //{ QtMultimediaKit::TrackCount, 0 }, + //{ QtMultimediaKit::CoverArtUrlSmall, 0 }, + //{ QtMultimediaKit::CoverArtUrlLarge, 0 }, + + // Image/Video + //{ QtMultimediaKit::Resolution, 0 }, + //{ QtMultimediaKit::PixelAspectRatio, 0 }, + + // Video + //{ QtMultimediaKit::FrameRate, 0 }, + { QtMultimediaKit::VideoBitRate, L"VideoBitRate" }, + { QtMultimediaKit::VideoCodec, L"VideoCodec" }, + + //{ QtMultimediaKit::PosterUrl, 0 }, + + // Movie + { QtMultimediaKit::ChapterNumber, L"ChapterNumber" }, + { QtMultimediaKit::Director, L"WM/Director" }, + { QtMultimediaKit::LeadPerformer, L"LeadPerformer" }, + { QtMultimediaKit::Writer, L"WM/Writer" }, + + // Photos + { QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" }, + { QtMultimediaKit::CameraModel, L"CameraModel" }, + { QtMultimediaKit::Event, L"Event" }, + { QtMultimediaKit::Subject, L"Subject" } +}; + +QWmpMetaData::QWmpMetaData(IWMPCore3 *player, QWmpEvents *events, QObject *parent) + : QMetaDataReaderControl(parent) + , m_media(0) +{ + player->get_currentMedia(&m_media); + + connect(events, SIGNAL(CurrentItemChange(IDispatch*)), + this, SLOT(currentItemChangeEvent(IDispatch*))); + connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*))); +} + +QWmpMetaData::~QWmpMetaData() +{ + if (m_media) + m_media->Release(); +} + +bool QWmpMetaData::isMetaDataAvailable() const +{ + return m_media != 0; +} + +bool QWmpMetaData::isWritable() const +{ + return m_media != 0; +} + +QVariant QWmpMetaData::metaData(QtMultimediaKit::MetaData key) const +{ + static const int count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup); + + switch (key) { + case QtMultimediaKit::Date: + { + QVariant day = value(m_media, QAutoBStr(L"ReleaseDateDay")); + QVariant month = value(m_media, QAutoBStr(L"ReleaseDateMonth")); + QVariant year = value(m_media, QAutoBStr(L"ReleaseDateYear")); + + if (!day.isNull() && !month.isNull() && !year.isNull()) + return QDate(year.toInt(), month.toInt(), day.toInt()); + } + break; + case QtMultimediaKit::CoverArtUrlSmall: + return albumArtUrl(m_media, "_Small.jpg"); + case QtMultimediaKit::CoverArtUrlLarge: + return albumArtUrl(m_media, "_Large.jpg"); + case QtMultimediaKit::Resolution: + { + QVariant width = value(m_media, QAutoBStr(L"WM/VideoWidth")); + QVariant height = value(m_media, QAutoBStr(L"WM/VideoHeight")); + + if (!width.isNull() && !height.isNull()) + return QSize(width.toInt(), height.toInt()); + } + break; + case QtMultimediaKit::PixelAspectRatio: + { + QVariant x = value(m_media, QAutoBStr(L"PixelAspectRatioX")); + QVariant y = value(m_media, QAutoBStr(L"PixelAspectRatioY")); + + if (!x.isNull() && !y.isNull()) + return QSize(x.toInt(), y.toInt()); + } + break; + case QtMultimediaKit::VideoFrameRate: + break; + default: + for (int i = 0; i < count; ++i) { + if (qt_wmpMetaDataKeys[i].key == key) + return value(m_media, QAutoBStr(qt_wmpMetaDataKeys[i].token)); + } + break; + } + return QVariant(); +} + +QList<QtMultimediaKit::MetaData> QWmpMetaData::availableMetaData() const +{ + QList<QtMultimediaKit::MetaData> keys; + + if (m_media) { + // WMP will return a list of all possible keys so there's no point in filtering the keys + // in the lookup table. + static const int count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup); + for (int i = 0; i < count; ++i) + keys.append(qt_wmpMetaDataKeys[i].key); + + BSTR string = 0; + if (m_media->get_sourceURL(&string) == S_OK) { + QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string)); + ::SysFreeString(string); + + if (m_media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) { + QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string)); + ::SysFreeString(string); + + QString albumArtLarge = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Large.jpg"); + QString albumArtSmall = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Small.jpg"); + + QDir dir = QFileInfo(url).absoluteDir(); + + if (dir.exists(albumArtLarge)) + keys.append(QtMultimediaKit::CoverArtUrlLarge); + if (dir.exists(albumArtSmall)) + keys.append(QtMultimediaKit::CoverArtUrlSmall); + } + } + } + return keys; +} + +QVariant QWmpMetaData::extendedMetaData(const QString &key) const +{ + return value(m_media, QAutoBStr(key)); +} + +QStringList QWmpMetaData::availableExtendedMetaData() const +{ + return keys(m_media); +} + +void QWmpMetaData::currentItemChangeEvent(IDispatch *dispatch) +{ + IWMPMedia *media = m_media; + + m_media = 0; + if (dispatch) + dispatch->QueryInterface(__uuidof(IWMPMedia), reinterpret_cast<void **>(&m_media)); + + if (media) { + if (m_media) + emit metaDataChanged(); + else + emit metaDataAvailableChanged(false); + + media->Release(); + } else { + if (m_media) + emit metaDataAvailableChanged(false); + } +} + +void QWmpMetaData::mediaChangeEvent(IDispatch *dispatch) +{ + IWMPMedia *media = 0; + if (dispatch && dispatch->QueryInterface( + __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) { + VARIANT_BOOL isEqual = VARIANT_FALSE; + if (media->get_isIdentical(m_media, &isEqual) == S_OK && isEqual) + emit metaDataChanged(); + media->Release(); + } +} + + +QStringList QWmpMetaData::keys(IWMPMedia *media) +{ + QStringList keys; + + long count = 0; + if (media && media->get_attributeCount(&count) == S_OK) { + for (long i = 0; i < count; ++i) { + BSTR string; + if (media->getAttributeName(i, &string) == S_OK) { + keys.append(QString::fromWCharArray(string, ::SysStringLen(string))); + + ::SysFreeString(string); + } + } + } + return keys; +} + +QVariant QWmpMetaData::value(IWMPMedia *media, BSTR key) +{ + QVariantList values; + IWMPMedia3 *media3 = 0; + if (media && media->QueryInterface( + __uuidof(IWMPMedia3), reinterpret_cast<void **>(&media3)) == S_OK) { + long count = 0; + media3->getAttributeCountByType(key, 0, &count); + + // The count appears to only be valid for static properties, dynamic properties like + // PlaylistIndex will have a count of zero but return a value for index 0. + if (count == 0) + count = 1; + + for (long i = 0; i < count; ++i) { + VARIANT var; + VariantInit(&var); + + if (media3->getItemInfoByType(key, 0, i, &var) == S_OK) { + QVariant value = convertVariant(var); + + if (!value.isNull()) + values.append(value); + + VariantClear(&var); + } + } + media3->Release(); + } + + switch (values.count()) { + case 0: + return QVariant(); + case 1: + return values.first(); + default: + return values; + } +} + +QMediaContent QWmpMetaData::resources(IWMPMedia *media) +{ + QMediaContent content; + + BSTR string = 0; + if (media->get_sourceURL(&string) == S_OK) { + QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string)); + ::SysFreeString(string); + + content = QMediaContent(QUrl(url)); + } + + return content; +} + +QVariant QWmpMetaData::convertVariant(const VARIANT &variant) +{ + switch (variant.vt) { + case VT_I2: + return variant.iVal; + case VT_I4: + return variant.lVal; + case VT_I8: + return variant.llVal; + case VT_UI2: + return variant.uiVal; + case VT_UI4: + return quint32(variant.ulVal); + case VT_UI8: + return variant.ullVal; + case VT_INT: + return variant.intVal; + case VT_UINT: + return variant.uintVal; + case VT_BSTR: + return QString::fromWCharArray(variant.bstrVal, ::SysStringLen(variant.bstrVal)); + case VT_DISPATCH: + { + IWMPMetadataPicture *picture = 0; + IWMPMetadataText *text = 0; + + if (variant.pdispVal->QueryInterface( + __uuidof(IWMPMetadataPicture), reinterpret_cast<void **>(&picture)) == S_OK) { + QUrl url; + BSTR string; + if (picture->get_URL(&string) == S_OK) { + url = QUrl(QString::fromWCharArray(string, ::SysStringLen(string))); + + ::SysFreeString(string); + } + picture->Release(); + return qVariantFromValue(url); + } else if (variant.pdispVal->QueryInterface( + __uuidof(IWMPMetadataText), reinterpret_cast<void **>(&text)) == S_OK) { + QString description; + BSTR string; + if (text->get_description(&string) == S_OK) { + description = QString::fromWCharArray(string, SysStringLen(string)); + + ::SysFreeString(string); + } + text->Release(); + return description; + } else { + qWarning("Unknown dispatch type"); + } + } + break; + default: + qWarning("Unsupported Type %d %x", variant.vt, variant.vt); + break; + } + + return QVariant(); +} + +QVariant QWmpMetaData::albumArtUrl(IWMPMedia *media, const char *suffix) +{ + BSTR string = 0; + if (media && media->get_sourceURL(&string) == S_OK) { + QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string)); + ::SysFreeString(string); + + if (media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) { + QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string)); + ::SysFreeString(string); + + QString fileName = QLatin1String("AlbumArt_") + uuid + QLatin1String(suffix); + + QDir dir = QFileInfo(url).absoluteDir(); + + if (dir.exists(fileName)) { + return qVariantFromValue( + QUrl(QLatin1String("file:///") + dir.absoluteFilePath(fileName))); + } + } + } + return QVariant(); +} diff --git a/src/plugins/wmp/qwmpmetadata.h b/src/plugins/wmp/qwmpmetadata.h new file mode 100644 index 000000000..b01a05c4e --- /dev/null +++ b/src/plugins/wmp/qwmpmetadata.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPMETADATA_H +#define QWMPMETADATA_H + +#include <qmetadatareadercontrol.h> +#include <qmediaresource.h> + +#include <wmp.h> + +QT_BEGIN_NAMESPACE +class QMediaContent; +QT_END_NAMESPACE + +class QWmpEvents; + +QT_USE_NAMESPACE + +class QWmpMetaData : public QMetaDataReaderControl +{ + Q_OBJECT +public: + QWmpMetaData(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0); + ~QWmpMetaData(); + + bool isMetaDataAvailable() const; + bool isWritable() const; + + QVariant metaData(QtMultimediaKit::MetaData key) const; + QList<QtMultimediaKit::MetaData> availableMetaData() const; + + QVariant extendedMetaData(const QString &key) const ; + QStringList availableExtendedMetaData() const; + + static QStringList keys(IWMPMedia *media); + static QVariant value(IWMPMedia *media, BSTR key); + static QMediaContent resources(IWMPMedia *media); + static QVariant convertVariant(const VARIANT &variant); + static QVariant albumArtUrl(IWMPMedia *media, const char *suffix); + +private Q_SLOTS: + void currentItemChangeEvent(IDispatch *dispatch); + void mediaChangeEvent(IDispatch *dispatch); + +private: + IWMPMedia *m_media; +}; + +#endif diff --git a/src/plugins/wmp/qwmpplayercontrol.cpp b/src/plugins/wmp/qwmpplayercontrol.cpp new file mode 100644 index 000000000..be8f107b8 --- /dev/null +++ b/src/plugins/wmp/qwmpplayercontrol.cpp @@ -0,0 +1,465 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpplayercontrol.h" + +#include "qwmpevents.h" +#include "qwmpglobal.h" +#include "qwmpmetadata.h" +#include "qwmpplaylist.h" + +#include <qmediaplayer.h> +#include <qmediaplaylist.h> + +#include <QtCore/qcoreapplication.h> +#include <QtCore/qcoreevent.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + +QWmpPlayerControl::QWmpPlayerControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent) + : QMediaPlayerControl(parent) + , m_player(player) + , m_controls(0) + , m_settings(0) + , m_state(QMediaPlayer::StoppedState) + , m_changes(0) + , m_buffering(false) + , m_audioAvailable(false) + , m_videoAvailable(false) +{ + m_player->get_controls(&m_controls); + m_player->get_settings(&m_settings); + m_player->get_network(&m_network); + + if (m_settings) + m_settings->put_autoStart(FALSE); + + WMPPlayState state = wmppsUndefined; + if (m_player->get_playState(&state) == S_OK) + playStateChangeEvent(state); + + connect(events, SIGNAL(Buffering(VARIANT_BOOL)), this, SLOT(bufferingEvent(VARIANT_BOOL))); + connect(events, SIGNAL(PositionChange(double,double)), + this, SLOT(positionChangeEvent(double,double))); + connect(events, SIGNAL(PlayStateChange(long)), this, SLOT(playStateChangeEvent(long))); + connect(events, SIGNAL(CurrentItemChange(IDispatch*)), + this, SLOT(currentItemChangeEvent(IDispatch*))); + connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*))); +} + +QWmpPlayerControl::~QWmpPlayerControl() +{ + if (m_controls) m_controls->Release(); + if (m_settings) m_settings->Release(); + if (m_network) m_network->Release(); +} + +QMediaPlayer::State QWmpPlayerControl::state() const +{ + return m_state; +} + +QMediaPlayer::MediaStatus QWmpPlayerControl::mediaStatus() const +{ + return m_status; +} + +qint64 QWmpPlayerControl::duration() const +{ + double duration = 0.; + + IWMPMedia *media = 0; + if (m_controls && m_controls->get_currentItem(&media) == S_OK) { + media->get_duration(&duration); + media->Release(); + } + + return duration * 1000; +} + +qint64 QWmpPlayerControl::position() const +{ + double position = 0.0; + + if (m_controls) + m_controls->get_currentPosition(&position); + + return position * 1000; +} + +void QWmpPlayerControl::setPosition(qint64 position) +{ + if (m_controls) + m_controls->put_currentPosition(double(position) / 1000.); +} + +int QWmpPlayerControl::volume() const +{ + long volume = 0; + + if (m_settings) + m_settings->get_volume(&volume); + + return volume; +} + +void QWmpPlayerControl::setVolume(int volume) +{ + if (m_settings && m_settings->put_volume(volume) == S_OK) + emit volumeChanged(volume); +} + +bool QWmpPlayerControl::isMuted() const +{ + VARIANT_BOOL mute = FALSE; + + if (m_settings) + m_settings->get_mute(&mute); + + return mute; +} + +void QWmpPlayerControl::setMuted(bool muted) +{ + if (m_settings && m_settings->put_mute(muted ? TRUE : FALSE) == S_OK) + emit mutedChanged(muted); + +} + +int QWmpPlayerControl::bufferStatus() const +{ + long progress = 0; + + if (m_network) + m_network->get_bufferingProgress(&progress); + + return progress; +} + +bool QWmpPlayerControl::isVideoAvailable() const +{ + return m_videoAvailable; +} + +bool QWmpPlayerControl::isAudioAvailable() const +{ + return m_audioAvailable; +} + +void QWmpPlayerControl::setAudioAvailable(bool available) +{ + if (m_audioAvailable != available) + emit audioAvailableChanged(m_audioAvailable = available); +} + +void QWmpPlayerControl::setVideoAvailable(bool available) +{ + if (m_videoAvailable != available) + emit videoAvailableChanged(m_videoAvailable = available); +} + +bool QWmpPlayerControl::isSeekable() const +{ + return true; +} + +QMediaTimeRange QWmpPlayerControl::availablePlaybackRanges() const +{ + QMediaTimeRange ranges; + + IWMPMedia *media = 0; + if (m_controls && m_controls->get_currentItem(&media) == S_OK) { + double duration = 0; + media->get_duration(&duration); + media->Release(); + + if(duration > 0) + ranges.addInterval(0, duration * 1000); + } + + return ranges; +} + +qreal QWmpPlayerControl::playbackRate() const +{ + double rate = 0.; + + if (m_settings) + m_settings->get_rate(&rate); + + return rate; +} + +void QWmpPlayerControl::setPlaybackRate(qreal rate) +{ + if (m_settings) + m_settings->put_rate(rate); +} + +void QWmpPlayerControl::play() +{ + if (m_controls) + m_controls->play(); +} + +void QWmpPlayerControl::pause() +{ + if (m_controls) + m_controls->pause(); +} + +void QWmpPlayerControl::stop() +{ + if (m_controls) + m_controls->stop(); +} + +QMediaContent QWmpPlayerControl::media() const +{ + QMediaResourceList resources; + + QUrl tmpUrl = url(); + + if (!tmpUrl.isEmpty()) + resources << QMediaResource(tmpUrl); + + return resources; +} + +const QIODevice *QWmpPlayerControl::mediaStream() const +{ + return 0; +} + +void QWmpPlayerControl::setMedia(const QMediaContent &content, QIODevice *stream) +{ + if (!content.isNull() && !stream) + setUrl(content.canonicalUrl()); + else + setUrl(QUrl()); +} + +bool QWmpPlayerControl::event(QEvent *event) +{ + if (event->type() == QEvent::UpdateRequest) { + const int changes = m_changes; + m_changes = 0; + + if (changes & DurationChanged) + emit durationChanged(duration()); + if (changes & PositionChanged) + emit positionChanged(position()); + if (changes & StatusChanged) + emit mediaStatusChanged(m_status); + if (changes & StateChanged) + emit stateChanged(m_state); + + return true; + } else { + return QMediaPlayerControl::event(event); + } +} + +void QWmpPlayerControl::scheduleUpdate(int change) +{ + if (m_changes == 0) + QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest)); + + m_changes |= change; +} + +void QWmpPlayerControl::bufferingEvent(VARIANT_BOOL buffering) +{ + if (m_state != QMediaPlayer::StoppedState) { + m_status = buffering + ? QMediaPlayer::BufferingMedia + : QMediaPlayer::BufferedMedia; + + scheduleUpdate(StatusChanged); + } +} + +void QWmpPlayerControl::currentItemChangeEvent(IDispatch *) +{ + scheduleUpdate(DurationChanged); +} + +void QWmpPlayerControl::mediaChangeEvent(IDispatch *dispatch) +{ + IWMPMedia *media = 0; + if (dispatch && dispatch->QueryInterface( + __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) { + IWMPMedia *currentMedia = 0; + if (m_controls && m_controls->get_currentItem(¤tMedia) == S_OK) { + VARIANT_BOOL isEqual = VARIANT_FALSE; + if (media->get_isIdentical(currentMedia, &isEqual) == S_OK && isEqual) + scheduleUpdate(DurationChanged); + + currentMedia->Release(); + } + media->Release(); + } +} + +void QWmpPlayerControl::positionChangeEvent(double , double) +{ + scheduleUpdate(PositionChanged); +} + +void QWmpPlayerControl::playStateChangeEvent(long state) +{ + switch (state) { + case wmppsUndefined: + m_state = QMediaPlayer::StoppedState; + m_status = QMediaPlayer::UnknownMediaStatus; + scheduleUpdate(StatusChanged | StateChanged); + break; + case wmppsStopped: + if (m_state != QMediaPlayer::StoppedState) { + m_state = QMediaPlayer::StoppedState; + scheduleUpdate(StateChanged); + + if (m_status != QMediaPlayer::EndOfMedia) { + m_status = QMediaPlayer::LoadedMedia; + scheduleUpdate(StatusChanged); + } + } + break; + case wmppsPaused: + if (m_state != QMediaPlayer::PausedState && m_status != QMediaPlayer::BufferedMedia) { + m_state = QMediaPlayer::PausedState; + m_status = QMediaPlayer::BufferedMedia; + scheduleUpdate(StatusChanged | StateChanged); + } else if (m_state != QMediaPlayer::PausedState) { + m_state = QMediaPlayer::PausedState; + scheduleUpdate(StateChanged); + } else if (m_status != QMediaPlayer::BufferedMedia) { + m_status = QMediaPlayer::BufferedMedia; + + scheduleUpdate(StatusChanged); + } + break; + case wmppsPlaying: + case wmppsScanForward: + case wmppsScanReverse: + if (m_state != QMediaPlayer::PlayingState && m_status != QMediaPlayer::BufferedMedia) { + m_state = QMediaPlayer::PlayingState; + m_status = QMediaPlayer::BufferedMedia; + scheduleUpdate(StatusChanged | StateChanged); + } else if (m_state != QMediaPlayer::PlayingState) { + m_state = QMediaPlayer::PlayingState; + scheduleUpdate(StateChanged); + } else if (m_status != QMediaPlayer::BufferedMedia) { + m_status = QMediaPlayer::BufferedMedia; + scheduleUpdate(StatusChanged); + } + + if (m_state != QMediaPlayer::PlayingState) { + m_state = QMediaPlayer::PlayingState; + scheduleUpdate(StateChanged); + } + if (m_status != QMediaPlayer::BufferedMedia) { + m_status = QMediaPlayer::BufferedMedia; + scheduleUpdate(StatusChanged); + } + break; + case wmppsBuffering: + case wmppsWaiting: + if (m_status != QMediaPlayer::StalledMedia && m_state != QMediaPlayer::StoppedState) { + m_status = QMediaPlayer::StalledMedia; + scheduleUpdate(StatusChanged); + } + break; + case wmppsMediaEnded: + if (m_status != QMediaPlayer::EndOfMedia && m_state != QMediaPlayer::StoppedState) { + m_state = QMediaPlayer::StoppedState; + m_status = QMediaPlayer::EndOfMedia; + scheduleUpdate(StatusChanged | StateChanged); + } + break; + case wmppsTransitioning: + break; + case wmppsReady: + if (m_status != QMediaPlayer::LoadedMedia) { + m_status = QMediaPlayer::LoadedMedia; + scheduleUpdate(StatusChanged); + } + + if (m_state != QMediaPlayer::StoppedState) { + m_state = QMediaPlayer::StoppedState; + scheduleUpdate(StateChanged); + } + break; + case wmppsReconnecting: + if (m_status != QMediaPlayer::StalledMedia && m_state != QMediaPlayer::StoppedState) { + m_status = QMediaPlayer::StalledMedia; + scheduleUpdate(StatusChanged); + } + break; + default: + break; + } +} + +QUrl QWmpPlayerControl::url() const +{ + BSTR string; + if (m_player && m_player->get_URL(&string) == S_OK) { + QUrl url(QString::fromWCharArray(string, SysStringLen(string)), QUrl::StrictMode); + + SysFreeString(string); + + return url; + } else { + return QUrl(); + } +} + +void QWmpPlayerControl::setUrl(const QUrl &url) +{ + if (url != QWmpPlayerControl::url() && m_player) { + BSTR string = SysAllocString(reinterpret_cast<const wchar_t *>(url.toString().unicode())); + + m_player->put_URL(string); + + SysFreeString(string); + } +} diff --git a/src/plugins/wmp/qwmpplayercontrol.h b/src/plugins/wmp/qwmpplayercontrol.h new file mode 100644 index 000000000..d966b38b2 --- /dev/null +++ b/src/plugins/wmp/qwmpplayercontrol.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPPLAYERCONTROL_H +#define QWMPPLAYERCONTROL_H + +#include <qmediaplayercontrol.h> + +#include <wmp.h> + +class QWmpEvents; +class QWmpPlaylist; + +QT_USE_NAMESPACE +class QWmpPlayerControl : public QMediaPlayerControl +{ + Q_OBJECT +public: + QWmpPlayerControl( + IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0); + ~QWmpPlayerControl(); + + QMediaPlayer::State state() const; + QMediaPlayer::MediaStatus mediaStatus() const; + + QMediaPlaylist* mediaPlaylist() const; + bool setMediaPlaylist(QMediaPlaylist *playlist); + + qint64 duration() const; + + qint64 position() const; + void setPosition(qint64 position); + + int playlistPosition() const; + void setPlaylistPosition(int position); + + int volume() const; + void setVolume(int volume); + + bool isMuted() const; + void setMuted(bool muted); + + int bufferStatus() const; + + bool isAudioAvailable() const; + void setAudioAvailable(bool available); + + bool isVideoAvailable() const; + void setVideoAvailable(bool available); + + qreal playbackRate() const; + void setPlaybackRate(qreal rate); + + bool isSeekable() const; + QMediaTimeRange availablePlaybackRanges() const; + + void play(); + void pause(); + void stop(); + + QMediaContent media() const; + const QIODevice *mediaStream() const; + void setMedia(const QMediaContent &content, QIODevice *stream); + + QUrl url() const; + void setUrl(const QUrl &url); + + bool event(QEvent *event); + + using QMediaPlayerControl::positionChanged; + +private Q_SLOTS: + + void bufferingEvent(VARIANT_BOOL buffering); + void currentItemChangeEvent(IDispatch *dispatch); + void mediaChangeEvent(IDispatch *dispatch); + void positionChangeEvent(double from, double to); + void playStateChangeEvent(long state); + +private: + enum Change + { + StateChanged = 0x01, + StatusChanged = 0x02, + PositionChanged = 0x04, + DurationChanged = 0x08 + }; + + void scheduleUpdate(int change); + + IWMPCore3 *m_player; + IWMPControls *m_controls; + IWMPSettings *m_settings; + IWMPNetwork *m_network; + QMediaPlayer::State m_state; + QMediaPlayer::MediaStatus m_status; + int m_changes; + bool m_buffering; + bool m_audioAvailable; + bool m_videoAvailable; +}; + +#endif diff --git a/src/plugins/wmp/qwmpplayerservice.cpp b/src/plugins/wmp/qwmpplayerservice.cpp new file mode 100644 index 000000000..e185aaf46 --- /dev/null +++ b/src/plugins/wmp/qwmpplayerservice.cpp @@ -0,0 +1,355 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpplayerservice.h" + +#ifdef QWMP_EVR +#include "qevrvideooverlay.h" +#endif + +#include "qwmpglobal.h" +#include "qwmpmetadata.h" +#include "qwmpplayercontrol.h" +#include "qwmpplaylist.h" +#include "qwmpplaylistcontrol.h" +#include "qwmpvideooverlay.h" + +#include <qmediaplayer.h> + +#include <QtCore/qcoreapplication.h> +#include <QtCore/quuid.h> +#include <QtCore/qvariant.h> +#include <QtGui/qevent.h> + +#include <d3d9.h> +#include <wmprealestate.h> + +QWmpPlayerService::QWmpPlayerService(EmbedMode mode, QObject *parent) + : QMediaService(parent) + , m_ref(1) + , m_embedMode(mode) + , m_player(0) + , m_oleObject(0) + , m_events(0) + , m_control(0) + , m_metaData(0) + , m_playlist(0) + , m_activeVideoOverlay(0) + , m_oleVideoOverlay(0) +#ifdef QWMP_EVR + , m_evrVideoOverlay(0) +#endif +{ + HRESULT hr; + + if ((hr = CoCreateInstance( + __uuidof(WindowsMediaPlayer), + 0, + CLSCTX_INPROC_SERVER, + __uuidof(IWMPPlayer4), + reinterpret_cast<void **>(&m_player))) != S_OK) { + qWarning("failed to create media player control, %x: %s", hr, qwmp_error_string(hr)); + } else { + m_events = new QWmpEvents(m_player); + + if ((hr = m_player->QueryInterface( + __uuidof(IOleObject), reinterpret_cast<void **>(&m_oleObject))) != S_OK) { + qWarning("No IOleObject interface, %x: %s", hr, qwmp_error_string(hr)); + } else if ((hr = m_oleObject->SetClientSite(this)) != S_OK) { + qWarning("Failed to set site, %x: %s", hr, qwmp_error_string(hr)); + } + + if (m_embedMode == LocalEmbed) + m_oleVideoOverlay = new QWmpVideoOverlay(m_player, m_oleObject, this); + + m_metaData = new QWmpMetaData(m_player, m_events); + m_playlist = new QWmpPlaylistControl(m_player, m_events); + m_control = new QWmpPlayerControl(m_player, m_events); + } +} + +QWmpPlayerService::~QWmpPlayerService() +{ + delete m_control; + delete m_metaData; + delete m_playlist; + delete m_events; + + if (m_oleObject) { + m_oleObject->SetClientSite(0); + m_oleObject->Release(); + delete m_oleVideoOverlay; + } + +#ifdef QWMP_EVR + delete m_evrVideoOverlay; +#endif + + + if (m_player) + m_player->Release(); + + Q_ASSERT(m_ref == 1); +} + +QMediaControl *QWmpPlayerService::requestControl(const char *name) +{ + if (qstrcmp(name, QMediaPlayerControl_iid) == 0) { + return m_control; + } else if (qstrcmp(name, QMetaDataReaderControl_iid) == 0) { + return m_metaData; + } else if (qstrcmp(name, QMediaPlaylistControl_iid) == 0) { + return m_playlist; + } else if (qstrcmp(name, QVideoWindowControl_iid) == 0 + && m_embedMode == LocalEmbed + && m_player + && !m_activeVideoOverlay) { +#ifdef QWMP_EVR + IWMPVideoRenderConfig *config = 0; + if (m_player->QueryInterface( + __uuidof(IWMPVideoRenderConfig), reinterpret_cast<void **>(&config)) == S_OK) { + if (HINSTANCE evrHwnd = LoadLibrary(L"evr")) { + m_evrVideoOverlay = new QEvrVideoOverlay(evrHwnd); + + if (SUCCEEDED(config->put_presenterActivate( + static_cast<IMFActivate *>(m_evrVideoOverlay)))) { + connect(m_events, SIGNAL(OpenStateChange(long)), + m_evrVideoOverlay, SLOT(openStateChanged(long))); + } else { + delete m_evrVideoOverlay; + + m_evrVideoOverlay = 0; + } + } + config->Release(); + } + + if (m_evrVideoOverlay) { + m_activeVideoOverlay = m_evrVideoOverlay; + + return m_evrVideoOverlay; + } else +#endif + if (SUCCEEDED(m_player->put_uiMode(QAutoBStr(L"none")))) { + m_activeVideoOverlay = m_oleVideoOverlay; + + return m_oleVideoOverlay; + } + } + return 0; +} + +void QWmpPlayerService::releaseControl(QMediaControl *control) +{ + if (!control) { + qWarning("QMediaService::releaseControl():" + " Attempted release of null control"); +#ifdef QWMP_EVR + } else if (control == m_evrVideoOverlay) { + + IWMPVideoRenderConfig *config = 0; + if (m_player->QueryInterface( + __uuidof(IWMPVideoRenderConfig), reinterpret_cast<void **>(&config)) == S_OK) { + config->put_presenterActivate(0); + config->Release(); + } + + delete m_evrVideoOverlay; + + m_evrVideoOverlay = 0; + m_activeVideoOverlay = 0; +#endif + } else if (control == m_oleVideoOverlay) { + m_player->put_uiMode(QAutoBStr(L"invisible")); + m_oleVideoOverlay->setWinId(0); + + m_activeVideoOverlay = 0; + } +} + +// IUnknown +HRESULT QWmpPlayerService::QueryInterface(REFIID riid, void **object) +{ + if (!object) { + return E_POINTER; + } else if (riid == __uuidof(IUnknown) + || riid == __uuidof(IOleClientSite)) { + *object = static_cast<IOleClientSite *>(this); + } else if (riid == __uuidof(IServiceProvider)) { + *object = static_cast<IServiceProvider *>(this); + } else if (riid == __uuidof(IWMPRemoteMediaServices)) { + *object = static_cast<IWMPRemoteMediaServices *>(this); + } else if (riid == __uuidof(IOleWindow) + || riid == __uuidof(IOleInPlaceSite)) { + *object = static_cast<IOleInPlaceSite *>(m_oleVideoOverlay); + } else if (riid == __uuidof(IOleInPlaceUIWindow) + || riid == __uuidof(IOleInPlaceFrame)) { + *object = static_cast<IOleInPlaceFrame *>(m_oleVideoOverlay); + } else { + *object = 0; + } + + if (*object) { + AddRef(); + + return S_OK; + } else { + return E_NOINTERFACE; + } +} + +ULONG QWmpPlayerService::AddRef() +{ + return InterlockedIncrement(&m_ref); +} + +ULONG QWmpPlayerService::Release() +{ + ULONG ref = InterlockedDecrement(&m_ref); + + Q_ASSERT(ref != 0); + + return ref; +} + +// IOleClientSite +HRESULT QWmpPlayerService::SaveObject() +{ + return E_NOTIMPL; +} + +HRESULT QWmpPlayerService::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk) +{ + Q_UNUSED(dwAssign); + Q_UNUSED(dwWhichMoniker); + Q_UNUSED(ppmk); + + return E_NOTIMPL; +} + +HRESULT QWmpPlayerService::GetContainer(IOleContainer **ppContainer) +{ + if (!ppContainer) { + return E_POINTER; + } else { + *ppContainer = 0; + + return E_NOINTERFACE; + } +} + +HRESULT QWmpPlayerService::ShowObject() +{ + return S_OK; +} + +HRESULT QWmpPlayerService::OnShowWindow(BOOL fShow) +{ + Q_UNUSED(fShow); + + return S_OK; +} + +HRESULT QWmpPlayerService::RequestNewObjectLayout() +{ + return E_NOTIMPL; +} + +// IServiceProvider +HRESULT QWmpPlayerService::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) +{ + Q_UNUSED(guidService); + + if (!ppvObject) { + return E_POINTER; + } else if (riid == __uuidof(IWMPRemoteMediaServices)) { + *ppvObject = static_cast<IWMPRemoteMediaServices *>(this); + + AddRef(); + + return S_OK; + } else { + return E_NOINTERFACE; + } +} + +// IWMPRemoteMediaServices +HRESULT QWmpPlayerService::GetServiceType(BSTR *pbstrType) +{ + if (!pbstrType) { + return E_POINTER; + } else if (m_embedMode == RemoteEmbed) { + *pbstrType = ::SysAllocString(L"Remote"); + + return S_OK; + } else { + *pbstrType = ::SysAllocString(L"Local"); + + return S_OK; + } +} + +HRESULT QWmpPlayerService::GetApplicationName(BSTR *pbstrName) +{ + if (!pbstrName) { + return E_POINTER; + } else { + *pbstrName = ::SysAllocString(static_cast<const wchar_t *>( + QCoreApplication::applicationName().utf16())); + + return S_OK; + } +} + +HRESULT QWmpPlayerService::GetScriptableObject(BSTR *pbstrName, IDispatch **ppDispatch) +{ + Q_UNUSED(pbstrName); + Q_UNUSED(ppDispatch); + + return E_NOTIMPL; +} + +HRESULT QWmpPlayerService::GetCustomUIMode(BSTR *pbstrFile) +{ + Q_UNUSED(pbstrFile); + + return E_NOTIMPL; +} diff --git a/src/plugins/wmp/qwmpplayerservice.h b/src/plugins/wmp/qwmpplayerservice.h new file mode 100644 index 000000000..ba79a9a68 --- /dev/null +++ b/src/plugins/wmp/qwmpplayerservice.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPPLAYERSERVICE_H +#define QWMPPLAYERSERVICE_H + +#include "qwmpevents.h" + +#include <qmediaservice.h> + +QT_BEGIN_NAMESPACE +class QMediaMetaData; +class QMediaPlayerControl; +class QMediaPlaylist; +class QVideoWindowControl; +QT_END_NAMESPACE + +#ifdef QWMP_EVR +class QEvrVideoOverlay; +#endif + +class QWmpMetaData; +class QWmpPlayerControl; +class QWmpPlaylist; +class QWmpPlaylistControl; +class QWmpVideoOverlay; + +QT_USE_NAMESPACE +class QWmpPlayerService + : public QMediaService + , public IOleClientSite + , public IServiceProvider + , public IWMPRemoteMediaServices +{ + Q_OBJECT +public: + enum EmbedMode + { + LocalEmbed, + RemoteEmbed + }; + + QWmpPlayerService(EmbedMode mode, QObject *parent = 0); + ~QWmpPlayerService(); + + QMediaControl *requestControl(const char *name); + void releaseControl(QMediaControl *control); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IOleClientSite + HRESULT STDMETHODCALLTYPE SaveObject(); + HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker **ppmk); + HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer **ppContainer); + HRESULT STDMETHODCALLTYPE ShowObject(); + HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow); + HRESULT STDMETHODCALLTYPE RequestNewObjectLayout(); + + // IServiceProvider + HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); + + // IWMPRemoteMediaServices + HRESULT STDMETHODCALLTYPE GetServiceType(BSTR *pbstrType); + HRESULT STDMETHODCALLTYPE GetApplicationName(BSTR *pbstrName); + HRESULT STDMETHODCALLTYPE GetScriptableObject(BSTR *pbstrName, IDispatch **ppDispatch); + HRESULT STDMETHODCALLTYPE GetCustomUIMode(BSTR *pbstrFile); + +private: + volatile LONG m_ref; + const EmbedMode m_embedMode; + IWMPPlayer4 *m_player; + IOleObject *m_oleObject; + QWmpEvents *m_events; + QWmpPlayerControl *m_control; + QWmpMetaData *m_metaData; + QWmpPlaylistControl *m_playlist; + QVideoWindowControl *m_activeVideoOverlay; + QWmpVideoOverlay *m_oleVideoOverlay; +#ifdef QWMP_EVR + QEvrVideoOverlay *m_evrVideoOverlay; +#endif +}; + +#endif diff --git a/src/plugins/wmp/qwmpplaylist.cpp b/src/plugins/wmp/qwmpplaylist.cpp new file mode 100644 index 000000000..10ce753b1 --- /dev/null +++ b/src/plugins/wmp/qwmpplaylist.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpplaylist.h" + +#include "qwmpevents.h" +#include "qwmpmetadata.h" +#include "qwmpglobal.h" + +#include <QtCore/qstringlist.h> +#include <QtCore/qurl.h> +#include <QtCore/qvariant.h> + +QWmpPlaylist::QWmpPlaylist(IWMPCore3 *player, QWmpEvents *events, QObject *parent) + : QMediaPlaylistProvider(parent) + , m_player(player) + , m_playlist(0) + , m_count(0) +{ + if (m_player && m_player->get_currentPlaylist(&m_playlist) == S_OK) + m_playlist->get_count(&m_count); + + connect(events, SIGNAL(CurrentPlaylistChange(WMPPlaylistChangeEventType)), + this, SLOT(currentPlaylistChangeEvent(WMPPlaylistChangeEventType))); + connect(events, SIGNAL(OpenPlaylistSwitch(IDispatch*)), + this, SLOT(openPlaylistChangeEvent(IDispatch*))); + connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*))); +} + +QWmpPlaylist::~QWmpPlaylist() +{ + if (m_playlist) + m_playlist->Release(); +} + +bool QWmpPlaylist::load(const QString &location, const char *format) +{ + Q_UNUSED(location); + Q_UNUSED(format); + + return false; +} + +bool QWmpPlaylist::load(QIODevice * device, const char *format) +{ + Q_UNUSED(device); + Q_UNUSED(format); + + return false; +} + +bool QWmpPlaylist::save(const QString &location, const char *format) +{ + Q_UNUSED(location); + Q_UNUSED(format); + + return false; +} + +bool QWmpPlaylist::save(QIODevice * device, const char *format) +{ + Q_UNUSED(device); + Q_UNUSED(format); + + return false; +} + +int QWmpPlaylist::mediaCount() const +{ + return m_count; +} + +QMediaContent QWmpPlaylist::media(int pos) const +{ + QMediaContent content; + + IWMPMedia *media = 0; + if (m_playlist && m_playlist->get_item(pos, &media) == S_OK) { + content = QWmpMetaData::resources(media); + + media->Release(); + } + + return content; +} + +bool QWmpPlaylist::isReadOnly() const +{ + return false; +} + +bool QWmpPlaylist::addMedia(const QMediaContent &content) +{ + bool appended = false; + + IWMPMedia *media = 0; + if (!content.isNull() && m_playlist && m_player && m_player->newMedia( + QAutoBStr(content.canonicalUrl()), &media) == S_OK) { + appended = m_playlist->appendItem(media) == S_OK; + + media->Release(); + } + + return appended; +} + +bool QWmpPlaylist::insertMedia(int pos, const QMediaContent &content) +{ + bool inserted = false; + + IWMPMedia *media = 0; + if (m_playlist && m_player && m_player->newMedia( + QAutoBStr(content.canonicalUrl()), &media) == S_OK) { + inserted = m_playlist->insertItem(pos, media) == S_OK; + + media->Release(); + } + + return inserted; +} + +bool QWmpPlaylist::removeMedia(int pos) +{ + IWMPMedia *media = 0; + if (m_playlist->get_item(pos, &media) == S_OK) { + bool removed = m_playlist->removeItem(media) == S_OK; + + media->Release(); + + return removed; + } else { + return false; + } +} + +bool QWmpPlaylist::removeMedia(int start, int end) +{ + if (!m_playlist) + return false; + + for (int i = start; i <= end; ++i) { + IWMPMedia *media = 0; + if (m_playlist->get_item(start, &media) == S_OK) { + bool removed = m_playlist->removeItem(media) == S_OK; + + media->Release(); + + if (!removed) + return false; + } + } + return true; +} + +bool QWmpPlaylist::clear() +{ + return m_playlist && m_playlist->clear() == S_OK; +} + +QStringList QWmpPlaylist::keys(int index) const +{ + QStringList keys; + + IWMPMedia *media = 0; + if (m_playlist && m_playlist->get_item(index, &media) == S_OK) { + keys = QWmpMetaData::keys(media); + + media->Release(); + } + + return keys; +} + +QVariant QWmpPlaylist::value(int index, const QString &key) const +{ + QVariant v; + + IWMPMedia *media = 0; + if (m_playlist && m_playlist->get_item(index, &media) == S_OK) { + v = QWmpMetaData::value(media, QAutoBStr(key)); + + media->Release(); + } + + return v; +} + +void QWmpPlaylist::shuffle() +{ +} + + +void QWmpPlaylist::currentPlaylistChangeEvent(WMPPlaylistChangeEventType change) +{ + Q_UNUSED(change); + + long count = 0; + if (m_playlist && m_playlist->get_count(&count) == S_OK && count > 0) { + if (count > m_count) { + emit mediaAboutToBeInserted(m_count, count - 1); + m_count = count; + emit mediaInserted(count, m_count - 1); + } else if (count < m_count) { + emit mediaAboutToBeRemoved(count, m_count - 1); + m_count = count; + emit mediaRemoved(count, m_count - 1); + } + } + if (m_count > 0) + emit mediaChanged(0, m_count - 1); +} + +void QWmpPlaylist::openPlaylistChangeEvent(IDispatch *dispatch) +{ + if (m_playlist && m_count > 0) { + emit mediaAboutToBeRemoved(0, m_count - 1); + m_playlist->Release(); + m_playlist = 0; + m_count = 0; + emit mediaRemoved(0, m_count - 1); + } else if (m_playlist) { + m_playlist->Release(); + m_playlist = 0; + } + + IWMPPlaylist *playlist = 0; + if (dispatch && dispatch->QueryInterface( + __uuidof(IWMPPlaylist), reinterpret_cast<void **>(&playlist))) { + + long count = 0; + if (playlist->get_count(&count) == S_OK && count > 0) { + emit mediaAboutToBeInserted(0, count - 1); + m_playlist = playlist; + m_count = count; + emit mediaInserted(0, count - 1); + } else { + m_playlist = playlist; + } + } +} + +void QWmpPlaylist::mediaChangeEvent(IDispatch *dispatch) +{ + + IWMPMedia *media = 0; + if (dispatch && dispatch->QueryInterface( + __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) { + VARIANT_BOOL isMember = VARIANT_FALSE; + + if (media->isMemberOf(m_playlist, &isMember) == S_OK && isMember) { + int index = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt(); + + if (index >= 0) + emit mediaChanged(index, index); + } + media->Release(); + } +} diff --git a/src/plugins/wmp/qwmpplaylist.h b/src/plugins/wmp/qwmpplaylist.h new file mode 100644 index 000000000..be168a7b5 --- /dev/null +++ b/src/plugins/wmp/qwmpplaylist.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPPLAYLIST_H +#define QWMPPLAYLIST_H + +#include <qmediaplaylistprovider.h> + +#include <QtCore/qvariant.h> + +#include <wmp.h> + +class QWmpEvents; + +QT_USE_NAMESPACE +class QWmpPlaylist : public QMediaPlaylistProvider +{ + Q_OBJECT +public: + QWmpPlaylist(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0); + ~QWmpPlaylist(); + + bool load(const QString &location, const char *format = 0); + bool load(QIODevice * device, const char *format = 0); + bool save(const QString &location, const char *format = 0); + bool save(QIODevice * device, const char *format); + + int mediaCount() const; + QMediaContent media(int pos) const; + + bool isReadOnly() const; + + bool addMedia(const QMediaContent &content); + bool insertMedia(int pos, const QMediaContent &content); + bool removeMedia(int pos); + bool removeMedia(int start, int end); + bool clear(); + + QStringList keys(int index) const; + QVariant value(int index, const QString &key) const; + +public Q_SLOTS: + virtual void shuffle(); + +private Q_SLOTS: + void currentPlaylistChangeEvent(WMPPlaylistChangeEventType change); + void openPlaylistChangeEvent(IDispatch *dispatch); + void mediaChangeEvent(IDispatch *dispatch); + +private: + IWMPCore3 *m_player; + IWMPPlaylist *m_playlist; + long m_count; +}; + +#endif diff --git a/src/plugins/wmp/qwmpplaylistcontrol.cpp b/src/plugins/wmp/qwmpplaylistcontrol.cpp new file mode 100644 index 000000000..f4cc12f7f --- /dev/null +++ b/src/plugins/wmp/qwmpplaylistcontrol.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpplaylistcontrol.h" + +#include "qwmpevents.h" +#include "qwmpglobal.h" +#include "qwmpmetadata.h" +#include "qwmpplaylist.h" + +QWmpPlaylistControl::QWmpPlaylistControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent) + : QMediaPlaylistControl(parent) + , m_player(player) + , m_controls(0) + , m_playlist(new QWmpPlaylist(player, events)) + , m_playbackMode(QMediaPlaylist::Sequential) +{ + m_player->get_controls(&m_controls); + + connect(events, SIGNAL(CurrentItemChange(IDispatch*)), + this, SLOT(currentItemChangeEvent(IDispatch*))); +} + +QWmpPlaylistControl::~QWmpPlaylistControl() +{ + if (m_controls) + m_controls->Release(); + + delete m_playlist; +} + +QMediaPlaylistProvider *QWmpPlaylistControl::playlistProvider() const +{ + return m_playlist; +} + +bool QWmpPlaylistControl::setPlaylistProvider(QMediaPlaylistProvider *playlist) +{ + Q_UNUSED(playlist); + + return false; +} + +int QWmpPlaylistControl::currentIndex() const +{ + int position = 0; + + IWMPMedia *media = 0; + if (m_controls && m_player->get_currentMedia(&media) == S_OK) { + position = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt(); + + media->Release(); + } + + return position; +} + +void QWmpPlaylistControl::setCurrentIndex(int position) +{ + + IWMPPlaylist *playlist = 0; + if (m_player->get_currentPlaylist(&playlist) == S_OK) { + IWMPMedia *media = 0; + if (playlist->get_item(position, &media) == S_OK) { + m_player->put_currentMedia(media); + + media->Release(); + } + playlist->Release(); + } +} + +int QWmpPlaylistControl::nextIndex(int steps) const +{ + return currentIndex() + steps; +} + +int QWmpPlaylistControl::previousIndex(int steps) const +{ + return currentIndex() - steps; +} + +void QWmpPlaylistControl::next() +{ + if (m_controls) + m_controls->next(); +} + +void QWmpPlaylistControl::previous() +{ + if (m_controls) + m_controls->previous(); +} + +QMediaPlaylist::PlaybackMode QWmpPlaylistControl::playbackMode() const +{ + return m_playbackMode; +} + +void QWmpPlaylistControl::setPlaybackMode(QMediaPlaylist::PlaybackMode mode) +{ + m_playbackMode = mode; +} + +void QWmpPlaylistControl::currentItemChangeEvent(IDispatch *dispatch) +{ + IWMPMedia *media = 0; + if (dispatch && dispatch->QueryInterface( + __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) { + int index = QWmpMetaData::value(media, QAutoBStr(L"PlaylistIndex")).toInt(); + + emit currentIndexChanged(index); + emit currentMediaChanged(m_playlist->media(index)); + } +} diff --git a/src/plugins/wmp/qwmpplaylistcontrol.h b/src/plugins/wmp/qwmpplaylistcontrol.h new file mode 100644 index 000000000..cf519aebb --- /dev/null +++ b/src/plugins/wmp/qwmpplaylistcontrol.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPPLAYLISTCONTROL_H +#define QWMPPLAYLISTCONTROL_H + +#include <qmediaplaylistcontrol.h> + +#include <wmp.h> + +class QWmpEvents; +class QWmpPlaylist; + +QT_USE_NAMESPACE +class QWmpPlaylistControl : public QMediaPlaylistControl +{ + Q_OBJECT +public: + QWmpPlaylistControl(IWMPCore3 *player, QWmpEvents *events, QObject *parent = 0); + ~QWmpPlaylistControl(); + + QMediaPlaylistProvider *playlistProvider() const; + bool setPlaylistProvider(QMediaPlaylistProvider *playlist); + + int currentIndex() const; + void setCurrentIndex(int position); + + int nextIndex(int steps) const; + int previousIndex(int steps) const; + + void next(); + void previous(); + + QMediaPlaylist::PlaybackMode playbackMode() const; + void setPlaybackMode(QMediaPlaylist::PlaybackMode mode); + +private slots: + void currentItemChangeEvent(IDispatch *dispatch); + +private: + IWMPCore3 *m_player; + IWMPControls *m_controls; + QWmpPlaylist *m_playlist; + QMediaPlaylist::PlaybackMode m_playbackMode; +}; + +#endif diff --git a/src/plugins/wmp/qwmpserviceprovider.cpp b/src/plugins/wmp/qwmpserviceprovider.cpp new file mode 100644 index 000000000..eec06008e --- /dev/null +++ b/src/plugins/wmp/qwmpserviceprovider.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpserviceprovider.h" + +#include "qwmpplayerservice.h" + +QStringList QWmpServiceProviderPlugin::keys() const +{ + return QStringList() + << QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) + << QLatin1String("windowsmediaplayer"); +} + +QMediaService *QWmpServiceProviderPlugin::create(const QString &key) +{ + if (QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER) == key) { + QByteArray providerKey = qgetenv("QT_MEDIAPLAYER_PROVIDER"); + if (!providerKey.isNull() && qstrcmp(providerKey.constData(), "windowsmediaplayer") == 0) + return new QWmpPlayerService(QWmpPlayerService::RemoteEmbed); + + return new QWmpPlayerService(QWmpPlayerService::LocalEmbed); + } + else if (QLatin1String("windowsmediaplayer") == key) + return new QWmpPlayerService(QWmpPlayerService::RemoteEmbed); + + return 0; +} + +void QWmpServiceProviderPlugin::release(QMediaService *service) +{ + delete service; +} + + +Q_EXPORT_PLUGIN2(qtmedia_wmp, QWmpServiceProviderPlugin); diff --git a/src/plugins/wmp/qwmpserviceprovider.h b/src/plugins/wmp/qwmpserviceprovider.h new file mode 100644 index 000000000..d58fb3bc8 --- /dev/null +++ b/src/plugins/wmp/qwmpserviceprovider.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPSERVICEPROVIDER_H +#define QWMPSERVICEPROVIDER_H + +#include <qmediaserviceprovider.h> +#include <qmediaserviceproviderplugin.h> + +QT_USE_NAMESPACE +class QWmpServiceProviderPlugin : public QMediaServiceProviderPlugin +{ + Q_OBJECT +public: + QStringList keys() const; + QMediaService *create(const QString &key); + void release(QMediaService *service); +}; + +#endif diff --git a/src/plugins/wmp/qwmpvideooverlay.cpp b/src/plugins/wmp/qwmpvideooverlay.cpp new file mode 100644 index 000000000..95ff77b6b --- /dev/null +++ b/src/plugins/wmp/qwmpvideooverlay.cpp @@ -0,0 +1,462 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qwmpvideooverlay.h" + +#include "qwmpglobal.h" + +QWmpVideoOverlay::QWmpVideoOverlay(IWMPPlayer4 *player, IOleObject *object, QWmpPlayerService *service) + : m_service(service) + , m_player(player) + , m_object(object) + , m_inPlaceObject(0) + , m_winId(0) + , m_aspectRatioMode(Qt::KeepAspectRatio) + , m_fullScreen(false) +{ + HRESULT hr; + + if ((hr = m_object->QueryInterface( + __uuidof(IOleInPlaceObject), + reinterpret_cast<void **>(&m_inPlaceObject))) != S_OK) { + qWarning("No IOleInPlaceObject interface, %x: %s", hr, qwmp_error_string(hr)); + } +} + +QWmpVideoOverlay::~QWmpVideoOverlay() +{ + if (m_inPlaceObject) + m_inPlaceObject->Release(); +} + +WId QWmpVideoOverlay::winId() const +{ + return m_winId; +} + +void QWmpVideoOverlay::setWinId(WId id) +{ + m_winId = id; + + if (QWidget *widget = QWidget::find(m_winId)) { + const QColor color = widget->palette().color(QPalette::Window); + + m_windowColor = RGB(color.red(), color.green(), color.blue()); + } + + if (m_inPlaceObject && m_winId) { + RECT rcPos = + { + m_displayRect.left(), + m_displayRect.top(), + m_displayRect.right(), + m_displayRect.bottom() + }; + + m_inPlaceObject->InPlaceDeactivate(); + m_object->DoVerb(OLEIVERB_INPLACEACTIVATE, 0, m_service, 0, m_winId, &rcPos); + } + + +} + +extern HDC Q_GUI_EXPORT qt_win_display_dc(); + +#define HIMETRIC_PER_INCH 2540 +#define MAP_PIX_TO_LOGHIM(x,ppli) ((HIMETRIC_PER_INCH*(x) + ((ppli)>>1)) / (ppli)) +#define MAP_LOGHIM_TO_PIX(x,ppli) (((ppli)*(x) + HIMETRIC_PER_INCH/2) / HIMETRIC_PER_INCH) + +QRect QWmpVideoOverlay::displayRect() const +{ + return m_displayRect; +} + +void QWmpVideoOverlay::setDisplayRect(const QRect &rect) +{ + m_displayRect = rect; + + if (m_inPlaceObject) { + HDC gdc = QT_PREPEND_NAMESPACE(qt_win_display_dc)(); + + SIZEL hmSize = { + MAP_PIX_TO_LOGHIM(rect.width(), GetDeviceCaps(gdc, LOGPIXELSX)), + MAP_PIX_TO_LOGHIM(rect.height(), GetDeviceCaps(gdc, LOGPIXELSY)) }; + + m_object->SetExtent(DVASPECT_CONTENT, &hmSize); + + RECT rcClip = { rect.left(), rect.top(), rect.right(), rect.bottom() }; + + if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) { + QSize size = m_sizeHint; + size.scale(rect.width(), rect.height(), Qt::KeepAspectRatioByExpanding); + + QRect positionRect(QPoint(0, 0), size); + positionRect.moveCenter(rect.center()); + + RECT rcPos = + { + positionRect.left(), + positionRect.top(), + positionRect.right(), + positionRect.bottom() + }; + + m_inPlaceObject->SetObjectRects(&rcPos, &rcClip); + } else { + m_inPlaceObject->SetObjectRects(&rcClip, &rcClip); + } + } +} + +bool QWmpVideoOverlay::isFullScreen() const +{ + return m_fullScreen; +} + +void QWmpVideoOverlay::setFullScreen(bool fullScreen) +{ + m_player->put_fullScreen(fullScreen); + + emit fullScreenChanged(m_fullScreen = fullScreen); +} + +QSize QWmpVideoOverlay::nativeSize() const +{ + return m_sizeHint; +} + +void QWmpVideoOverlay::setNativeSize(const QSize &size) +{ + if (m_sizeHint != size) { + m_sizeHint = size; + + emit nativeSizeChanged(); + } +} + +Qt::AspectRatioMode QWmpVideoOverlay::aspectRatioMode() const +{ + return m_aspectRatioMode; +} + +void QWmpVideoOverlay::setAspectRatioMode(Qt::AspectRatioMode mode) +{ + m_aspectRatioMode = mode; + + m_player->put_stretchToFit(mode != Qt::KeepAspectRatio); + + setDisplayRect(m_displayRect); +} + +void QWmpVideoOverlay::repaint() +{ + PAINTSTRUCT paint; + + if (HDC dc = ::BeginPaint(m_winId, &paint)) { + HPEN pen = ::CreatePen(PS_SOLID, 1, m_windowColor); + HBRUSH brush = ::CreateSolidBrush(m_windowColor); + ::SelectObject(dc, pen); + ::SelectObject(dc, brush); + + ::Rectangle( + dc, + m_displayRect.left(), + m_displayRect.top(), + m_displayRect.right() + 1, + m_displayRect.bottom() + 1); + + ::DeleteObject(pen); + ::DeleteObject(brush); + + ::EndPaint(m_winId, &paint); + } +} + +int QWmpVideoOverlay::brightness() const +{ + return 0; +} + +void QWmpVideoOverlay::setBrightness(int) +{ +} + +int QWmpVideoOverlay::contrast() const +{ + return 0; +} + +void QWmpVideoOverlay::setContrast(int) +{ +} + +int QWmpVideoOverlay::hue() const +{ + return 0; +} + +void QWmpVideoOverlay::setHue(int) +{ +} + +int QWmpVideoOverlay::saturation() const +{ + return 0; +} + +void QWmpVideoOverlay::setSaturation(int) +{ +} + +// IUnknown +HRESULT QWmpVideoOverlay::QueryInterface(REFIID riid, void **object) +{ + return m_service->QueryInterface(riid, object); +} + +ULONG QWmpVideoOverlay::AddRef() +{ + return m_service->AddRef(); +} + +ULONG QWmpVideoOverlay::Release() +{ + return m_service->Release(); +} + +// IOleWindow +HRESULT QWmpVideoOverlay::GetWindow(HWND *phwnd) +{ + if (!phwnd) { + return E_POINTER; + } else { + *phwnd = m_winId; + return S_OK; + } +} + +HRESULT QWmpVideoOverlay::ContextSensitiveHelp(BOOL fEnterMode) +{ + Q_UNUSED(fEnterMode); + + return E_NOTIMPL; +} + +// IOleInPlaceSite +HRESULT QWmpVideoOverlay::CanInPlaceActivate() +{ + return S_OK; +} + +HRESULT QWmpVideoOverlay::OnInPlaceActivate() +{ + return S_OK; +} + +HRESULT QWmpVideoOverlay::OnUIActivate() +{ + return S_OK; +} + +HRESULT QWmpVideoOverlay::GetWindowContext( + IOleInPlaceFrame **ppFrame, + IOleInPlaceUIWindow **ppDoc, + LPRECT lprcPosRect, + LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo) +{ + if (!ppFrame || !ppDoc || !lprcPosRect || !lprcClipRect || !lpFrameInfo) + return E_POINTER; + + QueryInterface(IID_IOleInPlaceFrame, reinterpret_cast<void **>(ppFrame)); + QueryInterface(IID_IOleInPlaceUIWindow, reinterpret_cast<void **>(ppDoc)); + + if (m_winId) { + SetRect(lprcClipRect, + m_displayRect.left(), + m_displayRect.top(), + m_displayRect.right(), + m_displayRect.bottom()); + + if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) { + QSize size = m_sizeHint; + size.scale( + m_displayRect.width(), + m_displayRect.height(), + Qt::KeepAspectRatioByExpanding); + + QRect positionRect(QPoint(0, 0), size); + positionRect.moveCenter(m_displayRect.center()); + + SetRect(lprcPosRect, + positionRect.left(), + positionRect.top(), + positionRect.right(), + positionRect.bottom()); + } else { + *lprcPosRect = *lprcClipRect; + } + } else { + SetRectEmpty(lprcPosRect); + SetRectEmpty(lprcClipRect); + } + + lpFrameInfo->fMDIApp = FALSE; + lpFrameInfo->haccel = 0; + lpFrameInfo->cAccelEntries = 0; + lpFrameInfo->hwndFrame = m_winId; + + return S_OK; +} + +HRESULT QWmpVideoOverlay::Scroll(SIZE scrollExtant) +{ + Q_UNUSED(scrollExtant); + + return S_FALSE; +} + +HRESULT QWmpVideoOverlay::OnUIDeactivate(BOOL fUndoable) +{ + Q_UNUSED(fUndoable); + + return S_OK; +} + +HRESULT QWmpVideoOverlay::OnInPlaceDeactivate() +{ + return S_OK; +} + +HRESULT QWmpVideoOverlay::DiscardUndoState() +{ + return S_OK; +} + +HRESULT QWmpVideoOverlay::DeactivateAndUndo() +{ + if (m_inPlaceObject) + m_inPlaceObject->UIDeactivate(); + + return S_OK; +} + +HRESULT QWmpVideoOverlay::OnPosRectChange(LPCRECT lprcPosRect) +{ + Q_UNUSED(lprcPosRect); + + return S_OK; +} + +// IOleInPlaceUIWindow +HRESULT QWmpVideoOverlay::GetBorder(LPRECT lprectBorder) +{ + Q_UNUSED(lprectBorder); + + return INPLACE_E_NOTOOLSPACE; +} + +HRESULT QWmpVideoOverlay::RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) +{ + Q_UNUSED(pborderwidths); + + return INPLACE_E_NOTOOLSPACE; +} + +HRESULT QWmpVideoOverlay::SetBorderSpace(LPCBORDERWIDTHS pborderwidths) +{ + Q_UNUSED(pborderwidths); + + return OLE_E_INVALIDRECT; +} + +HRESULT QWmpVideoOverlay::SetActiveObject( + IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName) +{ + Q_UNUSED(pActiveObject); + Q_UNUSED(pszObjName); + + return S_OK; +} + +// IOleInPlaceFrame +HRESULT QWmpVideoOverlay::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) +{ + Q_UNUSED(hmenuShared); + Q_UNUSED(lpMenuWidths); + + return E_NOTIMPL; +} + +HRESULT QWmpVideoOverlay::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) +{ + Q_UNUSED(hmenuShared); + Q_UNUSED(holemenu); + Q_UNUSED(hwndActiveObject); + + return E_NOTIMPL; +} + +HRESULT QWmpVideoOverlay::RemoveMenus(HMENU hmenuShared) +{ + Q_UNUSED(hmenuShared); + + return E_NOTIMPL; +} + +HRESULT QWmpVideoOverlay::SetStatusText(LPCOLESTR pszStatusText) +{ + Q_UNUSED(pszStatusText); + + return E_NOTIMPL; +} + +HRESULT QWmpVideoOverlay::EnableModeless(BOOL fEnable) +{ + Q_UNUSED(fEnable); + + return E_NOTIMPL; +} + +HRESULT QWmpVideoOverlay::TranslateAccelerator(LPMSG lpmsg, WORD wID) +{ + return TranslateAccelerator(lpmsg, static_cast<DWORD>(wID)); +} diff --git a/src/plugins/wmp/qwmpvideooverlay.h b/src/plugins/wmp/qwmpvideooverlay.h new file mode 100644 index 000000000..3bc1005a7 --- /dev/null +++ b/src/plugins/wmp/qwmpvideooverlay.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +#ifndef QWMPVIDEOOVERLAY_H +#define QWMPVIDEOOVERLAY_H + +#include <qvideowindowcontrol.h> + +#include "qwmpplayerservice.h" + +#include <wmp.h> + +QT_USE_NAMESPACE +class QWmpVideoOverlay + : public QVideoWindowControl + , public IOleInPlaceSite + , public IOleInPlaceFrame +{ + Q_OBJECT +public: + QWmpVideoOverlay(IWMPPlayer4 *player, IOleObject *object, QWmpPlayerService *service); + ~QWmpVideoOverlay(); + + WId winId() const; + void setWinId(WId id); + + QRect displayRect() const; + void setDisplayRect(const QRect &rect); + + bool isFullScreen() const; + void setFullScreen(bool fullScreen); + + void repaint(); + + QSize nativeSize() const; + void setNativeSize(const QSize &size); + + Qt::AspectRatioMode aspectRatioMode() const; + void setAspectRatioMode(Qt::AspectRatioMode mode); + + int brightness() const; + void setBrightness(int brightness); + + int contrast() const; + void setContrast(int contrast); + + int hue() const; + void setHue(int hue); + + int saturation() const; + void setSaturation(int saturation); + + // IUnknown + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IOleWindow + HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd); + HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); + + // IOleInPlaceSite + HRESULT STDMETHODCALLTYPE CanInPlaceActivate(); + HRESULT STDMETHODCALLTYPE OnInPlaceActivate(); + HRESULT STDMETHODCALLTYPE OnUIActivate(); + HRESULT STDMETHODCALLTYPE GetWindowContext( + IOleInPlaceFrame **ppFrame, + IOleInPlaceUIWindow **ppDoc, + LPRECT lprcPosRect, + LPRECT lprcClipRect, + LPOLEINPLACEFRAMEINFO lpFrameInfo); + HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtant); + HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable); + HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate(); + HRESULT STDMETHODCALLTYPE DiscardUndoState(); + HRESULT STDMETHODCALLTYPE DeactivateAndUndo(); + HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect); + + // IOleInPlaceUIWindow + HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder); + HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths); + HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths); + HRESULT STDMETHODCALLTYPE SetActiveObject( + IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName); + + // IOleInPlaceFrame + HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths); + HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject); + HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared); + HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText); + HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable); + HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID); + +private: + QWmpPlayerService *m_service; + IWMPPlayer4 *m_player; + IOleObject *m_object; + IOleInPlaceObject *m_inPlaceObject; + WId m_winId; + COLORREF m_windowColor; + Qt::AspectRatioMode m_aspectRatioMode; + QSize m_sizeHint; + QRect m_displayRect; + bool m_fullScreen; +}; + +#endif diff --git a/src/plugins/wmp/wmp.pro b/src/plugins/wmp/wmp.pro new file mode 100644 index 000000000..1b544bbeb --- /dev/null +++ b/src/plugins/wmp/wmp.pro @@ -0,0 +1,47 @@ +TEMPLATE = lib +CONFIG += plugin +TARGET = $$qtLibraryTarget(qtmedia_wmp) + +PLUGIN_TYPE=mediaservice + +INCLUDEPATH+=../../../src/multimedia +include(../../../common.pri) + +CONFIG += mobility +MOBILITY = multimedia +LIBS += -lstrmiids -lole32 -lOleaut32 -luser32 -lgdi32 + +HEADERS = \ + qmfactivate.h \ + qwmpevents.h \ + qwmpglobal.h \ + qwmpmetadata.h \ + qwmpplayercontrol.h \ + qwmpplayerservice.h \ + qwmpplaylist.h \ + qwmpplaylistcontrol.h \ + qwmpserviceprovider.h \ + qwmpvideooverlay.h + +SOURCES = \ + qmfactivate.cpp \ + qwmpevents.cpp \ + qwmpglobal.cpp \ + qwmpmetadata.cpp \ + qwmpplayercontrol.cpp \ + qwmpplayerservice.cpp \ + qwmpplaylist.cpp \ + qwmpplaylistcontrol.cpp \ + qwmpserviceprovider.cpp \ + qwmpvideooverlay.cpp + +contains(evr_enabled, yes) { + HEADERS += \ + qevrvideooverlay.h + + SOURCES += \ + qevrvideooverlay.cpp + + DEFINES += \ + QWMP_EVR +} |