1 /***************************************************************************
2 copyright : (C) 2004 by Allan Sandfeld Jensen
3 email : kde@carewolf.org
4 ***************************************************************************/
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. *
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. *
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 *
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 ***************************************************************************/
26 #include <tbytevector.h>
33 #include "id3v2header.h"
35 #include "apefooter.h"
37 using namespace TagLib;
41 enum { APEIndex, ID3v1Index };
44 class MPC::File::FilePrivate
71 ID3v2::Header *ID3v2Header;
77 Properties *properties;
80 // These indicate whether the file *on disk* has these tags, not if
81 // this data structure does. This is used in computing offsets.
88 ////////////////////////////////////////////////////////////////////////////////
90 ////////////////////////////////////////////////////////////////////////////////
92 MPC::File::File(FileName file, bool readProperties,
93 Properties::ReadStyle propertiesStyle) : TagLib::File(file)
96 read(readProperties, propertiesStyle);
104 TagLib::Tag *MPC::File::tag() const
109 MPC::Properties *MPC::File::audioProperties() const
111 return d->properties;
114 bool MPC::File::save()
117 debug("MPC::File::save() -- File is read only.");
121 // Possibly strip ID3v2 tag
123 if(d->hasID3v2 && !d->ID3v2Header) {
124 removeBlock(d->ID3v2Location, d->ID3v2Size);
127 d->ID3v1Location -= d->ID3v2Size;
129 d->APELocation -= d->ID3v2Size;
136 seek(d->ID3v1Location);
137 writeBlock(ID3v1Tag()->render());
141 d->ID3v1Location = tell();
142 writeBlock(ID3v1Tag()->render());
147 removeBlock(d->ID3v1Location, 128);
150 if(d->APELocation > d->ID3v1Location)
151 d->APELocation -= 128;
159 insert(APETag()->render(), d->APELocation, d->APESize);
162 insert(APETag()->render(), d->ID3v1Location, 0);
163 d->APESize = APETag()->footer()->completeTagSize();
165 d->APELocation = d->ID3v1Location;
166 d->ID3v1Location += d->APESize;
170 d->APELocation = tell();
171 writeBlock(APETag()->render());
172 d->APESize = APETag()->footer()->completeTagSize();
179 removeBlock(d->APELocation, d->APESize);
182 if(d->ID3v1Location > d->APELocation)
183 d->ID3v1Location -= d->APESize;
190 ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
192 return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
195 APE::Tag *MPC::File::APETag(bool create)
197 return d->tag.access<APE::Tag>(APEIndex, create);
200 void MPC::File::strip(int tags)
203 d->tag.set(ID3v1Index, 0);
208 delete d->ID3v2Header;
213 d->tag.set(APEIndex, 0);
220 void MPC::File::remove(int tags)
226 ////////////////////////////////////////////////////////////////////////////////
228 ////////////////////////////////////////////////////////////////////////////////
230 void MPC::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
232 // Look for an ID3v1 tag
234 d->ID3v1Location = findID3v1();
236 if(d->ID3v1Location >= 0) {
237 d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
241 // Look for an APE tag
245 d->APELocation = findAPE();
247 if(d->APELocation >= 0) {
248 d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
250 d->APESize = APETag()->footer()->completeTagSize();
251 d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
258 // Look for and skip an ID3v2 tag
260 d->ID3v2Location = findID3v2();
262 if(d->ID3v2Location >= 0) {
263 seek(d->ID3v2Location);
264 d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
265 d->ID3v2Size = d->ID3v2Header->completeTagSize();
270 seek(d->ID3v2Location + d->ID3v2Size);
274 // Look for MPC metadata
277 d->properties = new Properties(readBlock(MPC::HeaderSize),
278 length() - d->ID3v2Size - d->APESize);
282 long MPC::File::findAPE()
294 if(readBlock(8) == APE::Tag::fileIdentifier())
300 long MPC::File::findID3v1()
308 if(readBlock(3) == ID3v1::Tag::fileIdentifier())
314 long MPC::File::findID3v2()
321 if(readBlock(3) == ID3v2::Header::fileIdentifier())