Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / asf / asfattribute.cpp
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
19  *   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 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #ifdef WITH_ASF
31
32 #include <taglib.h>
33 #include <tdebug.h>
34 #include "asfattribute.h"
35 #include "asffile.h"
36
37 using namespace TagLib;
38
39 class ASF::Attribute::AttributePrivate : public RefCounter
40 {
41 public:
42   AttributePrivate()
43     : stream(0),
44       language(0) {}
45   AttributeTypes type;
46   String stringValue;
47   ByteVector byteVectorValue;
48   union {
49     unsigned int intValue;
50     unsigned short shortValue;
51     unsigned long long longLongValue;
52     bool boolValue;
53   };
54   int stream;
55   int language;
56 };
57
58 ////////////////////////////////////////////////////////////////////////////////
59 // public members
60 ////////////////////////////////////////////////////////////////////////////////
61
62 ASF::Attribute::Attribute()
63 {
64   d = new AttributePrivate;
65   d->type = UnicodeType;
66 }
67
68 ASF::Attribute::Attribute(const ASF::Attribute &other)
69   : d(other.d)
70 {
71   d->ref();
72 }
73
74 ASF::Attribute &
75 ASF::Attribute::operator=(const ASF::Attribute &other)
76 {
77   if(d->deref())
78     delete d;
79   d = other.d;
80   d->ref();
81   return *this;
82 }
83
84 ASF::Attribute::~Attribute()
85 {
86   if(d->deref())
87     delete d;
88 }
89
90 ASF::Attribute::Attribute(const String &value)
91 {
92   d = new AttributePrivate;
93   d->type = UnicodeType;
94   d->stringValue = value;
95 }
96
97 ASF::Attribute::Attribute(const ByteVector &value)
98 {
99   d = new AttributePrivate;
100   d->type = BytesType;
101   d->byteVectorValue = value;
102 }
103
104 ASF::Attribute::Attribute(unsigned int value)
105 {
106   d = new AttributePrivate;
107   d->type = DWordType;
108   d->intValue = value;
109 }
110
111 ASF::Attribute::Attribute(unsigned long long value)
112 {
113   d = new AttributePrivate;
114   d->type = QWordType;
115   d->longLongValue = value;
116 }
117
118 ASF::Attribute::Attribute(unsigned short value)
119 {
120   d = new AttributePrivate;
121   d->type = WordType;
122   d->shortValue = value;
123 }
124
125 ASF::Attribute::Attribute(bool value)
126 {
127   d = new AttributePrivate;
128   d->type = BoolType;
129   d->boolValue = value;
130 }
131
132 ASF::Attribute::AttributeTypes
133 ASF::Attribute::type() const
134 {
135   return d->type;
136 }
137
138 String
139 ASF::Attribute::toString() const
140 {
141   return d->stringValue;
142 }
143
144 ByteVector
145 ASF::Attribute::toByteVector() const
146 {
147   return d->byteVectorValue;
148 }
149
150 unsigned short
151 ASF::Attribute::toBool() const
152 {
153   return d->shortValue;
154 }
155
156 unsigned short
157 ASF::Attribute::toUShort() const
158 {
159   return d->shortValue;
160 }
161
162 unsigned int
163 ASF::Attribute::toUInt() const
164 {
165   return d->intValue;
166 }
167
168 unsigned long long
169 ASF::Attribute::toULongLong() const
170 {
171   return d->longLongValue;
172 }
173
174 String
175 ASF::Attribute::parse(ASF::File &f, int kind)
176 {
177   int size, nameLength;
178   String name;
179
180   // extended content descriptor
181   if(kind == 0) {
182     nameLength = f.readWORD();
183     name = f.readString(nameLength);
184     d->type = ASF::Attribute::AttributeTypes(f.readWORD());
185     size = f.readWORD();
186   }
187   // metadata & metadata library
188   else {
189     int temp = f.readWORD();
190     // metadata library
191     if(kind == 2) {
192       d->language = temp;
193     }
194     d->stream = f.readWORD();
195     nameLength = f.readWORD();
196     d->type = ASF::Attribute::AttributeTypes(f.readWORD());
197     size = f.readDWORD();
198     name = f.readString(nameLength);
199   }
200
201   if(kind != 2 && size > 65535) {
202     debug("ASF::Attribute::parse() -- Value larger than 64kB");
203   }
204
205   switch(d->type) {
206   case WordType:
207     d->shortValue = f.readWORD();
208     break;
209
210   case BoolType:
211     if(kind == 0) {
212       d->boolValue = f.readDWORD() == 1;
213     }
214     else {
215       d->boolValue = f.readWORD() == 1;
216     }
217     break;
218
219   case DWordType:
220     d->intValue = f.readDWORD();
221     break;
222
223   case QWordType:
224     d->longLongValue = f.readQWORD();
225     break;
226
227   case UnicodeType:
228     d->stringValue = f.readString(size);
229     break;
230
231   case BytesType:
232   case GuidType:
233     d->byteVectorValue = f.readBlock(size);
234     break;
235   }
236
237   return name;
238 }
239
240 int
241 ASF::Attribute::dataSize() const
242 {
243   switch (d->type) {
244   case WordType:
245     return 2;
246   case BoolType:
247     return 4;
248   case DWordType:
249     return 4;
250   case QWordType:
251     return 5;
252   case UnicodeType:
253     return d->stringValue.size() * 2 + 2;
254   case BytesType:
255   case GuidType:
256     return d->byteVectorValue.size();
257   }
258   return 0;
259 }
260
261 ByteVector
262 ASF::Attribute::render(const String &name, int kind) const
263 {
264   ByteVector data;
265
266   switch (d->type) {
267   case WordType:
268     data.append(ByteVector::fromShort(d->shortValue, false));
269     break;
270
271   case BoolType:
272     if(kind == 0) {
273       data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
274     }
275     else {
276       data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
277     }
278     break;
279
280   case DWordType:
281     data.append(ByteVector::fromUInt(d->intValue, false));
282     break;
283
284   case QWordType:
285     data.append(ByteVector::fromLongLong(d->longLongValue, false));
286     break;
287
288   case UnicodeType:
289     data.append(File::renderString(d->stringValue));
290     break;
291
292   case BytesType:
293   case GuidType:
294     data.append(d->byteVectorValue);
295     break;
296   }
297
298   if(kind == 0) {
299     data = File::renderString(name, true) +
300            ByteVector::fromShort((int)d->type, false) +
301            ByteVector::fromShort(data.size(), false) +
302            data;
303   }
304   else {
305     ByteVector nameData = File::renderString(name);
306     data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
307            ByteVector::fromShort(d->stream, false) +
308            ByteVector::fromShort(nameData.size(), false) +
309            ByteVector::fromShort((int)d->type, false) +
310            ByteVector::fromUInt(data.size(), false) +
311            nameData +
312            data;
313   }
314
315   return data;
316 }
317
318 int
319 ASF::Attribute::language() const
320 {
321   return d->language;
322 }
323
324 void
325 ASF::Attribute::setLanguage(int value)
326 {
327   d->language = value;
328 }
329
330 int
331 ASF::Attribute::stream() const
332 {
333   return d->stream;
334 }
335
336 void
337 ASF::Attribute::setStream(int value)
338 {
339   d->stream = value;
340 }
341
342 #endif