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"
|
Chris@386
|
23
|
Chris@386
|
24 #include <QString>
|
Chris@386
|
25 #include <QFileInfo>
|
Chris@386
|
26 #include <iostream>
|
Chris@386
|
27
|
Chris@386
|
28 QString
|
Chris@386
|
29 AudioFileReaderFactory::getKnownExtensions()
|
Chris@386
|
30 {
|
Chris@386
|
31 std::set<QString> extensions;
|
Chris@386
|
32
|
Chris@386
|
33 WavFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
34 #ifdef HAVE_MAD
|
Chris@386
|
35 MP3FileReader::getSupportedExtensions(extensions);
|
Chris@386
|
36 #endif
|
Chris@386
|
37 #ifdef HAVE_OGGZ
|
Chris@386
|
38 #ifdef HAVE_FISHSOUND
|
Chris@386
|
39 OggVorbisFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
40 #endif
|
Chris@386
|
41 #endif
|
Chris@386
|
42 #ifdef HAVE_QUICKTIME
|
Chris@386
|
43 QuickTimeFileReader::getSupportedExtensions(extensions);
|
Chris@386
|
44 #endif
|
Chris@386
|
45
|
Chris@386
|
46 QString rv;
|
Chris@386
|
47 for (std::set<QString>::const_iterator i = extensions.begin();
|
Chris@386
|
48 i != extensions.end(); ++i) {
|
Chris@386
|
49 if (i != extensions.begin()) rv += " ";
|
Chris@386
|
50 rv += "*." + *i;
|
Chris@386
|
51 }
|
Chris@386
|
52
|
Chris@386
|
53 return rv;
|
Chris@386
|
54 }
|
Chris@386
|
55
|
Chris@386
|
56 AudioFileReader *
|
Chris@392
|
57 AudioFileReaderFactory::createReader(FileSource source, size_t targetRate,
|
Chris@392
|
58 ProgressReporter *reporter)
|
Chris@386
|
59 {
|
Chris@392
|
60 return create(source, targetRate, false, reporter);
|
Chris@386
|
61 }
|
Chris@386
|
62
|
Chris@386
|
63 AudioFileReader *
|
Chris@392
|
64 AudioFileReaderFactory::createThreadingReader(FileSource source, size_t targetRate,
|
Chris@392
|
65 ProgressReporter *reporter)
|
Chris@386
|
66 {
|
Chris@392
|
67 return create(source, targetRate, true, reporter);
|
Chris@386
|
68 }
|
Chris@386
|
69
|
Chris@386
|
70 AudioFileReader *
|
Chris@392
|
71 AudioFileReaderFactory::create(FileSource source, size_t targetRate, bool threading,
|
Chris@392
|
72 ProgressReporter *reporter)
|
Chris@386
|
73 {
|
Chris@386
|
74 QString err;
|
Chris@386
|
75
|
Chris@386
|
76 // std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\"): Requested rate: " << targetRate << std::endl;
|
Chris@386
|
77
|
Chris@386
|
78 if (!source.isOK() || !source.isAvailable()) {
|
Chris@386
|
79 std::cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation().toStdString() << "\": Source unavailable" << std::endl;
|
Chris@386
|
80 return 0;
|
Chris@386
|
81 }
|
Chris@386
|
82
|
Chris@386
|
83 AudioFileReader *reader = 0;
|
Chris@386
|
84
|
Chris@386
|
85 // Try to construct a preferred reader based on the extension or
|
Chris@386
|
86 // MIME type.
|
Chris@386
|
87
|
Chris@386
|
88 if (WavFileReader::supports(source)) {
|
Chris@386
|
89
|
Chris@386
|
90 reader = new WavFileReader(source);
|
Chris@386
|
91
|
Chris@386
|
92 if (targetRate != 0 &&
|
Chris@386
|
93 reader->isOK() &&
|
Chris@386
|
94 reader->getSampleRate() != targetRate) {
|
Chris@386
|
95
|
Chris@386
|
96 std::cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << std::endl;
|
Chris@386
|
97
|
Chris@386
|
98 delete reader;
|
Chris@386
|
99 reader = new ResamplingWavFileReader
|
Chris@386
|
100 (source,
|
Chris@386
|
101 threading ?
|
Chris@386
|
102 ResamplingWavFileReader::ResampleThreaded :
|
Chris@386
|
103 ResamplingWavFileReader::ResampleAtOnce,
|
Chris@386
|
104 ResamplingWavFileReader::CacheInTemporaryFile,
|
Chris@392
|
105 targetRate,
|
Chris@392
|
106 reporter);
|
Chris@440
|
107 if (!reader->isOK()) {
|
Chris@440
|
108 delete reader;
|
Chris@440
|
109 reader = 0;
|
Chris@440
|
110 }
|
Chris@386
|
111 }
|
Chris@386
|
112 }
|
Chris@386
|
113
|
Chris@386
|
114 #ifdef HAVE_OGGZ
|
Chris@386
|
115 #ifdef HAVE_FISHSOUND
|
Chris@386
|
116 if (!reader) {
|
Chris@386
|
117 if (OggVorbisFileReader::supports(source)) {
|
Chris@386
|
118 reader = new OggVorbisFileReader
|
Chris@386
|
119 (source,
|
Chris@386
|
120 threading ?
|
Chris@386
|
121 OggVorbisFileReader::DecodeThreaded :
|
Chris@386
|
122 OggVorbisFileReader::DecodeAtOnce,
|
Chris@386
|
123 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@392
|
124 targetRate,
|
Chris@392
|
125 reporter);
|
Chris@440
|
126 if (!reader->isOK()) {
|
Chris@440
|
127 delete reader;
|
Chris@440
|
128 reader = 0;
|
Chris@440
|
129 }
|
Chris@386
|
130 }
|
Chris@386
|
131 }
|
Chris@386
|
132 #endif
|
Chris@386
|
133 #endif
|
Chris@386
|
134
|
Chris@386
|
135 #ifdef HAVE_MAD
|
Chris@386
|
136 if (!reader) {
|
Chris@386
|
137 if (MP3FileReader::supports(source)) {
|
Chris@386
|
138 reader = new MP3FileReader
|
Chris@386
|
139 (source,
|
Chris@386
|
140 threading ?
|
Chris@386
|
141 MP3FileReader::DecodeThreaded :
|
Chris@386
|
142 MP3FileReader::DecodeAtOnce,
|
Chris@386
|
143 MP3FileReader::CacheInTemporaryFile,
|
Chris@392
|
144 targetRate,
|
Chris@392
|
145 reporter);
|
Chris@440
|
146 if (!reader->isOK()) {
|
Chris@440
|
147 delete reader;
|
Chris@440
|
148 reader = 0;
|
Chris@440
|
149 }
|
Chris@386
|
150 }
|
Chris@386
|
151 }
|
Chris@386
|
152 #endif
|
Chris@386
|
153
|
Chris@386
|
154 #ifdef HAVE_QUICKTIME
|
Chris@386
|
155 if (!reader) {
|
Chris@386
|
156 if (QuickTimeFileReader::supports(source)) {
|
Chris@386
|
157 reader = new QuickTimeFileReader
|
Chris@386
|
158 (source,
|
Chris@386
|
159 threading ?
|
Chris@386
|
160 QuickTimeFileReader::DecodeThreaded :
|
Chris@386
|
161 QuickTimeFileReader::DecodeAtOnce,
|
Chris@386
|
162 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@392
|
163 targetRate,
|
Chris@392
|
164 reporter);
|
Chris@440
|
165 if (!reader->isOK()) {
|
Chris@440
|
166 delete reader;
|
Chris@440
|
167 reader = 0;
|
Chris@440
|
168 }
|
Chris@440
|
169 }
|
Chris@440
|
170 }
|
Chris@440
|
171 #endif
|
Chris@440
|
172
|
Chris@440
|
173 // If none of the readers claimed to support this file extension,
|
Chris@440
|
174 // perhaps the extension is missing or misleading. Try again,
|
Chris@440
|
175 // ignoring it. We have to be confident that the reader won't
|
Chris@440
|
176 // open just any old text file or whatever and pretend it's
|
Chris@440
|
177 // succeeded
|
Chris@440
|
178
|
Chris@440
|
179 if (!reader) {
|
Chris@440
|
180
|
Chris@440
|
181 reader = new WavFileReader(source);
|
Chris@440
|
182
|
Chris@440
|
183 if (targetRate != 0 &&
|
Chris@440
|
184 reader->isOK() &&
|
Chris@440
|
185 reader->getSampleRate() != targetRate) {
|
Chris@440
|
186
|
Chris@440
|
187 std::cerr << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", creating resampling reader" << std::endl;
|
Chris@440
|
188
|
Chris@440
|
189 delete reader;
|
Chris@440
|
190 reader = new ResamplingWavFileReader
|
Chris@440
|
191 (source,
|
Chris@440
|
192 threading ?
|
Chris@440
|
193 ResamplingWavFileReader::ResampleThreaded :
|
Chris@440
|
194 ResamplingWavFileReader::ResampleAtOnce,
|
Chris@440
|
195 ResamplingWavFileReader::CacheInTemporaryFile,
|
Chris@440
|
196 targetRate,
|
Chris@440
|
197 reporter);
|
Chris@440
|
198 }
|
Chris@440
|
199
|
Chris@440
|
200 if (!reader->isOK()) {
|
Chris@440
|
201 delete reader;
|
Chris@440
|
202 reader = 0;
|
Chris@440
|
203 }
|
Chris@440
|
204 }
|
Chris@440
|
205
|
Chris@440
|
206 #ifdef HAVE_OGGZ
|
Chris@440
|
207 #ifdef HAVE_FISHSOUND
|
Chris@440
|
208 if (!reader) {
|
Chris@440
|
209 reader = new OggVorbisFileReader
|
Chris@440
|
210 (source,
|
Chris@440
|
211 threading ?
|
Chris@440
|
212 OggVorbisFileReader::DecodeThreaded :
|
Chris@440
|
213 OggVorbisFileReader::DecodeAtOnce,
|
Chris@440
|
214 OggVorbisFileReader::CacheInTemporaryFile,
|
Chris@440
|
215 targetRate,
|
Chris@440
|
216 reporter);
|
Chris@440
|
217
|
Chris@440
|
218 if (!reader->isOK()) {
|
Chris@440
|
219 delete reader;
|
Chris@440
|
220 reader = 0;
|
Chris@440
|
221 }
|
Chris@440
|
222 }
|
Chris@440
|
223 #endif
|
Chris@440
|
224 #endif
|
Chris@440
|
225
|
Chris@440
|
226 #ifdef HAVE_MAD
|
Chris@440
|
227 if (!reader) {
|
Chris@440
|
228 reader = new MP3FileReader
|
Chris@440
|
229 (source,
|
Chris@440
|
230 threading ?
|
Chris@440
|
231 MP3FileReader::DecodeThreaded :
|
Chris@440
|
232 MP3FileReader::DecodeAtOnce,
|
Chris@440
|
233 MP3FileReader::CacheInTemporaryFile,
|
Chris@440
|
234 targetRate,
|
Chris@440
|
235 reporter);
|
Chris@440
|
236
|
Chris@440
|
237 if (!reader->isOK()) {
|
Chris@440
|
238 delete reader;
|
Chris@440
|
239 reader = 0;
|
Chris@440
|
240 }
|
Chris@440
|
241 }
|
Chris@440
|
242 #endif
|
Chris@440
|
243
|
Chris@440
|
244 #ifdef HAVE_QUICKTIME
|
Chris@440
|
245 if (!reader) {
|
Chris@440
|
246 reader = new QuickTimeFileReader
|
Chris@440
|
247 (source,
|
Chris@440
|
248 threading ?
|
Chris@440
|
249 QuickTimeFileReader::DecodeThreaded :
|
Chris@440
|
250 QuickTimeFileReader::DecodeAtOnce,
|
Chris@440
|
251 QuickTimeFileReader::CacheInTemporaryFile,
|
Chris@440
|
252 targetRate,
|
Chris@440
|
253 reporter);
|
Chris@440
|
254
|
Chris@440
|
255 if (!reader->isOK()) {
|
Chris@440
|
256 delete reader;
|
Chris@440
|
257 reader = 0;
|
Chris@386
|
258 }
|
Chris@386
|
259 }
|
Chris@386
|
260 #endif
|
Chris@386
|
261
|
Chris@386
|
262 if (reader) {
|
Chris@386
|
263 if (reader->isOK()) {
|
Chris@386
|
264 // std::cerr << "AudioFileReaderFactory: Reader is OK" << std::endl;
|
Chris@386
|
265 return reader;
|
Chris@386
|
266 }
|
Chris@386
|
267 std::cerr << "AudioFileReaderFactory: Preferred reader for "
|
Chris@386
|
268 << "url \"" << source.getLocation().toStdString()
|
Chris@386
|
269 << "\" (content type \""
|
Chris@386
|
270 << source.getContentType().toStdString() << "\") failed";
|
Chris@386
|
271
|
Chris@386
|
272 if (reader->getError() != "") {
|
Chris@386
|
273 std::cerr << ": \"" << reader->getError().toStdString() << "\"";
|
Chris@386
|
274 }
|
Chris@386
|
275 std::cerr << std::endl;
|
Chris@386
|
276 delete reader;
|
Chris@386
|
277 reader = 0;
|
Chris@386
|
278 }
|
Chris@386
|
279
|
Chris@386
|
280 std::cerr << "AudioFileReaderFactory: No reader" << std::endl;
|
Chris@386
|
281 return reader;
|
Chris@386
|
282 }
|
Chris@386
|
283
|