diff options
-rw-r--r-- | config.tests/wshellitem/main.cpp | 50 | ||||
-rw-r--r-- | config.tests/wshellitem/wshellitem.pro | 4 | ||||
-rw-r--r-- | qtmultimedia.pro | 4 | ||||
-rw-r--r-- | src/plugins/directshow/player/directshowmetadatacontrol.cpp | 400 | ||||
-rw-r--r-- | src/plugins/directshow/player/directshowmetadatacontrol.h | 15 | ||||
-rw-r--r-- | src/plugins/directshow/player/directshowplayerservice.cpp | 19 | ||||
-rw-r--r-- | src/plugins/directshow/player/player.pri | 6 |
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 |