annotate data/fileio/AudioFileReaderFactory.cpp @ 458:f60360209e5c

* Fix race condition in FFTFileCache when reading from the same FFT model from multiple threads (e.g. when applying more than one plugin at once)
author Chris Cannam
date Wed, 15 Oct 2008 12:08:02 +0000
parents 5746c559af15
children 029dd9e5cc29 1c8898816fd0
rev   line source
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