Add M4A to files pattern
[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   l.append("m4a");
146   l.append("m4b");
147   l.append("m4p");
148   l.append("3g2");
149   l.append("mp4");
150   l.append("wma");
151   l.append("asf");
152   l.append("aif");
153   l.append("aiff");
154   l.append("wav");
155
156   return l;
157 }
158
159 bool FileRef::isNull() const
160 {
161   return !d->file || !d->file->isValid();
162 }
163
164 FileRef &FileRef::operator=(const FileRef &ref)
165 {
166   if(&ref == this)
167     return *this;
168
169   if(d->deref())
170     delete d;
171
172   d = ref.d;
173   d->ref();
174
175   return *this;
176 }
177
178 bool FileRef::operator==(const FileRef &ref) const
179 {
180   return ref.d->file == d->file;
181 }
182
183 bool FileRef::operator!=(const FileRef &ref) const
184 {
185   return ref.d->file != d->file;
186 }
187
188 File *FileRef::create(FileName fileName, bool readAudioProperties,
189                       AudioProperties::ReadStyle audioPropertiesStyle) // static
190 {
191
192   List<const FileTypeResolver *>::ConstIterator it = FileRefPrivate::fileTypeResolvers.begin();
193
194   for(; it != FileRefPrivate::fileTypeResolvers.end(); ++it) {
195     File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
196     if(file)
197       return file;
198   }
199
200   // Ok, this is really dumb for now, but it works for testing.
201
202   String s;
203
204 #ifdef _WIN32
205   s = (wcslen((const wchar_t *) fileName) > 0) ? String((const wchar_t *) fileName) : String((const char *) fileName);
206 #else
207   s = fileName;
208 #endif
209
210   // If this list is updated, the method defaultFileExtensions() should also be
211   // updated.  However at some point that list should be created at the same time
212   // that a default file type resolver is created.
213
214   int pos = s.rfind(".");
215   if(pos != -1) {
216     String ext = s.substr(pos + 1).upper();
217     if(ext == "MP3")
218       return new MPEG::File(fileName, readAudioProperties, audioPropertiesStyle);
219     if(ext == "OGG")
220       return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
221     if(ext == "OGA") {
222       /* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
223       File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
224       if (file->isValid())
225         return file;
226       delete file;
227       return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
228     }
229     if(ext == "FLAC")
230       return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
231     if(ext == "MPC")
232       return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
233     if(ext == "WV")
234       return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
235     if(ext == "SPX")
236       return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
237     if(ext == "TTA")
238       return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
239     if(ext == "M4A" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
240       return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
241     if(ext == "WMA" || ext == "ASF")
242       return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
243     if(ext == "AIF")
244       return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
245     if(ext == "WAV")
246       return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
247     if(ext == "AIFF")
248       return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
249   }
250
251   return 0;
252 }