svcore  1.9
AudioFileReaderFactory.cpp
Go to the documentation of this file.
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
00002 
00003 /*
00004     Sonic Visualiser
00005     An audio file viewer and annotation editor.
00006     Centre for Digital Music, Queen Mary, University of London.
00007     This file copyright 2006 Chris Cannam and QMUL.
00008     
00009     This program is free software; you can redistribute it and/or
00010     modify it under the terms of the GNU General Public License as
00011     published by the Free Software Foundation; either version 2 of the
00012     License, or (at your option) any later version.  See the file
00013     COPYING included with this distribution for more information.
00014 */
00015 
00016 #include "AudioFileReaderFactory.h"
00017 
00018 #include "WavFileReader.h"
00019 #include "DecodingWavFileReader.h"
00020 #include "OggVorbisFileReader.h"
00021 #include "MP3FileReader.h"
00022 #include "QuickTimeFileReader.h"
00023 #include "CoreAudioFileReader.h"
00024 
00025 #include <QString>
00026 #include <QFileInfo>
00027 #include <iostream>
00028 
00029 QString
00030 AudioFileReaderFactory::getKnownExtensions()
00031 {
00032     std::set<QString> extensions;
00033 
00034     WavFileReader::getSupportedExtensions(extensions);
00035 #ifdef HAVE_MAD
00036     MP3FileReader::getSupportedExtensions(extensions);
00037 #endif
00038 #ifdef HAVE_OGGZ
00039 #ifdef HAVE_FISHSOUND
00040     OggVorbisFileReader::getSupportedExtensions(extensions);
00041 #endif
00042 #endif
00043 #ifdef HAVE_QUICKTIME
00044     QuickTimeFileReader::getSupportedExtensions(extensions);
00045 #endif
00046 #ifdef HAVE_COREAUDIO
00047     CoreAudioFileReader::getSupportedExtensions(extensions);
00048 #endif
00049 
00050     QString rv;
00051     for (std::set<QString>::const_iterator i = extensions.begin();
00052          i != extensions.end(); ++i) {
00053         if (i != extensions.begin()) rv += " ";
00054         rv += "*." + *i;
00055     }
00056 
00057     return rv;
00058 }
00059 
00060 AudioFileReader *
00061 AudioFileReaderFactory::createReader(FileSource source, 
00062                                      int targetRate,
00063                                      bool normalised,
00064                                      ProgressReporter *reporter)
00065 {
00066     return create(source, targetRate, normalised, false, reporter);
00067 }
00068 
00069 AudioFileReader *
00070 AudioFileReaderFactory::createThreadingReader(FileSource source, 
00071                                               int targetRate,
00072                                               bool normalised,
00073                                               ProgressReporter *reporter)
00074 {
00075     return create(source, targetRate, normalised, true, reporter);
00076 }
00077 
00078 AudioFileReader *
00079 AudioFileReaderFactory::create(FileSource source, 
00080                                int targetRate, 
00081                                bool normalised,
00082                                bool threading,
00083                                ProgressReporter *reporter)
00084 {
00085     QString err;
00086 
00087     SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl;
00088 
00089     if (!source.isOK()) {
00090         cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl;
00091         return 0;
00092     }
00093 
00094     if (!source.isAvailable()) {
00095         SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl;
00096         return 0;
00097     }
00098 
00099     AudioFileReader *reader = 0;
00100 
00101     // Try to construct a preferred reader based on the extension or
00102     // MIME type.
00103 
00104     if (WavFileReader::supports(source)) {
00105 
00106         reader = new WavFileReader(source);
00107 
00108         int fileRate = reader->getSampleRate();
00109 
00110         if (reader->isOK() &&
00111             (!reader->isQuicklySeekable() ||
00112              normalised ||
00113              (targetRate != 0 && fileRate != targetRate))) {
00114 
00115             SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
00116 
00117             delete reader;
00118             reader = new DecodingWavFileReader
00119                 (source,
00120                  threading ?
00121                  DecodingWavFileReader::ResampleThreaded :
00122                  DecodingWavFileReader::ResampleAtOnce,
00123                  DecodingWavFileReader::CacheInTemporaryFile,
00124                  targetRate ? targetRate : fileRate,
00125                  normalised,
00126                  reporter);
00127             if (!reader->isOK()) {
00128                 delete reader;
00129                 reader = 0;
00130             }
00131         }
00132     }
00133     
00134 #ifdef HAVE_OGGZ
00135 #ifdef HAVE_FISHSOUND
00136     if (!reader) {
00137         if (OggVorbisFileReader::supports(source)) {
00138             reader = new OggVorbisFileReader
00139                 (source,
00140                  threading ?
00141                  OggVorbisFileReader::DecodeThreaded :
00142                  OggVorbisFileReader::DecodeAtOnce,
00143                  OggVorbisFileReader::CacheInTemporaryFile,
00144                  targetRate,
00145                  normalised,
00146                  reporter);
00147             if (!reader->isOK()) {
00148                 delete reader;
00149                 reader = 0;
00150             }
00151         }
00152     }
00153 #endif
00154 #endif
00155 
00156 #ifdef HAVE_MAD
00157     if (!reader) {
00158         if (MP3FileReader::supports(source)) {
00159             reader = new MP3FileReader
00160                 (source,
00161                  threading ?
00162                  MP3FileReader::DecodeThreaded :
00163                  MP3FileReader::DecodeAtOnce,
00164                  MP3FileReader::CacheInTemporaryFile,
00165                  targetRate,
00166                  normalised,
00167                  reporter);
00168             if (!reader->isOK()) {
00169                 delete reader;
00170                 reader = 0;
00171             }
00172         }
00173     }
00174 #endif
00175 
00176 #ifdef HAVE_QUICKTIME
00177     if (!reader) {
00178         if (QuickTimeFileReader::supports(source)) {
00179             reader = new QuickTimeFileReader
00180                 (source,
00181                  threading ?
00182                  QuickTimeFileReader::DecodeThreaded : 
00183                  QuickTimeFileReader::DecodeAtOnce,
00184                  QuickTimeFileReader::CacheInTemporaryFile,
00185                  targetRate,
00186                  normalised,
00187                  reporter);
00188             if (!reader->isOK()) {
00189                 delete reader;
00190                 reader = 0;
00191             }
00192         }
00193     }
00194 #endif
00195 
00196 #ifdef HAVE_COREAUDIO
00197     if (!reader) {
00198         if (CoreAudioFileReader::supports(source)) {
00199             reader = new CoreAudioFileReader
00200                 (source,
00201                  threading ?
00202                  CoreAudioFileReader::DecodeThreaded :
00203                  CoreAudioFileReader::DecodeAtOnce,
00204                  CoreAudioFileReader::CacheInTemporaryFile,
00205                  targetRate,
00206                  normalised,
00207                  reporter);
00208             if (!reader->isOK()) {
00209                 delete reader;
00210                 reader = 0;
00211             }
00212         }
00213     }
00214 #endif
00215 
00216 
00217     // If none of the readers claimed to support this file extension,
00218     // perhaps the extension is missing or misleading.  Try again,
00219     // ignoring it.  We have to be confident that the reader won't
00220     // open just any old text file or whatever and pretend it's
00221     // succeeded
00222 
00223     if (!reader) {
00224 
00225         reader = new WavFileReader(source);
00226 
00227         int fileRate = reader->getSampleRate();
00228 
00229         if (reader->isOK() &&
00230             (!reader->isQuicklySeekable() ||
00231              normalised ||
00232              (targetRate != 0 && fileRate != targetRate))) {
00233 
00234             SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl;
00235 
00236             delete reader;
00237             reader = new DecodingWavFileReader
00238                 (source,
00239                  threading ?
00240                  DecodingWavFileReader::ResampleThreaded :
00241                  DecodingWavFileReader::ResampleAtOnce,
00242                  DecodingWavFileReader::CacheInTemporaryFile,
00243                  targetRate ? targetRate : fileRate,
00244                  normalised,
00245                  reporter);
00246         }
00247 
00248         if (!reader->isOK()) {
00249             delete reader;
00250             reader = 0;
00251         }
00252     }
00253     
00254 #ifdef HAVE_OGGZ
00255 #ifdef HAVE_FISHSOUND
00256     if (!reader) {
00257         reader = new OggVorbisFileReader
00258             (source,
00259              threading ?
00260              OggVorbisFileReader::DecodeThreaded :
00261              OggVorbisFileReader::DecodeAtOnce,
00262              OggVorbisFileReader::CacheInTemporaryFile,
00263              targetRate,
00264              reporter);
00265 
00266         if (!reader->isOK()) {
00267             delete reader;
00268             reader = 0;
00269         }
00270     }
00271 #endif
00272 #endif
00273 
00274 #ifdef HAVE_MAD
00275     if (!reader) {
00276         reader = new MP3FileReader
00277             (source,
00278              threading ?
00279              MP3FileReader::DecodeThreaded :
00280              MP3FileReader::DecodeAtOnce,
00281              MP3FileReader::CacheInTemporaryFile,
00282              targetRate,
00283              reporter);
00284 
00285         if (!reader->isOK()) {
00286             delete reader;
00287             reader = 0;
00288         }
00289     }
00290 #endif
00291 
00292 #ifdef HAVE_QUICKTIME
00293     if (!reader) {
00294         reader = new QuickTimeFileReader
00295             (source,
00296              threading ?
00297              QuickTimeFileReader::DecodeThreaded : 
00298              QuickTimeFileReader::DecodeAtOnce,
00299              QuickTimeFileReader::CacheInTemporaryFile,
00300              targetRate,
00301              reporter);
00302 
00303         if (!reader->isOK()) {
00304             delete reader;
00305             reader = 0;
00306         }
00307     }
00308 #endif
00309 
00310 #ifdef HAVE_COREAUDIO
00311     if (!reader) {
00312         reader = new CoreAudioFileReader
00313             (source,
00314              threading ?
00315              CoreAudioFileReader::DecodeThreaded :
00316              CoreAudioFileReader::DecodeAtOnce,
00317              CoreAudioFileReader::CacheInTemporaryFile,
00318              targetRate,
00319              reporter);
00320 
00321         if (!reader->isOK()) {
00322             delete reader;
00323             reader = 0;
00324         }
00325     }
00326 #endif
00327 
00328     if (reader) {
00329         if (reader->isOK()) {
00330             SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl;
00331             return reader;
00332         }
00333         cerr << "AudioFileReaderFactory: Preferred reader for "
00334                   << "url \"" << source.getLocation()
00335                   << "\" (content type \""
00336                   << source.getContentType() << "\") failed";
00337 
00338         if (reader->getError() != "") {
00339             cerr << ": \"" << reader->getError() << "\"";
00340         }
00341         cerr << endl;
00342         delete reader;
00343         reader = 0;
00344     }
00345 
00346     cerr << "AudioFileReaderFactory: No reader" << endl;
00347     return reader;
00348 }
00349