~njh-aelius/maxosx/musicbrainz-tags

« back to all changes in this revision

Viewing changes to Frameworks/taglib/taglib/taglib/wavpack/wavpackfile.cpp

  • Committer: stephen_booth
  • Date: 2008-04-30 01:48:01 UTC
  • Revision ID: svn-v4:6b6cea13-1402-0410-9567-a7afb52bf336:trunk:1371
Fixing the taglib source tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
    copyright            : (C) 2006 by Lukáš Lalinský
3
 
    email                : lalinsky@gmail.com
4
 
 
5
 
    copyright            : (C) 2004 by Allan Sandfeld Jensen
6
 
    email                : kde@carewolf.org
7
 
                           (original MPC implementation)
8
 
 ***************************************************************************/
9
 
 
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.                     *
14
 
 *                                                                         *
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.                       *
19
 
 *                                                                         *
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  *
23
 
 *   USA                                                                   *
24
 
 *                                                                         *
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
 
 ***************************************************************************/
29
 
 
30
 
#include <tbytevector.h>
31
 
#include <tstring.h>
32
 
#include <tdebug.h>
33
 
#include <tagunion.h>
34
 
 
35
 
#include "wavpackfile.h"
36
 
#include "id3v1tag.h"
37
 
#include "id3v2header.h"
38
 
#include "apetag.h"
39
 
#include "apefooter.h"
40
 
 
41
 
using namespace TagLib;
42
 
 
43
 
namespace
44
 
{
45
 
  enum { APEIndex, ID3v1Index };
46
 
}
47
 
 
48
 
class WavPack::File::FilePrivate
49
 
{
50
 
public:
51
 
  FilePrivate() :
52
 
    APELocation(-1),
53
 
    APESize(0),
54
 
    ID3v1Location(-1),
55
 
    properties(0),
56
 
    scanned(false),
57
 
    hasAPE(false),
58
 
    hasID3v1(false) {}
59
 
 
60
 
  ~FilePrivate()
61
 
  {
62
 
    delete properties;
63
 
  }
64
 
 
65
 
  long APELocation;
66
 
  uint APESize;
67
 
 
68
 
  long ID3v1Location;
69
 
 
70
 
  TagUnion tag;
71
 
 
72
 
  Properties *properties;
73
 
  bool scanned;
74
 
 
75
 
  // These indicate whether the file *on disk* has these tags, not if
76
 
  // this data structure does.  This is used in computing offsets.
77
 
 
78
 
  bool hasAPE;
79
 
  bool hasID3v1;
80
 
};
81
 
 
82
 
////////////////////////////////////////////////////////////////////////////////
83
 
// public members
84
 
////////////////////////////////////////////////////////////////////////////////
85
 
 
86
 
WavPack::File::File(FileName file, bool readProperties,
87
 
                Properties::ReadStyle propertiesStyle) : TagLib::File(file)
88
 
{
89
 
  d = new FilePrivate;
90
 
  read(readProperties, propertiesStyle);
91
 
}
92
 
 
93
 
WavPack::File::~File()
94
 
{
95
 
  delete d;
96
 
}
97
 
 
98
 
TagLib::Tag *WavPack::File::tag() const
99
 
{
100
 
  return &d->tag;
101
 
}
102
 
 
103
 
WavPack::Properties *WavPack::File::audioProperties() const
104
 
{
105
 
  return d->properties;
106
 
}
107
 
 
108
 
bool WavPack::File::save()
109
 
