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