~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

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
}