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., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 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 <tagunion.h>
27 #include <tstringlist.h>
28 #include <tpropertymap.h>
29
30 #include "id3v1tag.h"
31 #include "id3v2tag.h"
32 #include "apetag.h"
33 #include "xiphcomment.h"
34 #include "infotag.h"
35
36 using namespace TagLib;
37
38 #define stringUnion(method) \
39 if(tag(0) && !tag(0)->method().isEmpty()) \
40 return tag(0)->method(); \
41 if(tag(1) && !tag(1)->method().isEmpty()) \
42 return tag(1)->method(); \
43 if(tag(2) && !tag(2)->method().isEmpty()) \
44 return tag(2)->method(); \
45 return String(); \
46
47 #define numberUnion(method) \
48 if(tag(0) && tag(0)->method() > 0) \
49 return tag(0)->method(); \
50 if(tag(1) && tag(1)->method() > 0) \
51 return tag(1)->method(); \
52 if(tag(2) && tag(2)->method() > 0) \
53 return tag(2)->method(); \
54 return 0
55
56 #define setUnion(method, value) \
57 if(tag(0)) \
58 tag(0)->set##method(value); \
59 if(tag(1)) \
60 tag(1)->set##method(value); \
61 if(tag(2)) \
62 tag(2)->set##method(value); \
63
64 class TagUnion::TagUnionPrivate
65 {
66 public:
TagUnionPrivate()67 TagUnionPrivate() : tags(3, static_cast<Tag *>(0))
68 {
69
70 }
71
~TagUnionPrivate()72 ~TagUnionPrivate()
73 {
74 delete tags[0];
75 delete tags[1];
76 delete tags[2];
77 }
78
79 std::vector<Tag *> tags;
80 };
81
TagUnion(Tag * first,Tag * second,Tag * third)82 TagUnion::TagUnion(Tag *first, Tag *second, Tag *third) :
83 d(new TagUnionPrivate())
84 {
85 d->tags[0] = first;
86 d->tags[1] = second;
87 d->tags[2] = third;
88 }
89
~TagUnion()90 TagUnion::~TagUnion()
91 {
92 delete d;
93 }
94
operator [](int index) const95 Tag *TagUnion::operator[](int index) const
96 {
97 return tag(index);
98 }
99
tag(int index) const100 Tag *TagUnion::tag(int index) const
101 {
102 return d->tags[index];
103 }
104
set(int index,Tag * tag)105 void TagUnion::set(int index, Tag *tag)
106 {
107 delete d->tags[index];
108 d->tags[index] = tag;
109 }
110
properties() const111 PropertyMap TagUnion::properties() const
112 {
113 // This is an ugly workaround but we can't add a virtual function.
114 // Should be virtual in taglib2.
115
116 for(size_t i = 0; i < 3; ++i) {
117
118 if(d->tags[i] && !d->tags[i]->isEmpty()) {
119
120 if(dynamic_cast<const ID3v1::Tag *>(d->tags[i]))
121 return dynamic_cast<const ID3v1::Tag *>(d->tags[i])->properties();
122
123 else if(dynamic_cast<const ID3v2::Tag *>(d->tags[i]))
124 return dynamic_cast<const ID3v2::Tag *>(d->tags[i])->properties();
125
126 else if(dynamic_cast<const APE::Tag *>(d->tags[i]))
127 return dynamic_cast<const APE::Tag *>(d->tags[i])->properties();
128
129 else if(dynamic_cast<const Ogg::XiphComment *>(d->tags[i]))
130 return dynamic_cast<const Ogg::XiphComment *>(d->tags[i])->properties();
131
132 else if(dynamic_cast<const RIFF::Info::Tag *>(d->tags[i]))
133 return dynamic_cast<const RIFF::Info::Tag *>(d->tags[i])->properties();
134 }
135 }
136
137 return PropertyMap();
138 }
139
removeUnsupportedProperties(const StringList & unsupported)140 void TagUnion::removeUnsupportedProperties(const StringList &unsupported)
141 {
142 // This is an ugly workaround but we can't add a virtual function.
143 // Should be virtual in taglib2.
144
145 for(size_t i = 0; i < 3; ++i) {
146
147 if(d->tags[i]) {
148
149 if(dynamic_cast<ID3v1::Tag *>(d->tags[i]))
150 dynamic_cast<ID3v1::Tag *>(d->tags[i])->removeUnsupportedProperties(unsupported);
151
152 else if(dynamic_cast<ID3v2::Tag *>(d->tags[i]))
153 dynamic_cast<ID3v2::Tag *>(d->tags[i])->removeUnsupportedProperties(unsupported);
154
155 else if(dynamic_cast<APE::Tag *>(d->tags[i]))
156 dynamic_cast<APE::Tag *>(d->tags[i])->removeUnsupportedProperties(unsupported);
157
158 else if(dynamic_cast<Ogg::XiphComment *>(d->tags[i]))
159 dynamic_cast<Ogg::XiphComment *>(d->tags[i])->removeUnsupportedProperties(unsupported);
160
161 else if(dynamic_cast<RIFF::Info::Tag *>(d->tags[i]))
162 dynamic_cast<RIFF::Info::Tag *>(d->tags[i])->removeUnsupportedProperties(unsupported);
163 }
164 }
165 }
166
title() const167 String TagUnion::title() const
168 {
169 stringUnion(title);
170 }
171
artist() const172 String TagUnion::artist() const
173 {
174 stringUnion(artist);
175 }
176
album() const177 String TagUnion::album() const
178 {
179 stringUnion(album);
180 }
181
comment() const182 String TagUnion::comment() const
183 {
184 stringUnion(comment);
185 }
186
genre() const187 String TagUnion::genre() const
188 {
189 stringUnion(genre);
190 }
191
year() const192 unsigned int TagUnion::year() const
193 {
194 numberUnion(year);
195 }
196
track() const197 unsigned int TagUnion::track() const
198 {
199 numberUnion(track);
200 }
201
setTitle(const String & s)202 void TagUnion::setTitle(const String &s)
203 {
204 setUnion(Title, s);
205 }
206
setArtist(const String & s)207 void TagUnion::setArtist(const String &s)
208 {
209 setUnion(Artist, s);
210 }
211
setAlbum(const String & s)212 void TagUnion::setAlbum(const String &s)
213 {
214 setUnion(Album, s);
215 }
216
setComment(const String & s)217 void TagUnion::setComment(const String &s)
218 {
219 setUnion(Comment, s);
220 }
221
setGenre(const String & s)222 void TagUnion::setGenre(const String &s)
223 {
224 setUnion(Genre, s);
225 }
226
setYear(unsigned int i)227 void TagUnion::setYear(unsigned int i)
228 {
229 setUnion(Year, i);
230 }
231
setTrack(unsigned int i)232 void TagUnion::setTrack(unsigned int i)
233 {
234 setUnion(Track, i);
235 }
236
isEmpty() const237 bool TagUnion::isEmpty() const
238 {
239 if(d->tags[0] && !d->tags[0]->isEmpty())
240 return false;
241 if(d->tags[1] && !d->tags[1]->isEmpty())
242 return false;
243 if(d->tags[2] && !d->tags[2]->isEmpty())
244 return false;
245
246 return true;
247 }
248
249