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())