Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / mpeg / id3v2 / frames / relativevolumeframe.cpp
1 /***************************************************************************
2     copyright            : (C) 2002 - 2008 by Scott Wheeler
3     email                : wheeler@kde.org
4  ***************************************************************************/
5
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.                     *
10  *                                                                         *
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.                       *
15  *                                                                         *
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  *
19  *   USA                                                                   *
20  *                                                                         *
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  ***************************************************************************/
25
26 #include <tdebug.h>
27 #include <tmap.h>
28
29 #include "relativevolumeframe.h"
30
31 using namespace TagLib;
32 using namespace ID3v2;
33
34 static inline int bitsToBytes(int i)
35 {
36   return i % 8 == 0 ? i / 8 : (i - i % 8) / 8 + 1;
37 }
38
39 struct ChannelData
40 {
41   ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
42
43   RelativeVolumeFrame::ChannelType channelType;
44   short volumeAdjustment;
45   RelativeVolumeFrame::PeakVolume peakVolume;
46 };
47
48 class RelativeVolumeFrame::RelativeVolumeFramePrivate
49 {
50 public:
51   String identification;
52   Map<ChannelType, ChannelData> channels;
53 };
54
55 ////////////////////////////////////////////////////////////////////////////////
56 // public members
57 ////////////////////////////////////////////////////////////////////////////////
58
59 RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2")
60 {
61   d = new RelativeVolumeFramePrivate;
62 }
63
64 RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data)
65 {
66   d = new RelativeVolumeFramePrivate;
67   setData(data);
68 }
69
70 RelativeVolumeFrame::~RelativeVolumeFrame()
71 {
72   delete d;
73 }
74
75 String RelativeVolumeFrame::toString() const
76 {
77   return d->identification;
78 }
79
80 List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
81 {
82   List<ChannelType> l;
83
84   Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
85   for(; it != d->channels.end(); ++it)
86     l.append((*it).first);
87
88   return l;
89 }
90
91 // deprecated
92
93 RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const
94 {
95   return MasterVolume;
96 }
97
98 // deprecated
99
100 void RelativeVolumeFrame::setChannelType(ChannelType)
101 {
102
103 }
104
105 short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const
106 {
107   return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0;
108 }
109
110 short RelativeVolumeFrame::volumeAdjustmentIndex() const
111 {
112   return volumeAdjustmentIndex(MasterVolume);
113 }
114
115 void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type)
116 {
117   d->channels[type].volumeAdjustment = index;
118 }
119
120 void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index)
121 {
122   setVolumeAdjustmentIndex(index, MasterVolume);
123 }
124
125 float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const
126 {
127   return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0;
128 }
129
130 float RelativeVolumeFrame::volumeAdjustment() const
131 {
132   return volumeAdjustment(MasterVolume);
133 }
134
135 void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type)
136 {
137   d->channels[type].volumeAdjustment = short(adjustment * float(512));
138 }
139
140 void RelativeVolumeFrame::setVolumeAdjustment(float adjustment)
141 {
142   setVolumeAdjustment(adjustment, MasterVolume);
143 }
144
145 RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const
146 {
147   return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume();
148 }
149
150 RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const
151 {
152   return peakVolume(MasterVolume);
153 }
154
155 void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type)
156 {
157   d->channels[type].peakVolume = peak;
158 }
159
160 void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak)
161 {
162   setPeakVolume(peak, MasterVolume);
163 }
164
165 String RelativeVolumeFrame::identification() const
166 {
167   return d->identification;
168 }
169
170 void RelativeVolumeFrame::setIdentification(const String &s)
171 {
172   d->identification = s;
173 }
174
175 ////////////////////////////////////////////////////////////////////////////////
176 // protected members
177 ////////////////////////////////////////////////////////////////////////////////
178
179 void RelativeVolumeFrame::parseFields(const ByteVector &data)
180 {
181   int pos = 0;
182   d->identification = readStringField(data, String::Latin1, &pos);
183
184   // Each channel is at least 4 bytes.
185
186   while(pos <= (int)data.size() - 4) {
187
188
189     ChannelType type = ChannelType(data[pos]);
190     pos += 1;
191
192     ChannelData &channel = d->channels[type];
193
194     channel.volumeAdjustment = data.mid(pos, 2).toShort();
195     pos += 2;
196
197     channel.peakVolume.bitsRepresentingPeak = data[pos];
198     pos += 1;
199
200     int bytes = bitsToBytes(channel.peakVolume.bitsRepresentingPeak);
201     channel.peakVolume.peakVolume = data.mid(pos, bytes);
202     pos += bytes;
203   }
204 }
205
206 ByteVector RelativeVolumeFrame::renderFields() const
207 {
208   ByteVector data;
209
210   data.append(d->identification.data(String::Latin1));
211   data.append(textDelimiter(String::Latin1));
212
213   Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
214
215   for(; it != d->channels.end(); ++it) {
216     ChannelType type = (*it).first;
217     const ChannelData &channel = (*it).second;
218
219     data.append(char(type));
220     data.append(ByteVector::fromShort(channel.volumeAdjustment));
221     data.append(char(channel.peakVolume.bitsRepresentingPeak));
222     data.append(channel.peakVolume.peakVolume);
223   }
224
225   return data;
226 }
227
228 ////////////////////////////////////////////////////////////////////////////////
229 // private members
230 ////////////////////////////////////////////////////////////////////////////////
231
232 RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h)
233 {
234   d = new RelativeVolumeFramePrivate;
235   parseFields(fieldData(data));
236 }