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@386
|
19 #include "ResamplingWavFileReader.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@392
|
61 AudioFileReaderFactory::createReader(FileSource source, size_t targetRate,
|
Chris@392
|
62 ProgressReporter *reporter)
|
Chris@386
|
63 {
|
Chris@392
|
64 return create(source, targetRate, false, reporter);
|
Chris@386
|
65 }
|
Chris@386
|
66
|
Chris@386
|
67 AudioFileReader *
|
Chris@392
|
68 AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate,
|
Chris@392
|
69 ProgressReporter *reporter)
|
Chris@386
|
70 {
|
Chris@392
|
71 return create(source, targetRate, true, reporter);
|
Chris@386
|
72 }
|
Chris@386
|
73
|
Chris@386
|
74 AudioFileReader *
|
Chris@392
|
75 AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading,
|
Chris@392
|
76 ProgressReporter *reporter)
|
Chris@386
|
77 {
|
Chris@386
|
78 QString err;
|
Chris@386
|
79
|
Chris@742
|
80 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
|
Chris@386
|
81
|
Chris@667
|
82 if (!source.isOK()) {
|
Chris@686
|
83 std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << std::endl;
|
Chris@667
|
84 return 0;
|
Chris@667
|
85 }
|
Chris@667
|
86
|
Chris@667
|
87 if (!source.isAvailable()) {
|
Chris@690
|
88 SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
|
Chris@386
|
89 return 0;
|
Chris@386
|
90 }
|
Chris@386
|
91
|
Chris@386
|
92 AudioFileReader *reader = 0;
|
Chris@386
|
93
|
Chris@386
|
94 // Try to construct a preferred reader based on the extension or
|
Chris@386
|
95 // MIME type.
|
Chris@386
|
96
|
Chris@386
|
97 if (WavFileReader::supports(source)) {
|
Chris@386
|
98
|
Chris@386
|
99 reader = new WavFileReader(source);
|
Chris@386
|
100
|
Chris@386
|
101 if (targetRate != 0 &&
|
Chris@386
|
102 reader->isOK() &&
|
Chris@386
|
103 reader->getSampleRate() != targetRate) {
|
Chris@386
|
104
|
Chris@690
|
105 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << endl;
|
Chris@386
|
106
|
Chris@386
|
107 delete reader;
|
Chris@386
|
108 reader = new ResamplingWavFileReader
|
Chris@386
|
109 (source,
|
Chris@386
|
110 threading ?
|
Chris@386
|
111 ResamplingWavFileReader::ResampleThreaded :
|
Chris@386
|
112 ResamplingWavFileReader::ResampleAtOnce,
|
Chris@386
|
113 ResamplingWavFileReader::CacheInTemporaryFile,
|
Chris@392
|
114 targetRate,
|
Chris@392
|
115 reporter);
|
Chris@440
|
116 if (!reader->isOK()) {
|
Chris@440
|
117 delete reader;
|
Chris@440
|
118 reader = 0;
|
Chris@440
|
119 }
|
Chris@386
|
120 }
|
Chris@386
|
121 }
|
Chris@386
|
122
|
Chris@386
|
123 #ifdef HAVE_OGGZ
|
Chris@386
|
124 #ifdef HAVE_FISHSOUND
|
Chris@386
|
125 if (!reader) {
|
Chris@386
|
126 if (OggVorbisFileReader::supports(source)) {
|
Chris@386
|
127 reader = new OggVorbisFileReader
|
Chris@386
|
128 (source,
|
Chris@386
|
129 threading ?
|
Chris@386
|
130 OggVorbisFileReader::DecodeThreaded :
|
Chris@386
|
131 OggVorbisFileReader::DecodeAtOnce,
|
Chris@386
|
132 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@392
|
133 targetRate,
|
Chris@392
|
134 reporter);
|
Chris@440
|
135 if (!reader->isOK()) {
|
Chris@440
|
136 delete reader;
|
Chris@440
|
137 reader = 0;
|
Chris@440
|
138 }
|
Chris@386
|
139 }
|
Chris@386
|
140 }
|
Chris@386
|
141 #endif
|
Chris@386
|
142 #endif
|
Chris@386
|
143
|
Chris@386
|
144 #ifdef HAVE_MAD
|
Chris@386
|
145 if (!reader) {
|
Chris@386
|
146 if (MP3FileReader::supports(source)) {
|
Chris@386
|
147 reader = new MP3FileReader
|
Chris@386
|
148 (source,
|
Chris@386
|
149 threading ?
|
Chris@386
|
150 MP3FileReader::DecodeThreaded :
|
Chris@386
|
151 MP3FileReader::DecodeAtOnce,
|
Chris@386
|
152 MP3FileReader::CacheInTemporaryFile,
|
Chris@392
|
153 targetRate,
|
Chris@392
|
154 reporter);
|
Chris@440
|
155 if (!reader->isOK()) {
|
Chris@440
|
156 delete reader;
|
Chris@440
|
157 reader = 0;
|
Chris@440
|
158 }
|
Chris@386
|
159 }
|
Chris@386
|
160 }
|
Chris@386
|
161 #endif
|
Chris@386
|
162
|
Chris@386
|
163 #ifdef HAVE_QUICKTIME
|
Chris@386
|
164 if (!reader) {
|
Chris@386
|
165 if (QuickTimeFileReader::supports(source)) {
|
Chris@386
|
166 reader = new QuickTimeFileReader
|
Chris@386
|
167 (source,
|
Chris@386
|
168 threading ?
|
Chris@386
|
169 QuickTimeFileReader::DecodeThreaded :
|
Chris@386
|
170 QuickTimeFileReader::DecodeAtOnce,
|
Chris@386
|
171 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@392
|
172 targetRate,
|
Chris@392
|
173 reporter);
|
Chris@440
|
174 if (!reader->isOK()) {
|
Chris@440
|
175 delete reader;
|
Chris@440
|
176 reader = 0;
|
Chris@440
|
177 }
|
Chris@440
|
178 }
|
Chris@440
|
179 }
|
Chris@440
|
180 #endif
|
Chris@440
|
181
|
luisf@665
|
182 #ifdef HAVE_COREAUDIO
|
luisf@665
|
183 if (!reader) {
|
luisf@665
|
184 if (CoreAudioFileReader::supports(source)) {
|
luisf@665
|
185 reader = new CoreAudioFileReader
|
luisf@665
|
186 (source,
|
luisf@665
|
187 threading ?
|
luisf@665
|
188 CoreAudioFileReader::DecodeThreaded :
|
luisf@665
|
189 CoreAudioFileReader::DecodeAtOnce,
|
luisf@665
|
190 CoreAudioFileReader::CacheInTemporaryFile,
|
luisf@665
|
191 targetRate,
|
luisf@665
|
192 reporter);
|
luisf@665
|
193 if (!reader->isOK()) {
|
luisf@665
|
194 delete reader;
|
luisf@665
|
195 reader = 0;
|
luisf@665
|
196 }
|
luisf@665
|
197 }
|
luisf@665
|
198 }
|
luisf@665
|
199 #endif
|
luisf@665
|
200
|
luisf@665
|
201
|
Chris@440
|
202 // If none of the readers claimed to support this file extension,
|
Chris@440
|
203 // perhaps the extension is missing or misleading. Try again,
|
Chris@440
|
204 // ignoring it. We have to be confident that the reader won't
|
Chris@440
|
205 // open just any old text file or whatever and pretend it's
|
Chris@440
|
206 // succeeded
|
Chris@440
|
207
|
Chris@440
|
208 if (!reader) {
|
Chris@440
|
209
|
Chris@440
|
210 reader = new WavFileReader(source);
|
Chris@440
|
211
|
Chris@440
|
212 if (targetRate != 0 &&
|
Chris@440
|
213 reader->isOK() &&
|
Chris@440
|
214 reader->getSampleRate() != targetRate) {
|
Chris@440
|
215
|
Chris@690
|
216 SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << endl;
|
Chris@440
|
217
|
Chris@440
|
218 delete reader;
|
Chris@440
|
219 reader = new ResamplingWavFileReader
|
Chris@440
|
220 (source,
|
Chris@440
|
221 threading ?
|
Chris@440
|
222 ResamplingWavFileReader::ResampleThreaded :
|
Chris@440
|
223 ResamplingWavFileReader::ResampleAtOnce,
|
Chris@440
|
224 ResamplingWavFileReader::CacheInTemporaryFile,
|
Chris@440
|
225 targetRate,
|
Chris@440
|
226 reporter);
|
Chris@440
|
227 }
|
Chris@440
|
228
|
Chris@440
|
229 if (!reader->isOK()) {
|
Chris@440
|
230 delete reader;
|
Chris@440
|
231 reader = 0;
|
Chris@440
|
232 }
|
Chris@440
|
233 }
|
Chris@440
|
234
|
Chris@440
|
235 #ifdef HAVE_OGGZ
|
Chris@440
|
236 #ifdef HAVE_FISHSOUND
|
Chris@440
|
237 if (!reader) {
|
Chris@440
|
238 reader = new OggVorbisFileReader
|
Chris@440
|
239 (source,
|
Chris@440
|
240 threading ?
|
Chris@440
|
241 OggVorbisFileReader::DecodeThreaded :
|
Chris@440
|
242 OggVorbisFileReader::DecodeAtOnce,
|
Chris@440
|
243 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@440
|
244 targetRate,
|
Chris@440
|
245 reporter);
|
Chris@440
|
246
|
Chris@440
|
247 if (!reader->isOK()) {
|
Chris@440
|
248 delete reader;
|
Chris@440
|
249 reader = 0;
|
Chris@440
|
250 }
|
Chris@440
|
251 }
|
Chris@440
|
252 #endif
|
Chris@440
|
253 #endif
|
Chris@440
|
254
|
Chris@440
|
255 #ifdef HAVE_MAD
|
Chris@440
|
256 if (!reader) {
|
Chris@440
|
257 reader = new MP3FileReader
|
Chris@440
|
258 (source,
|
Chris@440
|
259 threading ?
|
Chris@440
|
260 MP3FileReader::DecodeThreaded :
|
Chris@440
|
261 MP3FileReader::DecodeAtOnce,
|
Chris@440
|
262 MP3FileReader::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
|
Chris@440
|
273 #ifdef HAVE_QUICKTIME
|
Chris@440
|
274 if (!reader) {
|
Chris@440
|
275 reader = new QuickTimeFileReader
|
Chris@440
|
276 (source,
|
Chris@440
|
277 threading ?
|
Chris@440
|
278 QuickTimeFileReader::DecodeThreaded :
|
Chris@440
|
279 QuickTimeFileReader::DecodeAtOnce,
|
Chris@440
|
280 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@440
|
281 targetRate,
|
Chris@440
|
282 reporter);
|
Chris@440
|
283
|
Chris@440
|
284 if (!reader->isOK()) {
|
Chris@440
|
285 delete reader;
|
Chris@440
|
286 reader = 0;
|
Chris@386
|
287 }
|
Chris@386
|
288 }
|
Chris@386
|
289 #endif
|
Chris@386
|
290
|
luisf@665
|
291 #ifdef HAVE_COREAUDIO
|
luisf@665
|
292
|
luisf@665
|
293 std::cerr << "AudioFileReaderFactory: HAVE_COREAUDIO" << std::endl;
|
luisf@665
|
294
|
luisf@665
|
295 if (!reader) {
|
luisf@665
|
296 reader = new CoreAudioFileReader
|
luisf@665
|
297 (source,
|
luisf@665
|
298 threading ?
|
luisf@665
|
299 CoreAudioFileReader::DecodeThreaded :
|
luisf@665
|
300 CoreAudioFileReader::DecodeAtOnce,
|
luisf@665
|
301 CoreAudioFileReader::CacheInTemporaryFile,
|
luisf@665
|
302 targetRate,
|
luisf@665
|
303 reporter);
|
luisf@665
|
304
|
luisf@665
|
305 if (!reader->isOK()) {
|
luisf@665
|
306 delete reader;
|
luisf@665
|
307 reader = 0;
|
luisf@665
|
308 }
|
luisf@665
|
309 }
|
luisf@665
|
310 #endif
|
luisf@665
|
311
|
Chris@386
|
312 if (reader) {
|
Chris@386
|
313 if (reader->isOK()) {
|
luisf@665
|
314 std::cerr << "AudioFileReaderFactory: Reader is OK" << std::endl;
|
Chris@386
|
315 return reader;
|
Chris@386
|
316 }
|
Chris@386
|
317 std::cerr << "AudioFileReaderFactory: Preferred reader for "
|
Chris@386
|
318 << "url \"" << source.getLocation().toStdString()
|
Chris@386
|
319 << "\" (content type \""
|
Chris@686
|
320 << source.getContentType() << "\") failed";
|
Chris@386
|
321
|
Chris@386
|
322 if (reader->getError() != "") {
|
Chris@686
|
323 std::cerr << ": \"" << reader->getError() << "\"";
|
Chris@386
|
324 }
|
Chris@386
|
325 std::cerr << std::endl;
|
Chris@386
|
326 delete reader;
|
Chris@386
|
327 reader = 0;
|
Chris@386
|
328 }
|
Chris@386
|
329
|
Chris@386
|
330 std::cerr << "AudioFileReaderFactory: No reader" << std::endl;
|
Chris@386
|
331 return reader;
|
Chris@386
|
332 }
|
Chris@386
|
333
|