summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/wshellitem/main.cpp50
-rw-r--r--config.tests/wshellitem/wshellitem.pro4
-rw-r--r--qtmultimedia.pro4
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.cpp400
-rw-r--r--src/plugins/directshow/player/directshowmetadatacontrol.h15
-rw-r--r--src/plugins/directshow/player/directshowplayerservice.cpp19
-rw-r--r--src/plugins/directshow/player/player.pri6
7 files changed, 402 insertions, 96 deletions
diff --git a/config.tests/wshellitem/main.cpp b/config.tests/wshellitem/main.cpp
new file mode 100644
index 000000000..c9e427275
--- /dev/null
+++ b/config.tests/wshellitem/main.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <ShlObj.h>
+
+int main(int, char**)
+{
+ IShellItem2 *item;
+ IPropertyStore *store;
+
+ return 0;
+}
diff --git a/config.tests/wshellitem/wshellitem.pro b/config.tests/wshellitem/wshellitem.pro
new file mode 100644
index 000000000..abb9ba83a
--- /dev/null
+++ b/config.tests/wshellitem/wshellitem.pro
@@ -0,0 +1,4 @@
+CONFIG -= qt
+CONFIG += console
+
+SOURCES += main.cpp
diff --git a/qtmultimedia.pro b/qtmultimedia.pro
index 0c5ad66fb..f3ede6cac 100644
--- a/qtmultimedia.pro
+++ b/qtmultimedia.pro
@@ -4,7 +4,9 @@ load(configure)
qtCompileTest(openal)
qtCompileTest(opensles)
win32 {
- qtCompileTest(directshow)
+ qtCompileTest(directshow) {
+ qtCompileTest(wshellitem)
+ }
qtCompileTest(wmsdk)
qtCompileTest(wmp)
contains(QT_CONFIG, wmf-backend): qtCompileTest(wmf)
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.cpp b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
index 341d2cf1d..3c81ae180 100644
--- a/src/plugins/directshow/player/directshowmetadatacontrol.cpp
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.cpp
@@ -39,6 +39,12 @@
**
****************************************************************************/
+#include <QtMultimedia/qmediametadata.h>
+#include <QtCore/qcoreapplication.h>
+#include <QSize>
+#include <qdatetime.h>
+#include <qimage.h>
+
#include <dshow.h>
#include <initguid.h>
#include <qnetwork.h>
@@ -46,8 +52,56 @@
#include "directshowmetadatacontrol.h"
#include "directshowplayerservice.h"
-#include <QtMultimedia/qmediametadata.h>
-#include <QtCore/qcoreapplication.h>
+#ifndef QT_NO_WMSDK
+#include <wmsdk.h>
+#endif
+
+#ifndef QT_NO_SHELLITEM
+#include <ShlObj.h>
+#include <propkeydef.h>
+#include <private/qsystemlibrary_p.h>
+
+DEFINE_PROPERTYKEY(PKEY_Author, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 4);
+DEFINE_PROPERTYKEY(PKEY_Title, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 2);
+DEFINE_PROPERTYKEY(PKEY_Media_SubTitle, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 38);
+DEFINE_PROPERTYKEY(PKEY_ParentalRating, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 21);
+DEFINE_PROPERTYKEY(PKEY_Comment, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 6);
+DEFINE_PROPERTYKEY(PKEY_Copyright, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 11);
+DEFINE_PROPERTYKEY(PKEY_Media_ProviderStyle, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 40);
+DEFINE_PROPERTYKEY(PKEY_Media_Year, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 5);
+DEFINE_PROPERTYKEY(PKEY_Media_DateEncoded, 0x2E4B640D, 0x5019, 0x46D8, 0x88, 0x81, 0x55, 0x41, 0x4C, 0xC5, 0xCA, 0xA0, 100);
+DEFINE_PROPERTYKEY(PKEY_Rating, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 9);
+DEFINE_PROPERTYKEY(PKEY_Keywords, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 5);
+DEFINE_PROPERTYKEY(PKEY_Language, 0xD5CDD502, 0x2E9C, 0x101B, 0x93, 0x97, 0x08, 0x00, 0x2B, 0x2C, 0xF9, 0xAE, 28);
+DEFINE_PROPERTYKEY(PKEY_Media_Publisher, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 30);
+DEFINE_PROPERTYKEY(PKEY_Media_Duration, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 3);
+DEFINE_PROPERTYKEY(PKEY_Audio_EncodingBitrate, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 4);
+DEFINE_PROPERTYKEY(PKEY_Media_AverageLevel, 0x09EDD5B6, 0xB301, 0x43C5, 0x99, 0x90, 0xD0, 0x03, 0x02, 0xEF, 0xFD, 0x46, 100);
+DEFINE_PROPERTYKEY(PKEY_Audio_ChannelCount, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 7);
+DEFINE_PROPERTYKEY(PKEY_Audio_PeakValue, 0x2579E5D0, 0x1116, 0x4084, 0xBD, 0x9A, 0x9B, 0x4F, 0x7C, 0xB4, 0xDF, 0x5E, 100);
+DEFINE_PROPERTYKEY(PKEY_Audio_SampleRate, 0x64440490, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 5);
+DEFINE_PROPERTYKEY(PKEY_Music_AlbumTitle, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 4);
+DEFINE_PROPERTYKEY(PKEY_Music_AlbumArtist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 13);
+DEFINE_PROPERTYKEY(PKEY_Music_Artist, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 2);
+DEFINE_PROPERTYKEY(PKEY_Music_Composer, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 19);
+DEFINE_PROPERTYKEY(PKEY_Music_Conductor, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 36);
+DEFINE_PROPERTYKEY(PKEY_Music_Lyrics, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 12);
+DEFINE_PROPERTYKEY(PKEY_Music_Mood, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 39);
+DEFINE_PROPERTYKEY(PKEY_Music_TrackNumber, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 7);
+DEFINE_PROPERTYKEY(PKEY_Music_Genre, 0x56A3372E, 0xCE9C, 0x11D2, 0x9F, 0x0E, 0x00, 0x60, 0x97, 0xC6, 0x86, 0xF6, 11);
+DEFINE_PROPERTYKEY(PKEY_ThumbnailStream, 0xF29F85E0, 0x4FF9, 0x1068, 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9, 27);
+DEFINE_PROPERTYKEY(PKEY_Video_FrameHeight, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 4);
+DEFINE_PROPERTYKEY(PKEY_Video_FrameWidth, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 3);
+DEFINE_PROPERTYKEY(PKEY_Video_HorizontalAspectRatio, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 42);
+DEFINE_PROPERTYKEY(PKEY_Video_VerticalAspectRatio, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 45);
+DEFINE_PROPERTYKEY(PKEY_Video_FrameRate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 6);
+DEFINE_PROPERTYKEY(PKEY_Video_EncodingBitrate, 0x64440491, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 8);
+DEFINE_PROPERTYKEY(PKEY_Video_Director, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 20);
+DEFINE_PROPERTYKEY(PKEY_Media_Writer, 0x64440492, 0x4C8B, 0x11D1, 0x8B, 0x70, 0x08, 0x00, 0x36, 0xB1, 0x1A, 0x03, 23);
+
+typedef HRESULT (WINAPI *q_SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
+static q_SHCreateItemFromParsingName sHCreateItemFromParsingName = 0;
+#endif
#ifndef QT_NO_WMSDK
namespace
@@ -70,12 +124,12 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
{ QMediaMetaData::Genre, L"WM/Genre" },
//{ QMediaMetaData::Date, 0 },
{ QMediaMetaData::Year, L"WM/Year" },
- { QMediaMetaData::UserRating, L"UserRating" },
+ { QMediaMetaData::UserRating, L"Rating" },
//{ QMediaMetaData::MetaDatawords, 0 },
- { QMediaMetaData::Language, L"Language" },
+ { QMediaMetaData::Language, L"WM/Language" },
{ QMediaMetaData::Publisher, L"WM/Publisher" },
{ QMediaMetaData::Copyright, L"Copyright" },
- { QMediaMetaData::ParentalRating, L"ParentalRating" },
+ { QMediaMetaData::ParentalRating, L"WM/ParentalRating" },
//{ QMediaMetaData::RatingOrganisation, L"RatingOrganisation" },
// Media
@@ -103,11 +157,11 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
//{ QMediaMetaData::CoverArtUriLarge, 0 },
// Image/Video
- //{ QMediaMetaData::Resolution, 0 },
- //{ QMediaMetaData::PixelAspectRatio, 0 },
+ { QMediaMetaData::Resolution, L"WM/VideoHeight" },
+ { QMediaMetaData::PixelAspectRatio, L"AspectRatioX" },
// Video
- //{ QMediaMetaData::FrameRate, 0 },
+ { QMediaMetaData::VideoFrameRate, L"WM/VideoFrameRate" },
{ QMediaMetaData::VideoBitRate, L"VideoBitRate" },
{ QMediaMetaData::VideoCodec, L"VideoCodec" },
@@ -118,12 +172,6 @@ static const QWMMetaDataKeyLookup qt_wmMetaDataKeys[] =
{ QMediaMetaData::Director, L"WM/Director" },
{ QMediaMetaData::LeadPerformer, L"LeadPerformer" },
{ QMediaMetaData::Writer, L"WM/Writer" },
-
- // Photos
- { QMediaMetaData::CameraManufacturer, L"CameraManufacturer" },
- { QMediaMetaData::CameraModel, L"CameraModel" },
- { QMediaMetaData::Event, L"Event" },
- { QMediaMetaData::Subject, L"Subject" }
};
static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
@@ -150,7 +198,7 @@ static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
case WMT_TYPE_STRING:
{
QString string;
- string.resize(size / 2 - 1);
+ string.resize(size / 2); // size is in bytes, string is in UTF16
if (header->GetAttributeByName(
&streamNumber,
@@ -227,12 +275,58 @@ static QVariant getValue(IWMHeaderInfo *header, const wchar_t *key)
}
#endif
+#ifndef QT_NO_SHELLITEM
+static QVariant convertValue(const PROPVARIANT& var)
+{
+ QVariant value;
+ switch (var.vt) {
+ case VT_LPWSTR:
+ value = QString::fromUtf16(reinterpret_cast<const ushort*>(var.pwszVal));
+ break;
+ case VT_UI4:
+ value = uint(var.ulVal);
+ break;
+ case VT_UI8:
+ value = qulonglong(var.uhVal.QuadPart);
+ break;
+ case VT_BOOL:
+ value = bool(var.boolVal);
+ break;
+ case VT_FILETIME:
+ SYSTEMTIME sysDate;
+ if (!FileTimeToSystemTime(&var.filetime, &sysDate))
+ break;
+ value = QDate(sysDate.wYear, sysDate.wMonth, sysDate.wDay);
+ break;
+ case VT_STREAM:
+ {
+ STATSTG stat;
+ if (FAILED(var.pStream->Stat(&stat, STATFLAG_NONAME)))
+ break;
+ void *data = malloc(stat.cbSize.QuadPart);
+ ULONG read = 0;
+ if (FAILED(var.pStream->Read(data, stat.cbSize.QuadPart, &read))) {
+ free(data);
+ break;
+ }
+ value = QImage::fromData(reinterpret_cast<const uchar*>(data), read);
+ free(data);
+ }
+ break;
+ case VT_VECTOR | VT_LPWSTR:
+ QStringList vList;
+ for (ULONG i = 0; i < var.calpwstr.cElems; ++i)
+ vList.append(QString::fromUtf16(reinterpret_cast<const ushort*>(var.calpwstr.pElems[i])));
+ value = vList;
+ break;
+ }
+ return value;
+}
+#endif
+
DirectShowMetaDataControl::DirectShowMetaDataControl(QObject *parent)
: QMetaDataReaderControl(parent)
- , m_content(0)
-#ifndef QT_NO_WMSDK
- , m_headerInfo(0)
-#endif
+ , m_available(false)
{
}
@@ -242,75 +336,229 @@ DirectShowMetaDataControl::~DirectShowMetaDataControl()
bool DirectShowMetaDataControl::isMetaDataAvailable() const
{
-#ifndef QT_NO_WMSDK
- return m_content || m_headerInfo;
-#else
- return m_content;
-#endif
+ return m_available;
}
QVariant DirectShowMetaDataControl::metaData(const QString &key) const
{
- QVariant value;
+ return m_metadata.value(key);
+}
+
+QStringList DirectShowMetaDataControl::availableMetaData() const
+{
+ return m_metadata.keys();
+}
+
+static QString convertBSTR(BSTR *string)
+{
+ QString value = QString::fromUtf16(reinterpret_cast<ushort *>(*string),
+ ::SysStringLen(*string));
+
+ ::SysFreeString(*string);
+ string = 0;
+
+ return value;
+}
+
+void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source, const QString &fileSrc)
+{
+ m_metadata.clear();
+
+#ifndef QT_NO_SHELLITEM
+ if (!sHCreateItemFromParsingName) {
+ QSystemLibrary lib(QStringLiteral("shell32"));
+ sHCreateItemFromParsingName = (q_SHCreateItemFromParsingName)(lib.resolve("SHCreateItemFromParsingName"));
+ }
+
+ if (!fileSrc.isEmpty() && sHCreateItemFromParsingName) {
+ IShellItem2* shellItem = 0;
+ if (sHCreateItemFromParsingName(reinterpret_cast<const WCHAR*>(fileSrc.utf16()),
+ 0, IID_PPV_ARGS(&shellItem)) == S_OK) {
+
+ IPropertyStore *pStore = 0;
+ if (shellItem->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pStore)) == S_OK) {
+ DWORD cProps;
+ if (SUCCEEDED(pStore->GetCount(&cProps))) {
+ for (DWORD i = 0; i < cProps; ++i)
+ {
+ PROPERTYKEY key;
+ PROPVARIANT var;
+ PropVariantInit(&var);
+ if (FAILED(pStore->GetAt(i, &key)))
+ continue;
+ if (FAILED(pStore->GetValue(key, &var)))
+ continue;
+
+ if (key == PKEY_Author) {
+ m_metadata.insert(QMediaMetaData::Author, convertValue(var));
+ } else if (key == PKEY_Title) {
+ m_metadata.insert(QMediaMetaData::Title, convertValue(var));
+ } else if (key == PKEY_Media_SubTitle) {
+ m_metadata.insert(QMediaMetaData::SubTitle, convertValue(var));
+ } else if (key == PKEY_ParentalRating) {
+ m_metadata.insert(QMediaMetaData::ParentalRating, convertValue(var));
+ } else if (key == PKEY_Comment) {
+ m_metadata.insert(QMediaMetaData::Description, convertValue(var));
+ } else if (key == PKEY_Copyright) {
+ m_metadata.insert(QMediaMetaData::Copyright, convertValue(var));
+ } else if (key == PKEY_Media_ProviderStyle) {
+ m_metadata.insert(QMediaMetaData::Genre, convertValue(var));
+ } else if (key == PKEY_Media_Year) {
+ m_metadata.insert(QMediaMetaData::Year, convertValue(var));
+ } else if (key == PKEY_Media_DateEncoded) {
+ m_metadata.insert(QMediaMetaData::Date, convertValue(var));
+ } else if (key == PKEY_Rating) {
+ m_metadata.insert(QMediaMetaData::UserRating,
+ int((convertValue(var).toUInt() - 1) / qreal(98) * 100));
+ } else if (key == PKEY_Keywords) {
+ m_metadata.insert(QMediaMetaData::Keywords, convertValue(var));
+ } else if (key == PKEY_Language) {
+ m_metadata.insert(QMediaMetaData::Language, convertValue(var));
+ } else if (key == PKEY_Media_Publisher) {
+ m_metadata.insert(QMediaMetaData::Publisher, convertValue(var));
+ } else if (key == PKEY_Media_Duration) {
+ m_metadata.insert(QMediaMetaData::Duration,
+ (convertValue(var).toLongLong() + 10000) / 10000);
+ } else if (key == PKEY_Audio_EncodingBitrate) {
+ m_metadata.insert(QMediaMetaData::AudioBitRate, convertValue(var));
+ } else if (key == PKEY_Media_AverageLevel) {
+ m_metadata.insert(QMediaMetaData::AverageLevel, convertValue(var));
+ } else if (key == PKEY_Audio_ChannelCount) {
+ m_metadata.insert(QMediaMetaData::ChannelCount, convertValue(var));
+ } else if (key == PKEY_Audio_PeakValue) {
+ m_metadata.insert(QMediaMetaData::PeakValue, convertValue(var));
+ } else if (key == PKEY_Audio_SampleRate) {
+ m_metadata.insert(QMediaMetaData::SampleRate, convertValue(var));
+ } else if (key == PKEY_Music_AlbumTitle) {
+ m_metadata.insert(QMediaMetaData::AlbumTitle, convertValue(var));
+ } else if (key == PKEY_Music_AlbumArtist) {
+ m_metadata.insert(QMediaMetaData::AlbumArtist, convertValue(var));
+ } else if (key == PKEY_Music_Artist) {
+ m_metadata.insert(QMediaMetaData::ContributingArtist, convertValue(var));
+ } else if (key == PKEY_Music_Composer) {
+ m_metadata.insert(QMediaMetaData::Composer, convertValue(var));
+ } else if (key == PKEY_Music_Conductor) {
+ m_metadata.insert(QMediaMetaData::Conductor, convertValue(var));
+ } else if (key == PKEY_Music_Lyrics) {
+ m_metadata.insert(QMediaMetaData::Lyrics, convertValue(var));
+ } else if (key == PKEY_Music_Mood) {
+ m_metadata.insert(QMediaMetaData::Mood, convertValue(var));
+ } else if (key == PKEY_Music_TrackNumber) {
+ m_metadata.insert(QMediaMetaData::TrackNumber, convertValue(var));
+ } else if (key == PKEY_Music_Genre) {
+ m_metadata.insert(QMediaMetaData::Genre, convertValue(var));
+ } else if (key == PKEY_ThumbnailStream) {
+ m_metadata.insert(QMediaMetaData::ThumbnailImage, convertValue(var));
+ } else if (key == PKEY_Video_FrameHeight) {
+ QSize res;
+ res.setHeight(convertValue(var).toUInt());
+ if (SUCCEEDED(pStore->GetValue(PKEY_Video_FrameWidth, &var)))
+ res.setWidth(convertValue(var).toUInt());
+ m_metadata.insert(QMediaMetaData::Resolution, res);
+ } else if (key == PKEY_Video_HorizontalAspectRatio) {
+ QSize aspectRatio;
+ aspectRatio.setWidth(convertValue(var).toUInt());
+ if (SUCCEEDED(pStore->GetValue(PKEY_Video_VerticalAspectRatio, &var)))
+ aspectRatio.setHeight(convertValue(var).toUInt());
+ m_metadata.insert(QMediaMetaData::PixelAspectRatio, aspectRatio);
+ } else if (key == PKEY_Video_FrameRate) {
+ m_metadata.insert(QMediaMetaData::VideoFrameRate,
+ convertValue(var).toReal() / 1000);
+ } else if (key == PKEY_Video_EncodingBitrate) {
+ m_metadata.insert(QMediaMetaData::VideoBitRate, convertValue(var));
+ } else if (key == PKEY_Video_Director) {
+ m_metadata.insert(QMediaMetaData::Director, convertValue(var));
+ } else if (key == PKEY_Media_Writer) {
+ m_metadata.insert(QMediaMetaData::Writer, convertValue(var));
+ }
+
+ PropVariantClear(&var);
+ }
+ }
+
+ pStore->Release();
+ }
+
+ shellItem->Release();
+ }
+ }
+
+ if (!m_metadata.isEmpty())
+ goto send_event;
+#endif
#ifndef QT_NO_WMSDK
- if (m_headerInfo) {
+ IWMHeaderInfo *info = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo);
+
+ if (info) {
static const int count = sizeof(qt_wmMetaDataKeys) / sizeof(QWMMetaDataKeyLookup);
for (int i = 0; i < count; ++i) {
- if (qt_wmMetaDataKeys[i].key == key) {
- value = getValue(m_headerInfo, qt_wmMetaDataKeys[i].token);
- break;
+ QVariant var = getValue(info, qt_wmMetaDataKeys[i].token);
+ if (var.isValid()) {
+ QString key = qt_wmMetaDataKeys[i].key;
+
+ if (key == QMediaMetaData::Duration) {
+ // duration is provided in 100-nanosecond units, convert to milliseconds
+ var = (var.toLongLong() + 10000) / 10000;
+ } else if (key == QMediaMetaData::Resolution) {
+ QSize res;
+ res.setHeight(var.toUInt());
+ res.setWidth(getValue(info, L"WM/VideoWidth").toUInt());
+ var = res;
+ } else if (key == QMediaMetaData::VideoFrameRate) {
+ var = var.toReal() / 1000.f;
+ } else if (key == QMediaMetaData::PixelAspectRatio) {
+ QSize aspectRatio;
+ aspectRatio.setWidth(var.toUInt());
+ aspectRatio.setHeight(getValue(info, L"AspectRatioY").toUInt());
+ var = aspectRatio;
+ } else if (key == QMediaMetaData::UserRating) {
+ var = (var.toUInt() - 1) / qreal(98) * 100;
+ }
+
+ m_metadata.insert(key, var);
}
}
- } else if (m_content) {
-#else
- if (m_content) {
+
+ info->Release();
+ }
+
+ if (!m_metadata.isEmpty())
+ goto send_event;
#endif
- BSTR string = 0;
-
- if (key == QMediaMetaData::Author)
- m_content->get_AuthorName(&string);
- else if (key == QMediaMetaData::Title)
- m_content->get_Title(&string);
- else if (key == QMediaMetaData::ParentalRating)
- m_content->get_Rating(&string);
- else if (key == QMediaMetaData::Description)
- m_content->get_Description(&string);
- else if (key == QMediaMetaData::Copyright)
- m_content->get_Copyright(&string);
-
- if (string) {
- value = QString::fromUtf16(reinterpret_cast<ushort *>(string), ::SysStringLen(string));
-
- ::SysFreeString(string);
+ {
+ IAMMediaContent *content = 0;
+
+ if ((!graph || graph->QueryInterface(
+ IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK)
+ && (!source || source->QueryInterface(
+ IID_IAMMediaContent, reinterpret_cast<void **>(&content)) != S_OK)) {
+ content = 0;
}
- }
- return value;
-}
-QStringList DirectShowMetaDataControl::availableMetaData() const
-{
- return QStringList();
-}
+ if (content) {
+ BSTR string = 0;
-void DirectShowMetaDataControl::updateGraph(IFilterGraph2 *graph, IBaseFilter *source)
-{
- if (m_content)
- m_content->Release();
+ if (content->get_AuthorName(&string) == S_OK)
+ m_metadata.insert(QMediaMetaData::Author, convertBSTR(&string));
- if (!graph || graph->QueryInterface(
- IID_IAMMediaContent, reinterpret_cast<void **>(&m_content)) != S_OK) {
- m_content = 0;
- }
+ if (content->get_Title(&string) == S_OK)
+ m_metadata.insert(QMediaMetaData::Title, convertBSTR(&string));
-#ifdef QT_NO_WMSDK
- Q_UNUSED(source);
-#else
- if (m_headerInfo)
- m_headerInfo->Release();
+ if (content->get_Description(&string) == S_OK)
+ m_metadata.insert(QMediaMetaData::Description, convertBSTR(&string));
- m_headerInfo = com_cast<IWMHeaderInfo>(source, IID_IWMHeaderInfo);
-#endif
+ if (content->get_Rating(&string) == S_OK)
+ m_metadata.insert(QMediaMetaData::UserRating, convertBSTR(&string));
+
+ if (content->get_Copyright(&string) == S_OK)
+ m_metadata.insert(QMediaMetaData::Copyright, convertBSTR(&string));
+
+ content->Release();
+ }
+ }
+
+send_event:
// DirectShowMediaPlayerService holds a lock at this point so defer emitting signals to a later
// time.
QCoreApplication::postEvent(this, new QEvent(QEvent::Type(MetaDataChanged)));
@@ -321,12 +569,12 @@ void DirectShowMetaDataControl::customEvent(QEvent *event)
if (event->type() == QEvent::Type(MetaDataChanged)) {
event->accept();
+ bool oldAvailable = m_available;
+ m_available = !m_metadata.isEmpty();
+ if (m_available != oldAvailable)
+ emit metaDataAvailableChanged(m_available);
+
emit metaDataChanged();
-#ifndef QT_NO_WMSDK
- emit metaDataAvailableChanged(m_content || m_headerInfo);
-#else
- emit metaDataAvailableChanged(m_content);
-#endif
} else {
QMetaDataReaderControl::customEvent(event);
}
diff --git a/src/plugins/directshow/player/directshowmetadatacontrol.h b/src/plugins/directshow/player/directshowmetadatacontrol.h
index fb740ee1c..935e75ee0 100644
--- a/src/plugins/directshow/player/directshowmetadatacontrol.h
+++ b/src/plugins/directshow/player/directshowmetadatacontrol.h
@@ -46,12 +46,6 @@
#include "directshowglobal.h"
-#include <qnetwork.h>
-
-#ifndef QT_NO_WMSDK
-#include <wmsdk.h>
-#endif
-
#include <QtCore/qcoreevent.h>
class DirectShowPlayerService;
@@ -70,7 +64,8 @@ public:
QVariant metaData(const QString &key) const;
QStringList availableMetaData() const;
- void updateGraph(IFilterGraph2 *graph, IBaseFilter *source);
+ void updateGraph(IFilterGraph2 *graph, IBaseFilter *source,
+ const QString &fileSrc = QString());
protected:
void customEvent(QEvent *event);
@@ -81,10 +76,8 @@ private:
MetaDataChanged = QEvent::User
};
- IAMMediaContent *m_content;
-#ifndef QT_NO_WMSDK
- IWMHeaderInfo *m_headerInfo;
-#endif
+ QVariantMap m_metadata;
+ bool m_available;
};
#endif
diff --git a/src/plugins/directshow/player/directshowplayerservice.cpp b/src/plugins/directshow/player/directshowplayerservice.cpp
index 70049e245..9d74be592 100644
--- a/src/plugins/directshow/player/directshowplayerservice.cpp
+++ b/src/plugins/directshow/player/directshowplayerservice.cpp
@@ -50,6 +50,10 @@
#include "vmr9videowindowcontrol.h"
#endif
+#ifndef QT_NO_WMSDK
+#include <wmsdk.h>
+#endif
+
#include "qmediacontent.h"
#include <QtCore/qcoreapplication.h>
@@ -268,11 +272,10 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
IBaseFilter *source = 0;
QMediaResource resource = m_resources.takeFirst();
- QUrl url = resource.url();
+ m_url = resource.url();
HRESULT hr = E_FAIL;
-
- if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https")) {
+ if (m_url.scheme() == QLatin1String("http") || m_url.scheme() == QLatin1String("https")) {
static const GUID clsid_WMAsfReader = {
0x187463a0, 0x5bb7, 0x11d3, {0xac, 0xbe, 0x00, 0x80, 0xc7, 0x5e, 0x24, 0x6e} };
@@ -283,7 +286,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
if (IFileSourceFilter *fileSource = com_new<IFileSourceFilter>(
clsid_WMAsfReader, iid_IFileSourceFilter)) {
locker->unlock();
- hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(url.toString().utf16()), 0);
+ hr = fileSource->Load(reinterpret_cast<const OLECHAR *>(m_url.toString().utf16()), 0);
if (SUCCEEDED(hr)) {
source = com_cast<IBaseFilter>(fileSource, IID_IBaseFilter);
@@ -296,11 +299,11 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
fileSource->Release();
locker->relock();
}
- } else if (url.scheme() == QLatin1String("qrc")) {
+ } else if (m_url.scheme() == QLatin1String("qrc")) {
DirectShowRcSource *rcSource = new DirectShowRcSource(m_loop);
locker->unlock();
- if (rcSource->open(url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source")))
+ if (rcSource->open(m_url) && SUCCEEDED(hr = m_graph->AddFilter(rcSource, L"Source")))
source = rcSource;
else
rcSource->Release();
@@ -310,7 +313,7 @@ void DirectShowPlayerService::doSetUrlSource(QMutexLocker *locker)
if (!SUCCEEDED(hr)) {
locker->unlock();
hr = m_graph->AddSourceFilter(
- reinterpret_cast<const OLECHAR *>(url.toString().utf16()), L"Source", &source);
+ reinterpret_cast<const OLECHAR *>(m_url.toString().utf16()), L"Source", &source);
locker->relock();
}
@@ -1128,7 +1131,7 @@ void DirectShowPlayerService::customEvent(QEvent *event)
QMutexLocker locker(&m_mutex);
m_playerControl->updateMediaInfo(m_duration, m_streamTypes, m_seekable);
- m_metaDataControl->updateGraph(m_graph, m_source);
+ m_metaDataControl->updateGraph(m_graph, m_source, m_url.toString());
updateStatus();
} else if (event->type() == QEvent::Type(Error)) {
diff --git a/src/plugins/directshow/player/player.pri b/src/plugins/directshow/player/player.pri
index e9675c2c9..c5c934a38 100644
--- a/src/plugins/directshow/player/player.pri
+++ b/src/plugins/directshow/player/player.pri
@@ -43,5 +43,11 @@ qtHaveModule(widgets):!simulator {
$$PWD/vmr9videowindowcontrol.cpp
}
+config_wshellitem {
+ QT += core-private
+} else {
+ DEFINES += QT_NO_SHELLITEM
+}
+
LIBS += -lstrmiids -ldmoguids -luuid -lmsdmo -lole32 -loleaut32 -lgdi32