1 /**************************************************************************
2 copyright : (C) 2005-2007 by Lukáš Lalinský
3 email : lalinsky@gmail.com
4 **************************************************************************/
5
6 /***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
10 * *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 USA *
20 * *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
25
26 #include <taglib.h>
27 #include <tdebug.h>
28 #include <trefcounter.h>
29
30 #include "asfattribute.h"
31 #include "asffile.h"
32 #include "asfutils.h"
33
34 using namespace TagLib;
35
36 class ASF::Attribute::AttributePrivate : public RefCounter
37 {
38 public:
AttributePrivate()39 AttributePrivate() :
40 pictureValue(ASF::Picture::fromInvalid()),
41 numericValue(0),
42 stream(0),
43 language(0) {}
44 AttributeTypes type;
45 String stringValue;
46 ByteVector byteVectorValue;
47 ASF::Picture pictureValue;
48 unsigned long long numericValue;
49 int stream;
50 int language;
51 };
52
53 ////////////////////////////////////////////////////////////////////////////////
54 // public members
55 ////////////////////////////////////////////////////////////////////////////////
56
Attribute()57 ASF::Attribute::Attribute() :
58 d(new AttributePrivate())
59 {
60 d->type = UnicodeType;
61 }
62
Attribute(const ASF::Attribute & other)63 ASF::Attribute::Attribute(const ASF::Attribute &other) :
64 d(other.d)
65 {
66 d->ref();
67 }
68
Attribute(const String & value)69 ASF::Attribute::Attribute(const String &value) :
70 d(new AttributePrivate())
71 {
72 d->type = UnicodeType;
73 d->stringValue = value;
74 }
75
Attribute(const ByteVector & value)76 ASF::Attribute::Attribute(const ByteVector &value) :
77 d(new AttributePrivate())
78 {
79 d->type = BytesType;
80 d->byteVectorValue = value;
81 }
82
Attribute(const ASF::Picture & value)83 ASF::Attribute::Attribute(const ASF::Picture &value) :
84 d(new AttributePrivate())
85 {
86 d->type = BytesType;
87 d->pictureValue = value;
88 }
89
Attribute(unsigned int value)90 ASF::Attribute::Attribute(unsigned int value) :
91 d(new AttributePrivate())
92 {
93 d->type = DWordType;
94 d->numericValue = value;
95 }
96
Attribute(unsigned long long value)97 ASF::Attribute::Attribute(unsigned long long value) :
98 d(new AttributePrivate())
99 {
100 d->type = QWordType;
101 d->numericValue = value;
102 }
103
Attribute(unsigned short value)104 ASF::Attribute::Attribute(unsigned short value) :
105 d(new AttributePrivate())
106 {
107 d->type = WordType;
108 d->numericValue = value;
109 }
110
Attribute(bool value)111 ASF::Attribute::Attribute(bool value) :
112 d(new AttributePrivate())
113 {
114 d->type = BoolType;
115 d->numericValue = value;
116 }
117
operator =(const ASF::Attribute & other)118 ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
119 {
120 Attribute(other).swap(*this);
121 return *this;
122 }
123
swap(Attribute & other)124 void ASF::Attribute::swap(Attribute &other)
125 {
126 using std::swap;
127
128 swap(d, other.d);
129 }
130
~Attribute()131 ASF::Attribute::~Attribute()
132 {
133 if(d->deref())
134 delete d;
135 }
136
type() const137 ASF::Attribute::AttributeTypes ASF::Attribute::type() const
138 {
139 return d->type;
140 }
141
toString() const142 String ASF::Attribute::toString() const
143 {
144 return d->stringValue;
145 }
146
toByteVector() const147 ByteVector ASF::Attribute::toByteVector() const
148 {
149 if(d->pictureValue.isValid())
150 return d->pictureValue.render();
151 return d->byteVectorValue;
152 }
153
toBool() const154 unsigned short ASF::Attribute::toBool() const
155 {
156 return d->numericValue ? 1 : 0;
157 }
158
toUShort() const159 unsigned short ASF::Attribute::toUShort() const
160 {
161 return static_cast<unsigned short>(d->numericValue);
162 }
163
toUInt() const164 unsigned int ASF::Attribute::toUInt() const
165 {
166 return static_cast<unsigned int>(d->numericValue);
167 }
168
toULongLong() const169 unsigned long long ASF::Attribute::toULongLong() const
170 {
171 return static_cast<unsigned long long>(d->numericValue);
172 }
173
toPicture() const174 ASF::Picture ASF::Attribute::toPicture() const
175 {
176 return d->pictureValue;
177 }
178
parse(ASF::File & f,int kind)179 String ASF::Attribute::parse(ASF::File &f, int kind)
180 {
181 unsigned int size, nameLength;
182 String name;
183 d->pictureValue = Picture::fromInvalid();
184 // extended content descriptor
185 if(kind == 0) {
186 nameLength = readWORD(&f);
187 name = readString(&f, nameLength);
188 d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
189 size = readWORD(&f);
190 }
191 // metadata & metadata library
192 else {
193 int temp = readWORD(&f);
194 // metadata library
195 if(kind == 2) {
196 d->language = temp;
197 }
198 d->stream = readWORD(&f);
199 nameLength = readWORD(&f);
200 d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
201 size = readDWORD(&f);
202 name = readString(&f, nameLength);
203 }
204
205 if(kind != 2 && size > 65535) {
206 debug("ASF::Attribute::parse() -- Value larger than 64kB");
207 }
208
209 switch(d->type) {
210 case WordType:
211 d->numericValue = readWORD(&f);
212 break;
213
214 case BoolType:
215 if(kind == 0) {
216 d->numericValue = (readDWORD(&f) != 0);
217 }
218 else {
219 d->numericValue = (readWORD(&f) != 0);
220 }
221 break;
222
223 case DWordType:
224 d->numericValue = readDWORD(&f);
225 break;
226
227 case QWordType:
228 d->numericValue = readQWORD(&f);
229 break;
230
231 case UnicodeType:
232 d->stringValue = readString(&f, size);
233 break;
234
235 case BytesType:
236 case GuidType:
237 d->byteVectorValue = f.readBlock(size);
238 break;
239 }
240
241 if(d->type == BytesType && name == "WM/Picture") {
242 d->pictureValue.parse(d->byteVectorValue);
243 if(d->pictureValue.isValid()) {
244 d->byteVectorValue.clear();
245 }
246 }
247
248 return name;
249 }
250
dataSize() const251 int ASF::Attribute::dataSize() const
252 {
253 switch (d->type) {
254 case WordType:
255 return 2;
256 case BoolType:
257 return 4;
258 case DWordType:
259 return 4;
260 case QWordType:
261 return 5;
262 case UnicodeType:
263 return d->stringValue.size() * 2 + 2;
264 case BytesType:
265 if(d->pictureValue.isValid())
266 return d->pictureValue.dataSize();
267 case GuidType:
268 return d->byteVectorValue.size();
269 }
270 return 0;
271 }
272
render(const String & name,int kind) const273 ByteVector ASF::Attribute::render(const String &name, int kind) const
274 {
275 ByteVector data;
276
277 switch (d->type) {
278 case WordType:
279 data.append(ByteVector::fromShort(toUShort(), false));
280 break;
281
282 case BoolType:
283 if(kind == 0) {
284 data.append(ByteVector::fromUInt(toBool(), false));
285 }
286 else {
287 data.append(ByteVector::fromShort(toBool(), false));
288 }
289 break;
290
291 case DWordType:
292 data.append(ByteVector::fromUInt(toUInt(), false));
293 break;
294
295 case QWordType:
296 data.append(ByteVector::fromLongLong(toULongLong(), false));
297 break;
298
299 case UnicodeType:
300 data.append(renderString(d->stringValue));
301 break;
302
303 case BytesType:
304 if(d->pictureValue.isValid()) {
305 data.append(d->pictureValue.render());
306 break;
307 }
308 case GuidType:
309 data.append(d->byteVectorValue);
310 break;
311 }
312
313 if(kind == 0) {
314 data = renderString(name, true) +
315 ByteVector::fromShort((int)d->type, false) +
316 ByteVector::fromShort(data.size(), false) +
317 data;
318 }
319 else {
320 ByteVector nameData = renderString(name);
321 data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
322 ByteVector::fromShort(d->stream, false) +
323 ByteVector::fromShort(nameData.size(), false) +
324 ByteVector::fromShort((int)d->type, false) +
325 ByteVector::fromUInt(data.size(), false) +
326 nameData +
327 data;
328 }
329
330 return data;
331 }
332
language() const333 int ASF::Attribute::language() const
334 {
335 return d->language;
336 }
337
setLanguage(int value)338 void ASF::Attribute::setLanguage(int value)
339 {
340 d->language = value;
341 }
342
stream() const343 int ASF::Attribute::stream() const
344 {
345 return d->stream;
346 }
347
setStream(int value)348 void ASF::Attribute::setStream(int value)
349 {
350 d->stream = value;
351 }
352