Chris@386
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@386
|
2
|
Chris@386
|
3 /*
|
Chris@386
|
4 Sonic Visualiser
|
Chris@386
|
5 An audio file viewer and annotation editor.
|
Chris@386
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@386
|
7 This file copyright 2006 Chris Cannam and QMUL.
|
Chris@386
|
8
|
Chris@386
|
9 This program is free software; you can redistribute it and/or
|
Chris@386
|
10 modify it under the terms of the GNU General Public License as
|
Chris@386
|
11 published by the Free Software Foundation; either version 2 of the
|
Chris@386
|
12 License, or (at your option) any later version. See the file
|
Chris@386
|
13 COPYING included with this distribution for more information.
|
Chris@386
|
14 */
|
Chris@386
|
15
|
Chris@386
|
16 #include "AudioFileReaderFactory.h"
|
Chris@386
|
17
|
Chris@386
|
18 #include "WavFileReader.h"
|
Chris@823
|
19 #include "DecodingWavFileReader.h"
|
Chris@386
|
20 #include "OggVorbisFileReader.h"
|
Chris@386
|
21 #include "MP3FileReader.h"
|
Chris@386
|
22 #include "QuickTimeFileReader.h"
|
luisf@665
|
23 #include "CoreAudioFileReader.h"
|
Chris@386
|
24
|
Chris@386
|
25 #include <QString>
|
Chris@386
|
26 #include <QFileInfo>
|
Chris@386
|
27 #include <iostream>
|
Chris@386
|
28
|
Chris@386
|
29 QString
|
Chris@386
|
30 AudioFileReaderFactory::getKnownExtensions()
|
Chris@386
|
31 {
|
Chris@386
|
32 std::set<QString> extensions;
|
Chris@386
|
33
|
Chris@386
|
34 WavFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
35 #ifdef HAVE_MAD
|
Chris@386
|
36 MP3FileReader::getSupportedExtensions(extensions);
|
Chris@386
|
37 #endif
|
Chris@386
|
38 #ifdef HAVE_OGGZ
|
Chris@386
|
39 #ifdef HAVE_FISHSOUND
|
Chris@386
|
40 OggVorbisFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
41 #endif
|
Chris@386
|
42 #endif
|
Chris@386
|
43 #ifdef HAVE_QUICKTIME
|
Chris@386
|
44 QuickTimeFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
45 #endif
|
luisf@665
|
46 #ifdef HAVE_COREAUDIO
|
luisf@665
|
47 CoreAudioFileReader::getSupportedExtensions(extensions);
|
luisf@665
|
48 #endif
|
Chris@386
|
49
|
Chris@386
|
50 QString rv;
|
Chris@386
|
51 for (std::set<QString>::const_iterator i = extensions.begin();
|
Chris@386
|
52 i != extensions.end(); ++i) {
|
Chris@386
|
53 if (i != extensions.begin()) rv += " ";
|
Chris@386
|
54 rv += "*." + *i;
|
Chris@386
|
55 }
|
Chris@386
|
56
|
Chris@386
|
57 return rv;
|
Chris@386
|
58 }
|
Chris@386
|
59
|
Chris@386
|
60 AudioFileReader *
|
Chris@920
|
61 AudioFileReaderFactory::createReader(FileSource source,
|
Chris@920
|
62 size_t targetRate,
|
Chris@920
|
63 bool normalised,
|
Chris@392
|
64 ProgressReporter *reporter)
|
Chris@386
|
65 {
|
Chris@920
|
66 return create(source, targetRate, normalised, false, reporter);
|
Chris@386
|
67 }
|
Chris@386
|
68
|
Chris@386
|
69 AudioFileReader *
|
Chris@920
|
70 AudioFileReaderFactory::createThreadingReader(FileSource source,
|
Chris@920
|
71 size_t targetRate,
|
Chris@920
|
72 bool normalised,
|
Chris@392
|
73 ProgressReporter *reporter)
|
Chris@386
|
74 {
|
Chris@920
|
75 return create(source, targetRate, normalised, true, reporter);
|
Chris@386
|
76 }
|
Chris@386
|
77
|
Chris@386
|
78 AudioFileReader *
|
Chris@920
|
79 AudioFileReaderFactory::create(FileSource source,
|
Chris@920
|
80 size_t targetRate,
|
Chris@920
|
81 bool normalised,
|
Chris@920
|
82 bool threading,
|
Chris@392
|
83 ProgressReporter *reporter)
|
Chris@386
|
84 {
|
Chris@386
|
85 QString err;
|
Chris@386
|
86
|
Chris@742
|
87 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
|
Chris@386
|
88
|
Chris@667
|
89 if (!source.isOK()) {
|
Chris@843
|
90 cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
|
Chris@667
|
91 return 0;
|
Chris@667
|
92 }
|
Chris@667
|
93
|
Chris@667
|
94 if (!source.isAvailable()) {
|
Chris@690
|
95 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
|
Chris@386
|
96 return 0;
|
Chris@386
|
97 }
|
Chris@386
|
98
|
Chris@386
|
99 AudioFileReader *reader = 0;
|
Chris@386
|
100
|
Chris@386
|
101 // Try to construct a preferred reader based on the extension or
|
Chris@386
|
102 // MIME type.
|
Chris@386
|
103
|
Chris@386
|
104 if (WavFileReader::supports(source)) {
|
Chris@386
|
105
|
Chris@386
|
106 reader = new WavFileReader(source);
|
Chris@386
|
107
|
Chris@823
|
108 int fileRate = reader->getSampleRate();
|
Chris@386
|
109
|
Chris@823
|
110 if (reader->isOK() &&
|
Chris@823
|
111 (!reader->isQuicklySeekable() ||
|
Chris@920
|
112 normalised ||
|
Chris@823
|
113 (targetRate != 0 && fileRate != targetRate))) {
|
Chris@823
|
114
|
Chris@920
|
115 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
|
Chris@386
|
116
|
Chris@386
|
117 delete reader;
|
Chris@823
|
118 reader = new DecodingWavFileReader
|
Chris@386
|
119 (source,
|
Chris@386
|
120 threading ?
|
Chris@823
|
121 DecodingWavFileReader::ResampleThreaded :
|
Chris@823
|
122 DecodingWavFileReader::ResampleAtOnce,
|
Chris@823
|
123 DecodingWavFileReader::CacheInTemporaryFile,
|
Chris@823
|
124 targetRate ? targetRate : fileRate,
|
Chris@920
|
125 normalised,
|
Chris@392
|
126 reporter);
|
Chris@440
|
127 if (!reader->isOK()) {
|
Chris@440
|
128 delete reader;
|
Chris@440
|
129 reader = 0;
|
Chris@440
|
130 }
|
Chris@386
|
131 }
|
Chris@386
|
132 }
|
Chris@386
|
133
|
Chris@386
|
134 #ifdef HAVE_OGGZ
|
Chris@386
|
135 #ifdef HAVE_FISHSOUND
|
Chris@386
|
136 if (!reader) {
|
Chris@386
|
137 if (OggVorbisFileReader::supports(source)) {
|
Chris@386
|
138 reader = new OggVorbisFileReader
|
Chris@386
|
139 (source,
|
Chris@386
|
140 threading ?
|
Chris@386
|
141 OggVorbisFileReader::DecodeThreaded :
|
Chris@386
|
142 OggVorbisFileReader::DecodeAtOnce,
|
Chris@386
|
143 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@392
|
144 targetRate,
|
Chris@920
|
145 normalised,
|
Chris@392
|
146 reporter);
|
Chris@440
|
147 if (!reader->isOK()) {
|
Chris@440
|
148 delete reader;
|
Chris@440
|
149 reader = 0;
|
Chris@440
|
150 }
|
Chris@386
|
151 }
|
Chris@386
|
152 }
|
Chris@386
|
153 #endif
|
Chris@386
|
154 #endif
|
Chris@386
|
155
|
Chris@386
|
156 #ifdef HAVE_MAD
|
Chris@386
|
157 if (!reader) {
|
Chris@386
|
158 if (MP3FileReader::supports(source)) {
|
Chris@386
|
159 reader = new MP3FileReader
|
Chris@386
|
160 (source,
|
Chris@386
|
161 threading ?
|
Chris@386
|
162 MP3FileReader::DecodeThreaded :
|
Chris@386
|
163 MP3FileReader::DecodeAtOnce,
|
Chris@386
|
164 MP3FileReader::CacheInTemporaryFile,
|
Chris@392
|
165 targetRate,
|
Chris@920
|
166 normalised,
|
Chris@392
|
167 reporter);
|
Chris@440
|
168 if (!reader->isOK()) {
|
Chris@440
|
169 delete reader;
|
Chris@440
|
170 reader = 0;
|
Chris@440
|
171 }
|
Chris@386
|
172 }
|
Chris@386
|
173 }
|
Chris@386
|
174 #endif
|
Chris@386
|
175
|
Chris@386
|
176 #ifdef HAVE_QUICKTIME
|
Chris@386
|
177 if (!reader) {
|
Chris@386
|
178 if (QuickTimeFileReader::supports(source)) {
|
Chris@386
|
179 reader = new QuickTimeFileReader
|
Chris@386
|
180 (source,
|
Chris@386
|
181 threading ?
|
Chris@386
|
182 QuickTimeFileReader::DecodeThreaded :
|
Chris@386
|
183 QuickTimeFileReader::DecodeAtOnce,
|
Chris@386
|
184 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@392
|
185 targetRate,
|
Chris@920
|
186 normalised,
|
Chris@392
|
187 reporter);
|
Chris@440
|
188 if (!reader->isOK()) {
|
Chris@440
|
189 delete reader;
|
Chris@440
|
190 reader = 0;
|
Chris@440
|
191 }
|
Chris@440
|
192 }
|
Chris@440
|
193 }
|
Chris@440
|
194 #endif
|
Chris@440
|
195
|
luisf@665
|
196 #ifdef HAVE_COREAUDIO
|
luisf@665
|
197 if (!reader) {
|
luisf@665
|
198 if (CoreAudioFileReader::supports(source)) {
|
luisf@665
|
199 reader = new CoreAudioFileReader
|
luisf@665
|
200 (source,
|
luisf@665
|
201 threading ?
|
luisf@665
|
202 CoreAudioFileReader::DecodeThreaded :
|
luisf@665
|
203 CoreAudioFileReader::DecodeAtOnce,
|
luisf@665
|
204 CoreAudioFileReader::CacheInTemporaryFile,
|
luisf@665
|
205 targetRate,
|
Chris@920
|
206 normalised,
|
luisf@665
|
207 reporter);
|
luisf@665
|
208 if (!reader->isOK()) {
|
luisf@665
|
209 delete reader;
|
luisf@665
|
210 reader = 0;
|
luisf@665
|
211 }
|
luisf@665
|
212 }
|
luisf@665
|
213 }
|
luisf@665
|
214 #endif
|
luisf@665
|
215
|
luisf@665
|
216
|
Chris@440
|
217 // If none of the readers claimed to support this file extension,
|
Chris@440
|
218 // perhaps the extension is missing or misleading. Try again,
|
Chris@440
|
219 // ignoring it. We have to be confident that the reader won't
|
Chris@440
|
220 // open just any old text file or whatever and pretend it's
|
Chris@440
|
221 // succeeded
|
Chris@440
|
222
|
Chris@440
|
223 if (!reader) {
|
Chris@440
|
224
|
Chris@440
|
225 reader = new WavFileReader(source);
|
Chris@440
|
226
|
Chris@823
|
227 int fileRate = reader->getSampleRate();
|
Chris@440
|
228
|
Chris@823
|
229 if (reader->isOK() &&
|
Chris@823
|
230 (!reader->isQuicklySeekable() ||
|
Chris@920
|
231 normalised ||
|
Chris@823
|
232 (targetRate != 0 && fileRate != targetRate))) {
|
Chris@823
|
233
|
Chris@920
|
234 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
|
Chris@440
|
235
|
Chris@440
|
236 delete reader;
|
Chris@823
|
237 reader = new DecodingWavFileReader
|
Chris@440
|
238 (source,
|
Chris@440
|
239 threading ?
|
Chris@823
|
240 DecodingWavFileReader::ResampleThreaded :
|
Chris@823
|
241 DecodingWavFileReader::ResampleAtOnce,
|
Chris@823
|
242 DecodingWavFileReader::CacheInTemporaryFile,
|
Chris@823
|
243 targetRate ? targetRate : fileRate,
|
Chris@920
|
244 normalised,
|
Chris@440
|
245 reporter);
|
Chris@440
|
246 }
|
Chris@440
|
247
|
Chris@440
|
248 if (!reader->isOK()) {
|
Chris@440
|
249 delete reader;
|
Chris@440
|
250 reader = 0;
|
Chris@440
|
251 }
|
Chris@440
|
252 }
|
Chris@440
|
253
|
Chris@440
|
254 #ifdef HAVE_OGGZ
|
Chris@440
|
255 #ifdef HAVE_FISHSOUND
|
Chris@440
|
256 if (!reader) {
|
Chris@440
|
257 reader = new OggVorbisFileReader
|
Chris@440
|
258 (source,
|
Chris@440
|
259 threading ?
|
Chris@440
|
260 OggVorbisFileReader::DecodeThreaded :
|
Chris@440
|
261 OggVorbisFileReader::DecodeAtOnce,
|
Chris@440
|
262 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@440
|
263 targetRate,
|
Chris@440
|
264 reporter);
|
Chris@440
|
265
|
Chris@440
|
266 if (!reader->isOK()) {
|
Chris@440
|
267 delete reader;
|
Chris@440
|
268 reader = 0;
|
Chris@440
|
269 }
|
Chris@440
|
270 }
|
Chris@440
|
271 #endif
|
Chris@440
|
272 #endif
|
Chris@440
|
273
|
Chris@440
|
274 #ifdef HAVE_MAD
|
Chris@440
|
275 if (!reader) {
|
Chris@440
|
276 reader = new MP3FileReader
|
Chris@440
|
277 (source,
|
Chris@440
|
278 threading ?
|
Chris@440
|
279 MP3FileReader::DecodeThreaded :
|
Chris@440
|
280 MP3FileReader::DecodeAtOnce,
|
Chris@440
|
281 MP3FileReader::CacheInTemporaryFile,
|
Chris@440
|
282 targetRate,
|
Chris@440
|
283 reporter);
|
Chris@440
|
284
|
Chris@440
|
285 if (!reader->isOK()) {
|
Chris@440
|
286 delete reader;
|
Chris@440
|
287 reader = 0;
|
Chris@440
|
288 }
|
Chris@440
|
289 }
|
Chris@440
|
290 #endif
|
Chris@440
|
291
|
Chris@440
|
292 #ifdef HAVE_QUICKTIME
|
Chris@440
|
293 if (!reader) {
|
Chris@440
|
294 reader = new QuickTimeFileReader
|
Chris@440
|
295 (source,
|
Chris@440
|
296 threading ?
|
Chris@440
|
297 QuickTimeFileReader::DecodeThreaded :
|
Chris@440
|
298 QuickTimeFileReader::DecodeAtOnce,
|
Chris@440
|
299 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@440
|
300 targetRate,
|
Chris@440
|
301 reporter);
|
Chris@440
|
302
|
Chris@440
|
303 if (!reader->isOK()) {
|
Chris@440
|
304 delete reader;
|
Chris@440
|
305 reader = 0;
|
Chris@386
|
306 }
|
Chris@386
|
307 }
|
Chris@386
|
308 #endif
|
Chris@386
|
309
|
luisf@665
|
310 #ifdef HAVE_COREAUDIO
|
luisf@665
|
311 if (!reader) {
|
luisf@665
|
312 reader = new CoreAudioFileReader
|
luisf@665
|
313 (source,
|
luisf@665
|
314 threading ?
|
luisf@665
|
315 CoreAudioFileReader::DecodeThreaded :
|
luisf@665
|
316 CoreAudioFileReader::DecodeAtOnce,
|
luisf@665
|
317 CoreAudioFileReader::CacheInTemporaryFile,
|
luisf@665
|
318 targetRate,
|
luisf@665
|
319 reporter);
|
luisf@665
|
320
|
luisf@665
|
321 if (!reader->isOK()) {
|
luisf@665
|
322 delete reader;
|
luisf@665
|
323 reader = 0;
|
luisf@665
|
324 }
|
luisf@665
|
325 }
|
luisf@665
|
326 #endif
|
luisf@665
|
327
|
Chris@386
|
328 if (reader) {
|
Chris@386
|
329 if (reader->isOK()) {
|
Chris@756
|
330 SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
|
Chris@386
|
331 return reader;
|
Chris@386
|
332 }
|
Chris@843
|
333 cerr << "AudioFileReaderFactory: Preferred reader for "
|
Chris@844
|
334 << "url \"" << source.getLocation()
|
Chris@386
|
335 << "\" (content type \""
|
Chris@686
|
336 << source.getContentType() << "\") failed";
|
Chris@386
|
337
|
Chris@386
|
338 if (reader->getError() != "") {
|
Chris@843
|
339 cerr << ": \"" << reader->getError() << "\"";
|
Chris@386
|
340 }
|
Chris@843
|
341 cerr << endl;
|
Chris@386
|
342 delete reader;
|
Chris@386
|
343 reader = 0;
|
Chris@386
|
344 }
|
Chris@386
|
345
|
Chris@843
|
346 cerr << "AudioFileReaderFactory: No reader" << endl;
|
Chris@386
|
347 return reader;
|
Chris@386
|
348 }
|
Chris@386
|
349
|