Added TagLib (with AUTORS and COPYING files)
[someplayer] / src / taglib / fileref.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 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29
30 #include <tfile.h>
31 #include <tstring.h>
32 #include <tdebug.h>
33
34 #include "fileref.h"
35 #include "asffile.h"
36 #include "mpegfile.h"
37 #include "vorbisfile.h"
38 #include "flacfile.h"
39 #include "oggflacfile.h"
40 #include "mpcfile.h"
41 #include "mp4file.h"
42 #include "wavpackfile.h"
43 #include "speexfile.h"
44 #include "trueaudiofile.h"
45 #include "aifffile.h"
46 #include "wavfile.h"
47
48 using namespace TagLib;
49
50 class FileRef::FileRefPrivate : public RefCounter
51 {
52 public:
53   FileRefPrivate(File *f) : RefCounter(), file(f) {}
54   ~FileRefPrivate() {
55     delete file;
56   }
57
58   File *file;
59   static List<const FileTypeResolver *> fileTypeResolvers;
60 };
61
62 List<const FileRef::FileTypeResolver *> FileRef::FileRefPrivate::fileTypeResolvers;
63
64 ////////////////////////////////////////////////////////////////////////////////
65 // public members
66 ////////////////////////////////////////////////////////////////////////////////
67
68 FileRef::FileRef()
69 {
70   d = new FileRefPrivate(0);
71 }
72
73 FileRef::FileRef(FileName fileName, bool readAudioProperties,
74                  AudioProperties::ReadStyle audioPropertiesStyle)
75 {
76   d = new FileRefPrivate(create(fileName, readAudioProperties, audioPropertiesStyle));
77 }
78
79 FileRef::FileRef(File *file)
80 {
81   d = new FileRefPrivate(file);
82 }
83
84 FileRef::FileRef(const FileRef &ref) : d(ref.d)
85 {
86   d->ref();
87 }
88
89 FileRef::~FileRef()
90 {
91   if(d->deref())
92     delete d;
93 }
94
95 Tag *FileRef::tag() const
96 {
97   if(isNull()) {
98     debug("FileRef::tag() - Called without a valid file.");
99     return 0;
100   }
101   return d->file->tag();
102 }
103
104 AudioProperties *FileRef::audioProperties() const
105 {
106   if(isNull()) {
107     debug("FileRef::audioProperties() - Called without a valid file.");
108     return 0;
109   }
110   return d->file->audioProperties();
111 }
112
113 File *FileRef::file() const
114 {
115   return d->file;
116 }
117
118 bool FileRef::save()
119 {
120   if(isNull()) {
121     debug("FileRef::save() - Called without a valid file.");
122     return false;
123   }
124   return d->file->save();
125 }
126
127 const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static
128 {
129   FileRefPrivate::fileTypeResolvers.prepend(resolver);
130   return resolver;
131 }
132
133 StringList FileRef::defaultFileExtensions()
134 {
135   StringList l;
136
137   l.append("ogg");
138   l.append("flac");
139   l.append("oga");
140   l.append("mp3");
141   l.append("mpc");
142   l.append("wv");
143   l.append("spx");
144   l.append("tta");
145 #ifdef TAGLIB_WITH_MP4
146   l.append("m4a");
147   l.append("m4b");
148   l.append("m4p");
149   l.append("3g2");
150   l.append("mp4");
151 #endif
152 #ifdef TAGLIB_WITH_ASF
153   l.append("wma");
154   l.append("asf");
155 #endif
156   l.append("aif");
157   l.append("aiff");
158   l.append("wav");
159
160   return l;
161 }
162
163 bool FileRef::isNull() const
164 {
165   return !d->file || !d->file->isValid();
166 }
167
168 FileRef &FileRef::operator=(const FileRef &ref)
169 {
170   if(&ref == this)
171     return *this;
172
173   if(d->deref())
174     delete d;
175
176   d = ref.d;
177   d->ref();
178
179   return *this;
180 }
181
182 bool FileRef::operator==(const FileRef &ref) const
183 {
184   return ref.d->file == d->file;
185 }
186
187 bool FileRef::operator!=(const FileRef &ref) const
188 {
189   return ref.d->file != d->file;
190 }
191
192 File *FileRef::create(FileName fileName, bool readAudioProperties,
193                       AudioProperties::ReadStyle audioPropertiesStyle) // static
194 {
195
196   List<const FileTypeResolver *>::ConstIterator it = FileRefPrivate::fileTypeResolvers.begin();
197
198   for(; it != FileRefPrivate::fileTypeResolvers.end(); ++it) {
199     File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
200     if(file)
201       return file;
202   }
203
204   // Ok, this is really dumb for now, but it works for testing.
205
206   String s;
207
208 #ifdef _WIN32
209   s = (wcslen((const wchar_t *) fileName) > 0) ? String((const wchar_t *) fileName) : String((const char *) fileName);
210 #else
211   s = fileName;
212 #endif
213
214   // If this list is updated, the method defaultFileExtensions() should also be
215   // updated.  However at some point that list should be created at the same time
216   // that a default file type resolver is created.
217
218   int pos = s.rfind(".");
219   if(pos != -1) {
220     String ext = s.substr(pos + 1).upper();
221     if(ext == "MP3")
222       return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
223     if(ext == "OGG")
224       return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
225     if(ext == "OGA") {
226       /* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
227       File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
228       if (file->isValid())
229         return file;
230       delete file;
231       return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
232     }
233     if(ext == "FLAC")
234       return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
235     if(ext == "MPC")
236       return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
237     if(ext == "WV")
238       return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
239     if(ext == "SPX")
240       return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
241     if(ext == "TTA")
242       return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
243 #ifdef TAGLIB_WITH_MP4
244     if(ext == "M4A" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
245       return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
246 #endif
247 #ifdef TAGLIB_WITH_ASF
248     if(ext == "WMA" || ext == "ASF")
249       return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
250 #endif
251     if(ext == "AIF")
252       return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
253     if(ext == "WAV")
254       return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
255     if(ext == "AIFF")
256       return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
257   }
258
259   return 0;
260 }