Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / ape / apefooter.cpp
1 /***************************************************************************
2     copyright            : (C) 2004 by Allan Sandfeld Jensen
3                            (C) 2002 - 2008 by Scott Wheeler (id3v2header.cpp)
4     email                : kde@carewolf.org
5  ***************************************************************************/
6
7 /***************************************************************************
8  *   This library is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU Lesser General Public License version   *
10  *   2.1 as published by the Free Software Foundation.                     *
11  *                                                                         *
12  *   This library is distributed in the hope that it will be useful, but   *
13  *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
15  *   Lesser General Public License for more details.                       *
16  *                                                                         *
17  *   You should have received a copy of the GNU Lesser General Public      *
18  *   License along with this library; if not, write to the Free Software   *
19  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
20  *   USA                                                                   *
21  *                                                                         *
22  *   Alternatively, this file is available under the Mozilla Public        *
23  *   License Version 1.1.  You may obtain a copy of the License at         *
24  *   http://www.mozilla.org/MPL/                                           *
25  ***************************************************************************/
26
27 #include <iostream>
28 #include <bitset>
29
30 #include <tstring.h>
31 #include <tdebug.h>
32
33 #include "apefooter.h"
34
35 using namespace TagLib;
36 using namespace APE;
37
38 class Footer::FooterPrivate
39 {
40 public:
41   FooterPrivate() : version(0),
42                     footerPresent(true),
43                     headerPresent(false),
44                     isHeader(false),
45                     itemCount(0),
46                     tagSize(0) {}
47
48   ~FooterPrivate() {}
49
50   uint version;
51
52   bool footerPresent;
53   bool headerPresent;
54
55   bool isHeader;
56
57   uint itemCount;
58   uint tagSize;
59
60   static const uint size = 32;
61 };
62
63 ////////////////////////////////////////////////////////////////////////////////
64 // static members
65 ////////////////////////////////////////////////////////////////////////////////
66
67 TagLib::uint Footer::size()
68 {
69   return FooterPrivate::size;
70 }
71
72 ByteVector Footer::fileIdentifier()
73 {
74   return ByteVector::fromCString("APETAGEX");
75 }
76
77 ////////////////////////////////////////////////////////////////////////////////
78 // public members
79 ////////////////////////////////////////////////////////////////////////////////
80
81 Footer::Footer()
82 {
83   d = new FooterPrivate;
84 }
85
86 Footer::Footer(const ByteVector &data)
87 {
88   d = new FooterPrivate;
89   parse(data);
90 }
91
92 Footer::~Footer()
93 {
94   delete d;
95 }
96
97 TagLib::uint Footer::version() const
98 {
99   return d->version;
100 }
101
102 bool Footer::headerPresent() const
103 {
104   return d->headerPresent;
105 }
106
107 bool Footer::footerPresent() const
108 {
109   return d->footerPresent;
110 }
111
112 bool Footer::isHeader() const
113 {
114   return d->isHeader;
115 }
116
117 void Footer::setHeaderPresent(bool b) const
118 {
119   d->headerPresent = b;
120 }
121
122 TagLib::uint Footer::itemCount() const
123 {
124   return d->itemCount;
125 }
126
127 void Footer::setItemCount(uint s)
128 {
129   d->itemCount = s;
130 }
131
132 TagLib::uint Footer::tagSize() const
133 {
134   return d->tagSize;
135 }
136
137 TagLib::uint Footer::completeTagSize() const
138 {
139   if(d->headerPresent)
140     return d->tagSize + d->size;
141   else
142     return d->tagSize;
143 }
144
145 void Footer::setTagSize(uint s)
146 {
147   d->tagSize = s;
148 }
149
150 void Footer::setData(const ByteVector &data)
151 {
152   parse(data);
153 }
154
155 ByteVector Footer::renderFooter() const
156 {
157     return render(false);
158 }
159
160 ByteVector Footer::renderHeader() const
161 {
162     if (!d->headerPresent) return ByteVector();
163
164     return render(true);
165 }
166
167 ////////////////////////////////////////////////////////////////////////////////
168 // protected members
169 ////////////////////////////////////////////////////////////////////////////////
170
171 void Footer::parse(const ByteVector &data)
172 {
173   if(data.size() < size())
174     return;
175
176   // The first eight bytes, data[0..7], are the File Identifier, "APETAGEX".
177
178   // Read the version number
179
180   d->version = data.mid(8, 4).toUInt(false);
181
182   // Read the tag size
183
184   d->tagSize = data.mid(12, 4).toUInt(false);
185
186   // Read the item count
187
188   d->itemCount = data.mid(16, 4).toUInt(false);
189
190   // Read the flags
191
192   std::bitset<32> flags(data.mid(20, 4).toUInt(false));
193
194   d->headerPresent = flags[31];
195   d->footerPresent = !flags[30];
196   d->isHeader = flags[29];
197
198 }
199
200 ByteVector Footer::render(bool isHeader) const
201 {
202   ByteVector v;
203
204   // add the file identifier -- "APETAGEX"
205
206   v.append(fileIdentifier());
207
208   // add the version number -- we always render a 2.000 tag regardless of what
209   // the tag originally was.
210
211   v.append(ByteVector::fromUInt(2000, false));
212
213   // add the tag size
214
215   v.append(ByteVector::fromUInt(d->tagSize, false));
216
217   // add the item count
218
219   v.append(ByteVector::fromUInt(d->itemCount, false));
220
221   // render and add the flags
222
223   std::bitset<32> flags;
224
225   flags[31] = d->headerPresent;
226   flags[30] = false; // footer is always present
227   flags[29] = isHeader;
228
229   v.append(ByteVector::fromUInt(flags.to_ulong(), false));
230
231   // add the reserved 64bit
232
233   v.append(ByteVector::fromLongLong(0));
234
235   return v;
236 }