1 /***************************************************************************
2 copyright : (C) 2006 by Lukáš Lalinský
3 email : lalinsky@gmail.com
5 copyright : (C) 2004 by Allan Sandfeld Jensen
6 email : kde@carewolf.org
7 (original MPC implementation)
8 ***************************************************************************/
10 /***************************************************************************
11 * This library is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU Lesser General Public License version *
13 * 2.1 as published by the Free Software Foundation. *
15 * This library is distributed in the hope that it will be useful, but *
16 * WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
18 * Lesser General Public License for more details. *
20 * You should have received a copy of the GNU Lesser General Public *
21 * License along with this library; if not, write to the Free Software *
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
25 * Alternatively, this file is available under the Mozilla Public *
26 * License Version 1.1. You may obtain a copy of the License at *
27 * http://www.mozilla.org/MPL/ *
28 ***************************************************************************/
30 #include <tbytevector.h>
35 #include "trueaudiofile.h"
38 #include "id3v2header.h"
40 using namespace TagLib;
44 enum { ID3v2Index = 0, ID3v1Index = 1 };
47 class TrueAudio::File::FilePrivate
50 FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
51 ID3v2FrameFactory(frameFactory),
65 const ID3v2::FrameFactory *ID3v2FrameFactory;
67 uint ID3v2OriginalSize;
73 Properties *properties;
76 // These indicate whether the file *on disk* has these tags, not if
77 // this data structure does. This is used in computing offsets.
83 ////////////////////////////////////////////////////////////////////////////////
85 ////////////////////////////////////////////////////////////////////////////////
87 TrueAudio::File::File(FileName file, bool readProperties,
88 Properties::ReadStyle propertiesStyle) : TagLib::File(file)
92 read(readProperties, propertiesStyle);
95 TrueAudio::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
96 bool readProperties, Properties::ReadStyle propertiesStyle) :
99 d = new FilePrivate(frameFactory);
101 read(readProperties, propertiesStyle);
104 TrueAudio::File::~File()
109 TagLib::Tag *TrueAudio::File::tag() const
114 TrueAudio::Properties *TrueAudio::File::audioProperties() const
116 return d->properties;
119 void TrueAudio::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
121 d->ID3v2FrameFactory = factory;
124 bool TrueAudio::File::save()
127 debug("TrueAudio::File::save() -- File is read only.");
133 if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
135 d->ID3v2Location = 0;
136 d->ID3v2OriginalSize = 0;
138 ByteVector data = ID3v2Tag()->render();
139 insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
140 d->ID3v1Location -= d->ID3v2OriginalSize - data.size();
141 d->ID3v2OriginalSize = data.size();
144 else if(d->hasID3v2) {
145 removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
146 d->ID3v1Location -= d->ID3v2OriginalSize;
147 d->ID3v2Location = -1;
148 d->ID3v2OriginalSize = 0;
154 if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
157 d->ID3v1Location = tell();
160 seek(d->ID3v1Location);
161 writeBlock(ID3v1Tag()->render());
164 else if(d->hasID3v1) {
165 removeBlock(d->ID3v1Location, 128);
166 d->ID3v1Location = -1;
173 ID3v1::Tag *TrueAudio::File::ID3v1Tag(bool create)
175 return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
178 ID3v2::Tag *TrueAudio::File::ID3v2Tag(bool create)
180 return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
183 void TrueAudio::File::strip(int tags)
186 d->tag.set(ID3v1Index, 0);
191 d->tag.set(ID3v2Index, 0);
199 ////////////////////////////////////////////////////////////////////////////////
201 ////////////////////////////////////////////////////////////////////////////////
203 void TrueAudio::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
205 // Look for an ID3v2 tag
207 d->ID3v2Location = findID3v2();
209 if(d->ID3v2Location >= 0) {
211 d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
213 d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
215 if(ID3v2Tag()->header()->tagSize() <= 0)
216 d->tag.set(ID3v2Index, 0);
221 // Look for an ID3v1 tag
223 d->ID3v1Location = findID3v1();
225 if(d->ID3v1Location >= 0) {
226 d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
233 // Look for TrueAudio metadata
236 if(d->ID3v2Location >= 0) {
237 seek(d->ID3v2Location + d->ID3v2OriginalSize);
238 d->properties = new Properties(readBlock(TrueAudio::HeaderSize),
239 length() - d->ID3v2OriginalSize);
243 d->properties = new Properties(readBlock(TrueAudio::HeaderSize),
249 long TrueAudio::File::findID3v1()
257 if(readBlock(3) == ID3v1::Tag::fileIdentifier())
263 long TrueAudio::File::findID3v2()
270 if(readBlock(3) == ID3v2::Header::fileIdentifier())