/* This file is part of the KDE project.
Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library. If not, see .
*/
#include "quicktimemetadata.h"
#include "quicktimevideoplayer.h"
QT_BEGIN_NAMESPACE
namespace Phonon
{
namespace QT7
{
QuickTimeMetaData::QuickTimeMetaData()
{
m_videoPlayer = 0;
m_movieChanged = false;
}
QuickTimeMetaData::~QuickTimeMetaData()
{
}
void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
{
m_videoPlayer = videoPlayer;
m_movieChanged = true;
m_metaData.clear();
}
#ifdef QUICKTIME_C_API_AVAILABLE
QString QuickTimeMetaData::stripCopyRightSymbol(const QString &key)
{
return key.right(key.length()-1);
}
QString QuickTimeMetaData::convertQuickTimeKeyToUserKey(const QString &key)
{
if (key == QLatin1String("com.apple.quicktime.displayname"))
return QLatin1String("nam");
else if (key == QLatin1String("com.apple.quicktime.album"))
return QLatin1String("alb");
else if (key == QLatin1String("com.apple.quicktime.artist"))
return QLatin1String("ART");
else
return QLatin1String("???");
}
OSStatus QuickTimeMetaData::readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass,
QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size)
{
QTPropertyValueType type;
ByteCount propSize;
UInt32 propFlags;
OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags);
BACKEND_ASSERT3(err == noErr, "Could not read meta data value size", NORMAL_ERROR, err)
*value = malloc(propSize);
err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size);
BACKEND_ASSERT3(err == noErr, "Could not read meta data value", NORMAL_ERROR, err)
if (type == 'code' || type == 'itsk' || type == 'itlk') {
// convert from native endian to big endian
OSTypePtr pType = (OSTypePtr)*value;
*pType = EndianU32_NtoB(*pType);
}
return err;
}
UInt32 QuickTimeMetaData::getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item)
{
QTPropertyValuePtr value = 0;
ByteCount ignore = 0;
OSStatus err = readMetaValue(
metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore);
BACKEND_ASSERT3(err == noErr, "Could not read meta data type", NORMAL_ERROR, 0)
UInt32 type = *((UInt32 *) value);
if (value)
free(value);
return type;
}
QString QuickTimeMetaData::getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id)
{
QTPropertyValuePtr value = 0;
ByteCount size = 0;
OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size);
BACKEND_ASSERT3(err == noErr, "Could not read meta data item", NORMAL_ERROR, QString())
BACKEND_ASSERT3(value != 0, "Could not read meta data item", NORMAL_ERROR, QString())
QString string;
UInt32 dataType = getMetaType(metaDataRef, item);
switch (dataType){
case kQTMetaDataTypeUTF8:
case kQTMetaDataTypeMacEncodedText:
string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false));
break;
case kQTMetaDataTypeUTF16BE:
string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false));
break;
default:
break;
}
if (value)
free(value);
return string;
}
void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap &result)
{
QTMetaDataItem item = kQTMetaDataItemUninitialized;
OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
while (err == noErr){
QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key);
if (format == kQTMetaDataStorageFormatQuickTime)
key = convertQuickTimeKeyToUserKey(key);
else
key = stripCopyRightSymbol(key);
if (!result.contains(key)){
QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value);
result.insert(key, val);
}
err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
}
}
#endif // QUICKTIME_C_API_AVAILABLE
void QuickTimeMetaData::readMetaData()
{
if (!m_videoPlayer)
return;
QMultiMap metaMap;
#ifdef QUICKTIME_C_API_AVAILABLE
QTMetaDataRef metaDataRef;
OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef);
BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR)
readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap);
readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap);
readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap);
#else
NSString *name = [m_videoPlayer->qtMovie() attributeForKey:@"QTMovieDisplayNameAttribute"];
metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String]));
#endif // QUICKTIME_C_API_AVAILABLE
m_metaData.insert(QLatin1String("ARTIST"), metaMap.value(QLatin1String("ART")));
m_metaData.insert(QLatin1String("ALBUM"), metaMap.value(QLatin1String("alb")));
m_metaData.insert(QLatin1String("TITLE"), metaMap.value(QLatin1String("nam")));
m_metaData.insert(QLatin1String("DATE"), metaMap.value(QLatin1String("day")));
m_metaData.insert(QLatin1String("GENRE"), metaMap.value(QLatin1String("gnre")));
m_metaData.insert(QLatin1String("TRACKNUMBER"), metaMap.value(QLatin1String("trk")));
m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des")));
}
QMultiMap QuickTimeMetaData::metaData()
{
if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged)
readMetaData();
return m_metaData;
}
}}
QT_END_NAMESPACE