{
110
 
  if(readOnly()) {
111
 
    debug("WavPack::File::save() -- File is read only.");
112
 
    return false;
113
 
  }
114
 
 
115
 
  // Update ID3v1 tag
116
 
 
117
 
  if(ID3v1Tag()) {
118
 
    if(d->hasID3v1) {
119
 
      seek(d->ID3v1Location);
120
 
      writeBlock(ID3v1Tag()->render());
121
 
    }
122
 
    else {
123
 
      seek(0, End);
124
 
      d->ID3v1Location = tell();
125
 
      writeBlock(ID3v1Tag()->render());
126
 
      d->hasID3v1 = true;
127
 
    }
128
 
  }
129
 
  else {
130
 
    if(d->hasID3v1) {
131
 
      removeBlock(d->ID3v1Location, 128);
132
 
      d->hasID3v1 = false;
133
 
      if(d->hasAPE) {
134
 
        if(d->APELocation > d->ID3v1Location)
135
 
          d->APELocation -= 128;
136
 
      }
137
 
    }
138
 
  }
139
 
 
140
 
  // Update APE tag
141
 
 
142
 
  if(APETag()) {
143
 
    if(d->hasAPE)
144
 
      insert(APETag()->render(), d->APELocation, d->APESize);
145
 
    else {
146
 
      if(d->hasID3v1)  {
147
 
        insert(APETag()->render(), d->ID3v1Location, 0);
148
 
        d->APESize = APETag()->footer()->completeTagSize();
149
 
        d->hasAPE = true;
150
 
        d->APELocation = d->ID3v1Location;
151
 
        d->ID3v1Location += d->APESize;
152
 
      }
153
 
      else {
154
 
        seek(0, End);
155
 
        d->APELocation = tell();
156
 
        writeBlock(APETag()->render());
157
 
        d->APESize = APETag()->footer()->completeTagSize();
158
 
        d->hasAPE = true;
159
 
      }
160
 
    }
161
 
  }
162
 
  else {
163
 
    if(d->hasAPE) {
164
 
      removeBlock(d->APELocation, d->APESize);
165
 
      d->hasAPE = false;
166
 
      if(d->hasID3v1) {
167
 
        if(d->ID3v1Location > d->APELocation) {
168
 
          d->ID3v1Location -= d->APESize;
169
 
        }
170
 
      }
171
 
    }
172
 
  }
173
 
 
174
 
   return true;
175
 
}
176
 
 
177
 
ID3v1::Tag *WavPack::File::ID3v1Tag(bool create)
178
 
{
179
 
  return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
180
 
}
181
 
 
182
 
APE::Tag *WavPack::File::APETag(bool create)
183
 
{
184
 
  return d->tag.access<APE::Tag>(APEIndex, create);
185
 
}
186
 
 
187
 
void WavPack::File::strip(int tags)
188
 
{
189
 
  if(tags & ID3v1) {
190
 
    d->tag.set(ID3v1Index, 0);
191
 
    APETag(true);
192
 
  }
193
 
 
194
 
  if(tags & APE) {
195
 
    d->tag.set(APEIndex, 0);
196
 
 
197
 
    if(!ID3v1Tag())
198
 
      APETag(true);
199
 
  }
200
 
}
201
 
 
202
 
////////////////////////////////////////////////////////////////////////////////
203
 
// private members
204
 
////////////////////////////////////////////////////////////////////////////////
205
 
 
206
 
void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
207
 
{
208
 
  // Look for an ID3v1 tag
209
 
 
210
 
  d->ID3v1Location = findID3v1();
211
 
 
212
 
  if(d->ID3v1Location >= 0) {
213
 
    d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
214
 
    d->hasID3v1 = true;
215
 
  }
216
 
 
217
 
  // Look for an APE tag
218
 
 
219
 
  d->APELocation = findAPE();
220
 
 
221
 
  if(d->APELocation >= 0) {
222
 
    d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
223
 
    d->APESize = APETag()->footer()->completeTagSize();
224
 
    d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
225
 
    d->hasAPE = true;
226
 
  }
227
 
 
228
 
  if(!d->hasID3v1)
229
 
    APETag(true);
230
 
 
231
 
  // Look for WavPack audio properties
232
 
 
233
 
  if(readProperties) {
234
 
    seek(0);
235
 
    d->properties = new Properties(readBlock(WavPack::HeaderSize),
236
 
                                   length() - d->APESize);
237
 
  }
238
 
}
239
 
 
240
 
long WavPack::File::findAPE()
241
 
{
242
 
  if(!isValid())
243
 
    return -1;
244
 
 
245
 
  if(d->hasID3v1)
246
 
    seek(-160, End);
247
 
  else
248
 
    seek(-32, End);
249
 
 
250
 
  long p = tell();
251
 
 
252
 
  if(readBlock(8) == APE::Tag::fileIdentifier())
253
 
    return p;
254
 
 
255
 
  return -1;
256
 
}
257
 
 
258
 
long WavPack::File::findID3v1()
259
 
{
260
 
  if(!isValid())
261
 
    return -1;
262
 
 
263
 
  seek(-128, End);
264
 
  long p = tell();
265
 
 
266
 
  if(readBlock(3) == ID3v1::Tag::fileIdentifier())
267
 
    return p;
268
 
 
269
 
  return -1;
270
 
}