1
/*  This file is part of the KDE project.
2
3
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4
5
    This library is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU Lesser General Public License as published by
7
    the Free Software Foundation, either version 2.1 or 3 of the License.
8
9
    This library is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU Lesser General Public License for more details.
13
14
    You should have received a copy of the GNU Lesser General Public License
15
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
18
#import <QTKit/QTMovie.h>
19
20
#include "quicktimemetadata.h"
21
#include "quicktimevideoplayer.h"
22
23
QT_BEGIN_NAMESPACE
24
25
namespace Phonon
26
{
27
namespace QT7
28
{
29
30
QuickTimeMetaData::QuickTimeMetaData()
31
{
32
    m_videoPlayer = 0;
33
    m_movieChanged = false;
34
}
35
36
QuickTimeMetaData::~QuickTimeMetaData()
37
{
38
}
39
40
void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
41
{
42
    m_videoPlayer = videoPlayer;
43
    m_movieChanged = true;
44
    m_metaData.clear();
45
}
46
47
#ifdef QUICKTIME_C_API_AVAILABLE
48
49
QString QuickTimeMetaData::stripCopyRightSymbol(const QString &key)
50
{
51
    return key.right(key.length()-1);
52
}
53
54
QString QuickTimeMetaData::convertQuickTimeKeyToUserKey(const QString &key)
55
{
56
    if (key == QLatin1String("com.apple.quicktime.displayname"))
57
        return QLatin1String("nam");
58
    else if (key == QLatin1String("com.apple.quicktime.album"))
59
        return QLatin1String("alb");
60
    else if (key == QLatin1String("com.apple.quicktime.artist"))
61
        return QLatin1String("ART");
62
    else
63
        return QLatin1String("???");
64
}
65
66
OSStatus QuickTimeMetaData::readMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, QTPropertyClass propClass,
67
    QTPropertyID id, QTPropertyValuePtr *value, ByteCount *size)
68
{
69
	QTPropertyValueType type;
70
	ByteCount propSize;
71
	UInt32 propFlags;
72
	OSStatus err = QTMetaDataGetItemPropertyInfo(metaDataRef, item, propClass, id, &type, &propSize, &propFlags);
73
    BACKEND_ASSERT3(err == noErr, "Could not read meta data value size", NORMAL_ERROR, err)
74
75
    *value = malloc(propSize);
76
77
	err = QTMetaDataGetItemProperty(metaDataRef, item, propClass, id, propSize, *value, size);
78
    BACKEND_ASSERT3(err == noErr, "Could not read meta data value", NORMAL_ERROR, err)
79
80
    if (type == 'code' || type == 'itsk' || type == 'itlk') {
81
        // convert from native endian to big endian
82
    	OSTypePtr pType = (OSTypePtr)*value;
83
    	*pType = EndianU32_NtoB(*pType);
84
    }
85
86
	return err;
87
}
88
89
UInt32 QuickTimeMetaData::getMetaType(QTMetaDataRef metaDataRef, QTMetaDataItem item)
90
{
91
	QTPropertyValuePtr value = 0;
92
	ByteCount ignore = 0;
93
	OSStatus err = readMetaValue(
94
	    metaDataRef, item, kPropertyClass_MetaDataItem, kQTMetaDataItemPropertyID_DataType, &value, &ignore);
95
    BACKEND_ASSERT3(err == noErr, "Could not read meta data type", NORMAL_ERROR, 0)
96
    UInt32 type = *((UInt32 *) value);
97
    if (value)
98
	    free(value);
99
	return type;
100
}
101
102
QString QuickTimeMetaData::getMetaValue(QTMetaDataRef metaDataRef, QTMetaDataItem item, SInt32 id)
103
{
104
	QTPropertyValuePtr value = 0;
105
	ByteCount size = 0;
106
	OSStatus err = readMetaValue(metaDataRef, item, kPropertyClass_MetaDataItem, id, &value, &size);
107
    BACKEND_ASSERT3(err == noErr, "Could not read meta data item", NORMAL_ERROR, QString())
108
    BACKEND_ASSERT3(value != 0, "Could not read meta data item", NORMAL_ERROR, QString())
109
110
    QString string;
111
    UInt32 dataType = getMetaType(metaDataRef, item);
112
    switch (dataType){
113
    case kQTMetaDataTypeUTF8:
114
    case kQTMetaDataTypeMacEncodedText:
115
        string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF8, false));
116
        break;
117
    case kQTMetaDataTypeUTF16BE:
118
        string = PhononCFString::toQString(CFStringCreateWithBytes(0, (UInt8*)value, size, kCFStringEncodingUTF16BE, false));
119
        break;
120
    default:
121
        break;
122
    }
123
124
    if (value)
125
	    free(value);
126
    return string;
127
}
128
129
void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType format, QMultiMap<QString, QString> &result)
130
{
131
	QTMetaDataItem item = kQTMetaDataItemUninitialized;
132
    OSStatus err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
133
	while (err == noErr){
134
        QString key = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Key);
135
        if (format == kQTMetaDataStorageFormatQuickTime)
136
            key = convertQuickTimeKeyToUserKey(key);
137
        else
138
            key = stripCopyRightSymbol(key);
139
140
	    if (!result.contains(key)){
141
	        QString val = getMetaValue(metaDataRef, item, kQTMetaDataItemPropertyID_Value);
142
            result.insert(key, val);
143
        }
144
        err = QTMetaDataGetNextItem(metaDataRef, format, item, kQTMetaDataKeyFormatWildcard, 0, 0, &item);
145
	}
146
}
147
148
#endif // QUICKTIME_C_API_AVAILABLE
149
150
void QuickTimeMetaData::readMetaData()
151
{
152
	if (!m_videoPlayer)
153
        return;
154
    QMultiMap<QString, QString> metaMap;
155
    
156
#ifdef QUICKTIME_C_API_AVAILABLE
157
	QTMetaDataRef metaDataRef;        
158
	OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef);
159
    BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR)
160
161
    readFormattedData(metaDataRef, kQTMetaDataStorageFormatUserData, metaMap);
162
    readFormattedData(metaDataRef, kQTMetaDataStorageFormatQuickTime, metaMap);
163
    readFormattedData(metaDataRef, kQTMetaDataStorageFormatiTunes, metaMap);
164
#else
165
	NSString *name = [m_videoPlayer->qtMovie() attributeForKey:@"QTMovieDisplayNameAttribute"];
166
	metaMap.insert(QLatin1String("nam"), QString::fromUtf8([name UTF8String]));
167
#endif // QUICKTIME_C_API_AVAILABLE
168
169
    m_metaData.insert(QLatin1String("ARTIST"), metaMap.value(QLatin1String("ART")));
170
    m_metaData.insert(QLatin1String("ALBUM"), metaMap.value(QLatin1String("alb")));
171
    m_metaData.insert(QLatin1String("TITLE"), metaMap.value(QLatin1String("nam")));
172
    m_metaData.insert(QLatin1String("DATE"), metaMap.value(QLatin1String("day")));
173
    m_metaData.insert(QLatin1String("GENRE"), metaMap.value(QLatin1String("gnre")));
174
    m_metaData.insert(QLatin1String("TRACKNUMBER"), metaMap.value(QLatin1String("trk")));
175
    m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des")));
176
}
177
178
QMultiMap<QString, QString> QuickTimeMetaData::metaData()
179
{
180
    if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged)
181
        readMetaData();
182
    return m_metaData;
183
}
184
185
}}
186
187
QT_END_NAMESPACE