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