2
* \file attributedata.cpp
3
* String representation of attribute data.
9
* Copyright (C) 2009 Urs Fleisch
11
* This file is part of Kid3.
13
* Kid3 is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 2 of the License, or
16
* (at your option) any later version.
18
* Kid3 is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
23
* You should have received a copy of the GNU General Public License
24
* along with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include "attributedata.h"
29
#include "qtcompatmac.h"
34
* @param name owner of Windows media PRIV frame
36
AttributeData::AttributeData(const QString& name)
38
/** PRIV-owner and type of Windows media PRIV frames */
39
static const struct TypeOfWmPriv {
43
{ "AverageLevel", DWord },
44
{ "PeakValue", DWord },
45
{ "WM/AlbumArtist", Utf16 },
46
{ "WM/AuthorURL", Utf16 },
47
{ "WM/BeatsPerMinute", Utf16 },
48
{ "WM/Composer", Utf16 },
49
{ "WM/Conductor", Utf16 },
50
{ "WM/ContentDistributor", Utf16 },
51
{ "WM/ContentGroupDescription", Utf16 },
52
{ "WM/EncodedBy", Utf16 },
53
{ "WM/EncodingSettings", Utf16 },
54
{ "WM/EncodingTime", Binary },
55
{ "WM/Genre", Utf16 },
56
{ "WM/InitialKey", Utf16 },
57
{ "WM/Language", Utf16 },
58
{ "WM/Lyrics", Utf16 },
59
{ "WM/Lyrics_Synchronised", Binary },
60
{ "WM/MCDI", Binary },
61
{ "WM/MediaClassPrimaryID", Guid },
62
{ "WM/MediaClassSecondaryID", Guid },
64
{ "WM/ParentalRating", Utf16 },
65
{ "WM/PartOfSet", Utf16 },
66
{ "WM/Period", Utf16 },
67
{ "WM/Picture", Binary },
68
{ "WM/Producer", Utf16 },
69
{ "WM/PromotionURL", Utf16 },
70
{ "WM/Provider", Utf16 },
71
{ "WM/Publisher", Utf16 },
72
{ "WM/SubTitle", Utf16 },
73
{ "WM/ToolName", Utf16 },
74
{ "WM/ToolVersion", Utf16 },
75
{ "WM/TrackNumber", Utf16 },
76
{ "WM/UniqueFileIdentifier", Utf16 },
77
{ "WM/UserWebURL", Binary },
78
{ "WM/WMCollectionGroupID", Guid },
79
{ "WM/WMCollectionID", Guid },
80
{ "WM/WMContentID", Guid },
81
{ "WM/Writer", Utf16 }
84
static QMap<QString, int> strNumMap;
85
if (strNumMap.empty()) {
86
// first time initialization
87
for (unsigned i = 0; i < sizeof(typeOfWmPriv) / sizeof(typeOfWmPriv[0]);
89
strNumMap.insert(QString(typeOfWmPriv[i].str), typeOfWmPriv[i].type);
92
QMap<QString, int>::const_iterator it =
94
m_type = (it != strNumMap.end()) ? static_cast<Type>(*it) : Unknown;
98
* Convert attribute data to string.
100
* @param data byte array with data
101
* @param str result string
103
* @return true if ok.
105
bool AttributeData::toString(const QByteArray& data, QString& str)
109
const ushort* unicode = reinterpret_cast<const ushort*>(data.data());
110
int size = data.size() / 2;
111
while (size > 0 && unicode[size - 1] == 0) {
114
#if QT_VERSION >= 0x040000
115
str = QString::fromUtf16(unicode, size);
117
str.setUnicodeCodes(unicode, size);
122
if (data.size() == 16) {
123
#if QT_VERSION >= 0x040000
128
for (int i = 0; i < 16; ++i) {
129
if (i == 4 || i == 6 || i == 8 || i == 10) {
132
unsigned char c = (unsigned char)data[i];
133
unsigned char d = c >> 4;
134
str += d >= 10 ? d - 10 + 'A' : d + '0';
136
str += d >= 10 ? d - 10 + 'A' : d + '0';
142
if (data.size() == 4) {
144
for (int i = 3; i >= 0; --i) {
146
num |= static_cast<unsigned char>(data[i]);
161
* Convert attribute data string to byte array.
163
* @param str string representation of data
164
* @param data result data
166
* @return true if ok.
168
bool AttributeData::toByteArray(const QString& str, QByteArray& data)
172
#if QT_VERSION >= 0x040000
173
const ushort* unicode = str.utf16();
175
const ushort* unicode = str.ucs2();
177
QCM_duplicate(data, reinterpret_cast<const char*>(unicode),
178
(str.length() + 1) * 2);
182
QString hexStr(str.QCM_toUpper());
184
if (hexStr.length() == 32) {
185
unsigned char buf[16];
186
unsigned char* bufPtr = buf;
187
for (int i = 0; i < 32;) {
188
#if QT_VERSION >= 0x040000
189
unsigned char h = (unsigned char)hexStr[i++].toLatin1();
190
unsigned char l = (unsigned char)hexStr[i++].toLatin1();
192
unsigned char h = (unsigned char)hexStr[i++].latin1();
193
unsigned char l = (unsigned char)hexStr[i++].latin1();
195
if (!((h >= '0' && h <= '9') || (h >= 'A' && h <= 'F')) ||
196
!((l >= '0' && l <= '9') || (l >= 'A' && l <= 'F'))) {
199
*bufPtr++ = ((h >= 'A' ? h + 10 - 'A' : h - '0') << 4) |
200
(l >= 'A' ? l + 10 - 'A' : l - '0');
202
QCM_duplicate(data, reinterpret_cast<char*>(buf), 16);
209
ulong num = str.toULong(&ok);
212
for (int i = 0; i < 4; ++i) {
213
data[i] = num & 0xff;
229
* Check if a string represents a hexadecimal number, i.e.
230
* contains only characters 0..9, A..F.
232
* @param str string to check
233
* @param lastAllowedLetter last allowed character (normally 'F')
234
* @param additionalChars additional allowed characters
236
* @return true if string has hex format.
238
bool AttributeData::isHexString(const QString& str, char lastAllowedLetter,
239
const QString additionalChars)
244
for (int i = 0; i < static_cast<int>(str.length()); ++i) {
245
#if QT_VERSION >= 0x040000
246
char c = str[i].toLatin1();
248
char c = str[i].latin1();
250
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= lastAllowedLetter) ||
251
additionalChars.QCM_indexOf(c) != -1)) {