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