plugins/multimedia/wmp/qwmpmetadata.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwmpmetadata.h"
       
    43 
       
    44 #include "qwmpevents.h"
       
    45 #include "qwmpglobal.h"
       
    46 
       
    47 #include <qmediacontent.h>
       
    48 
       
    49 #include <QtCore/qdatetime.h>
       
    50 #include <QtCore/qdir.h>
       
    51 #include <QtCore/qfileinfo.h>
       
    52 #include <QtCore/qsize.h>
       
    53 #include <QtCore/qstringlist.h>
       
    54 #include <QtCore/qurl.h>
       
    55 #include <QtCore/qvariant.h>
       
    56 
       
    57 
       
    58 struct QWmpMetaDataKeyLookup
       
    59 {
       
    60     QtMultimediaKit::MetaData key;
       
    61     const wchar_t *token;
       
    62 };
       
    63 
       
    64 static const QWmpMetaDataKeyLookup qt_wmpMetaDataKeys[] =
       
    65 {
       
    66     { QtMultimediaKit::Title, L"Title" },
       
    67     { QtMultimediaKit::SubTitle, L"WM/SubTitle" },
       
    68     { QtMultimediaKit::Author, L"Author" },
       
    69     { QtMultimediaKit::Comment, L"Comment" },
       
    70     { QtMultimediaKit::Description, L"Description" },
       
    71     { QtMultimediaKit::Category, L"WM/Category" },
       
    72     { QtMultimediaKit::Genre, L"WM/Genre" },
       
    73     //{ QtMultimediaKit::Date, 0 },
       
    74     { QtMultimediaKit::Year, L"WM/Year" },
       
    75     { QtMultimediaKit::UserRating, L"UserRating" },
       
    76     //{ QtMultimediaKit::MetaDatawords, 0 },
       
    77     { QtMultimediaKit::Language, L"Language" },
       
    78     { QtMultimediaKit::Publisher, L"WM/Publisher" },
       
    79     { QtMultimediaKit::Copyright, L"Copyright" },
       
    80     { QtMultimediaKit::ParentalRating, L"ParentalRating" },
       
    81     { QtMultimediaKit::RatingOrganisation, L"RatingOrganisation" },
       
    82 
       
    83     // Media
       
    84     { QtMultimediaKit::Size, L"FileSize" },
       
    85     { QtMultimediaKit::MediaType, L"MediaType" },
       
    86     { QtMultimediaKit::Duration, L"Duration" },
       
    87 
       
    88     // Audio
       
    89     { QtMultimediaKit::AudioBitRate, L"AudioBitrate" },
       
    90     { QtMultimediaKit::AudioCodec, L"AudioCodec" },
       
    91     { QtMultimediaKit::ChannelCount, L"Channels" },
       
    92     { QtMultimediaKit::SampleRate, L"Frequency" },
       
    93 
       
    94     // Music
       
    95     { QtMultimediaKit::AlbumTitle, L"WM/AlbumTitle" },
       
    96     { QtMultimediaKit::AlbumArtist, L"WM/AlbumArtist" },
       
    97     { QtMultimediaKit::ContributingArtist, L"Author" },
       
    98     { QtMultimediaKit::Composer, L"WM/Composer" },
       
    99     { QtMultimediaKit::Conductor, L"WM/Conductor" },
       
   100     { QtMultimediaKit::Lyrics, L"WM/Lyrics" },
       
   101     { QtMultimediaKit::Mood, L"WM/Mood" },
       
   102     { QtMultimediaKit::TrackNumber, L"WM/TrackNumber" },
       
   103     //{ QtMultimediaKit::TrackCount, 0 },
       
   104     //{ QtMultimediaKit::CoverArtUrlSmall, 0 },
       
   105     //{ QtMultimediaKit::CoverArtUrlLarge, 0 },
       
   106 
       
   107     // Image/Video
       
   108     //{ QtMultimediaKit::Resolution, 0 },
       
   109     //{ QtMultimediaKit::PixelAspectRatio, 0 },
       
   110 
       
   111     // Video
       
   112     //{ QtMultimediaKit::FrameRate, 0 },
       
   113     { QtMultimediaKit::VideoBitRate, L"VideoBitRate" },
       
   114     { QtMultimediaKit::VideoCodec, L"VideoCodec" },
       
   115 
       
   116     //{ QtMultimediaKit::PosterUrl, 0 },
       
   117 
       
   118     // Movie
       
   119     { QtMultimediaKit::ChapterNumber, L"ChapterNumber" },
       
   120     { QtMultimediaKit::Director, L"WM/Director" },
       
   121     { QtMultimediaKit::LeadPerformer, L"LeadPerformer" },
       
   122     { QtMultimediaKit::Writer, L"WM/Writer" },
       
   123 
       
   124     // Photos
       
   125     { QtMultimediaKit::CameraManufacturer, L"CameraManufacturer" },
       
   126     { QtMultimediaKit::CameraModel, L"CameraModel" },
       
   127     { QtMultimediaKit::Event, L"Event" },
       
   128     { QtMultimediaKit::Subject, L"Subject" }
       
   129 };
       
   130 
       
   131 QWmpMetaData::QWmpMetaData(IWMPCore3 *player, QWmpEvents *events, QObject *parent)
       
   132     : QMetaDataReaderControl(parent)
       
   133     , m_media(0)
       
   134 {
       
   135     player->get_currentMedia(&m_media);
       
   136 
       
   137     connect(events, SIGNAL(CurrentItemChange(IDispatch*)),
       
   138             this, SLOT(currentItemChangeEvent(IDispatch*)));
       
   139     connect(events, SIGNAL(MediaChange(IDispatch*)), this, SLOT(mediaChangeEvent(IDispatch*)));
       
   140 }
       
   141 
       
   142 QWmpMetaData::~QWmpMetaData()
       
   143 {
       
   144     if (m_media)
       
   145         m_media->Release();
       
   146 }
       
   147 
       
   148 bool QWmpMetaData::isMetaDataAvailable() const
       
   149 {
       
   150     return m_media != 0;
       
   151 }
       
   152 
       
   153 bool QWmpMetaData::isWritable() const
       
   154 {
       
   155     return m_media != 0;
       
   156 }
       
   157 
       
   158 QVariant QWmpMetaData::metaData(QtMultimediaKit::MetaData key) const
       
   159 {
       
   160     static const int  count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup);
       
   161 
       
   162     switch (key) {
       
   163     case QtMultimediaKit::Date:
       
   164         {
       
   165             QVariant day = value(m_media, QAutoBStr(L"ReleaseDateDay"));
       
   166             QVariant month = value(m_media, QAutoBStr(L"ReleaseDateMonth"));
       
   167             QVariant year = value(m_media, QAutoBStr(L"ReleaseDateYear"));
       
   168 
       
   169             if (!day.isNull() && !month.isNull() && !year.isNull())
       
   170                 return QDate(year.toInt(), month.toInt(), day.toInt());
       
   171         }
       
   172         break;
       
   173     case QtMultimediaKit::CoverArtUrlSmall:
       
   174         return albumArtUrl(m_media, "_Small.jpg");
       
   175     case QtMultimediaKit::CoverArtUrlLarge:
       
   176         return albumArtUrl(m_media, "_Large.jpg");
       
   177     case QtMultimediaKit::Resolution:
       
   178         {
       
   179             QVariant width = value(m_media, QAutoBStr(L"WM/VideoWidth"));
       
   180             QVariant height = value(m_media, QAutoBStr(L"WM/VideoHeight"));
       
   181 
       
   182             if (!width.isNull() && !height.isNull())
       
   183                 return QSize(width.toInt(), height.toInt());
       
   184         }
       
   185         break;
       
   186     case QtMultimediaKit::PixelAspectRatio:
       
   187         {
       
   188             QVariant x = value(m_media, QAutoBStr(L"PixelAspectRatioX"));
       
   189             QVariant y = value(m_media, QAutoBStr(L"PixelAspectRatioY"));
       
   190 
       
   191             if (!x.isNull() && !y.isNull())
       
   192                 return QSize(x.toInt(), y.toInt());
       
   193         }
       
   194         break;
       
   195     case QtMultimediaKit::VideoFrameRate:
       
   196         break;
       
   197     default:
       
   198         for (int i = 0; i < count; ++i) {
       
   199             if (qt_wmpMetaDataKeys[i].key == key)
       
   200                 return value(m_media, QAutoBStr(qt_wmpMetaDataKeys[i].token));
       
   201         }
       
   202         break;
       
   203     }
       
   204     return QVariant();
       
   205 }
       
   206 
       
   207 QList<QtMultimediaKit::MetaData> QWmpMetaData::availableMetaData() const
       
   208 {
       
   209     QList<QtMultimediaKit::MetaData> keys;
       
   210 
       
   211     if (m_media) {
       
   212         // WMP will return a list of all possible keys so there's no point in filtering the keys
       
   213         // in the lookup table.
       
   214         static const int  count = sizeof(qt_wmpMetaDataKeys) / sizeof(QWmpMetaDataKeyLookup);
       
   215         for (int i = 0; i < count; ++i)
       
   216             keys.append(qt_wmpMetaDataKeys[i].key);
       
   217 
       
   218         BSTR string = 0;
       
   219         if (m_media->get_sourceURL(&string) == S_OK) {
       
   220             QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
       
   221             ::SysFreeString(string);
       
   222 
       
   223             if (m_media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) {
       
   224                 QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string));
       
   225                 ::SysFreeString(string);
       
   226 
       
   227                 QString albumArtLarge = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Large.jpg");
       
   228                 QString albumArtSmall = QLatin1String("AlbumArt_") + uuid + QLatin1String("_Small.jpg");
       
   229 
       
   230                 QDir dir = QFileInfo(url).absoluteDir();
       
   231 
       
   232                 if (dir.exists(albumArtLarge))
       
   233                     keys.append(QtMultimediaKit::CoverArtUrlLarge);
       
   234                 if (dir.exists(albumArtSmall))
       
   235                     keys.append(QtMultimediaKit::CoverArtUrlSmall);
       
   236             }
       
   237         }
       
   238     }
       
   239     return keys;
       
   240 }
       
   241 
       
   242 QVariant QWmpMetaData::extendedMetaData(const QString &key) const
       
   243 {
       
   244     return value(m_media, QAutoBStr(key));
       
   245 }
       
   246 
       
   247 QStringList QWmpMetaData::availableExtendedMetaData() const
       
   248 {
       
   249     return keys(m_media);
       
   250 }
       
   251 
       
   252 void QWmpMetaData::currentItemChangeEvent(IDispatch *dispatch)
       
   253 {
       
   254     IWMPMedia *media = m_media;
       
   255 
       
   256     m_media = 0;
       
   257     if (dispatch)
       
   258         dispatch->QueryInterface(__uuidof(IWMPMedia), reinterpret_cast<void **>(&m_media));
       
   259 
       
   260     if (media) {
       
   261         if (m_media)
       
   262             emit metaDataChanged();
       
   263         else
       
   264             emit metaDataAvailableChanged(false);
       
   265 
       
   266         media->Release();
       
   267     } else {
       
   268         if (m_media)
       
   269             emit metaDataAvailableChanged(false);
       
   270     }
       
   271 }
       
   272 
       
   273 void QWmpMetaData::mediaChangeEvent(IDispatch *dispatch)
       
   274 {
       
   275     IWMPMedia *media = 0;
       
   276     if (dispatch &&  dispatch->QueryInterface(
       
   277             __uuidof(IWMPMedia), reinterpret_cast<void **>(&media)) == S_OK) {
       
   278         VARIANT_BOOL isEqual = VARIANT_FALSE;
       
   279         if (media->get_isIdentical(m_media, &isEqual) == S_OK && isEqual)
       
   280             emit metaDataChanged();
       
   281         media->Release();
       
   282     }
       
   283 }
       
   284 
       
   285 
       
   286 QStringList QWmpMetaData::keys(IWMPMedia *media)
       
   287 {
       
   288     QStringList keys;
       
   289 
       
   290     long count = 0;
       
   291     if (media && media->get_attributeCount(&count) == S_OK) {
       
   292         for (long i = 0; i < count; ++i) {
       
   293             BSTR string;
       
   294             if (media->getAttributeName(i, &string) == S_OK) {
       
   295                 keys.append(QString::fromWCharArray(string, ::SysStringLen(string)));
       
   296 
       
   297                 ::SysFreeString(string);
       
   298             }
       
   299         }
       
   300     }
       
   301     return keys;
       
   302 }
       
   303 
       
   304 QVariant QWmpMetaData::value(IWMPMedia *media, BSTR key)
       
   305 {
       
   306     QVariantList values;
       
   307     IWMPMedia3 *media3 = 0;
       
   308     if (media && media->QueryInterface(
       
   309             __uuidof(IWMPMedia3), reinterpret_cast<void **>(&media3)) == S_OK) {
       
   310         long count = 0;
       
   311         media3->getAttributeCountByType(key, 0, &count);
       
   312 
       
   313         // The count appears to only be valid for static properties, dynamic properties like
       
   314         // PlaylistIndex will have a count of zero but return a value for index 0.
       
   315         if (count == 0)
       
   316             count = 1;
       
   317 
       
   318         for (long i = 0; i < count; ++i) {
       
   319             VARIANT var;
       
   320             VariantInit(&var);
       
   321 
       
   322             if (media3->getItemInfoByType(key, 0, i, &var) == S_OK) {
       
   323                 QVariant value = convertVariant(var);
       
   324 
       
   325                 if (!value.isNull())
       
   326                     values.append(value);
       
   327 
       
   328                 VariantClear(&var);
       
   329             }
       
   330         }
       
   331         media3->Release();
       
   332     }
       
   333 
       
   334     switch (values.count()) {
       
   335     case 0:
       
   336         return QVariant();
       
   337     case 1:
       
   338         return values.first();
       
   339     default:
       
   340         return values;
       
   341     }
       
   342 }
       
   343 
       
   344 QMediaContent QWmpMetaData::resources(IWMPMedia *media)
       
   345 {
       
   346     QMediaContent content;
       
   347 
       
   348     BSTR string = 0;
       
   349     if (media->get_sourceURL(&string) == S_OK) {
       
   350         QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
       
   351         ::SysFreeString(string);
       
   352 
       
   353         content = QMediaContent(QUrl(url));
       
   354     }
       
   355 
       
   356     return content;
       
   357 }
       
   358 
       
   359 QVariant QWmpMetaData::convertVariant(const VARIANT &variant)
       
   360 {
       
   361     switch (variant.vt) {
       
   362     case VT_I2:
       
   363         return variant.iVal;
       
   364     case VT_I4:
       
   365         return variant.lVal;
       
   366     case VT_I8:
       
   367         return variant.llVal;
       
   368     case VT_UI2:
       
   369         return variant.uiVal;
       
   370     case VT_UI4:
       
   371         return quint32(variant.ulVal);
       
   372     case VT_UI8:
       
   373         return variant.ullVal;
       
   374     case VT_INT:
       
   375         return variant.intVal;
       
   376     case VT_UINT:
       
   377         return variant.uintVal;
       
   378     case VT_BSTR:
       
   379         return QString::fromWCharArray(variant.bstrVal, ::SysStringLen(variant.bstrVal));
       
   380     case VT_DISPATCH:
       
   381         {
       
   382             IWMPMetadataPicture *picture = 0;
       
   383             IWMPMetadataText *text = 0;
       
   384 
       
   385             if (variant.pdispVal->QueryInterface(
       
   386                     __uuidof(IWMPMetadataPicture), reinterpret_cast<void **>(&picture)) == S_OK) {
       
   387                 QUrl url;
       
   388                 BSTR string;
       
   389                 if (picture->get_URL(&string) == S_OK) {
       
   390                     url = QUrl(QString::fromWCharArray(string, ::SysStringLen(string)));
       
   391 
       
   392                     ::SysFreeString(string);
       
   393                 }
       
   394                 picture->Release();
       
   395                 return qVariantFromValue(url);
       
   396             } else if (variant.pdispVal->QueryInterface(
       
   397                     __uuidof(IWMPMetadataText), reinterpret_cast<void **>(&text)) == S_OK) {
       
   398                 QString description;
       
   399                 BSTR string;
       
   400                 if (text->get_description(&string) == S_OK) {
       
   401                     description = QString::fromWCharArray(string, SysStringLen(string));
       
   402 
       
   403                     ::SysFreeString(string);
       
   404                 }
       
   405                 text->Release();
       
   406                 return description;
       
   407             } else {
       
   408                 qWarning("Unknown dispatch type");
       
   409             }
       
   410         }
       
   411         break;
       
   412     default:
       
   413         qWarning("Unsupported Type %d %x", variant.vt, variant.vt);
       
   414         break;
       
   415     }
       
   416 
       
   417     return QVariant();
       
   418 }
       
   419 
       
   420 QVariant QWmpMetaData::albumArtUrl(IWMPMedia *media, const char *suffix)
       
   421 {
       
   422     BSTR string = 0;
       
   423     if (media && media->get_sourceURL(&string) == S_OK) {
       
   424         QString url = QString::fromWCharArray(static_cast<const wchar_t *>(string));
       
   425         ::SysFreeString(string);
       
   426 
       
   427         if (media->getItemInfo(QAutoBStr(L"WM/WMCollectionGroupID"), &string) == S_OK) {
       
   428             QString uuid = QString::fromWCharArray(static_cast<const wchar_t *>(string));
       
   429             ::SysFreeString(string);
       
   430 
       
   431             QString fileName = QLatin1String("AlbumArt_") + uuid + QLatin1String(suffix);
       
   432 
       
   433             QDir dir = QFileInfo(url).absoluteDir();
       
   434 
       
   435             if (dir.exists(fileName)) {
       
   436                 return qVariantFromValue(
       
   437                         QUrl(QLatin1String("file:///") + dir.absoluteFilePath(fileName)));
       
   438             }
       
   439         }
       
   440     }
       
   441     return QVariant();
       
   442 }