Chris@386: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@386: Chris@386: /* Chris@386: Sonic Visualiser Chris@386: An audio file viewer and annotation editor. Chris@386: Centre for Digital Music, Queen Mary, University of London. Chris@386: This file copyright 2006 Chris Cannam and QMUL. Chris@386: Chris@386: This program is free software; you can redistribute it and/or Chris@386: modify it under the terms of the GNU General Public License as Chris@386: published by the Free Software Foundation; either version 2 of the Chris@386: License, or (at your option) any later version. See the file Chris@386: COPYING included with this distribution for more information. Chris@386: */ Chris@386: Chris@386: #include "AudioFileReaderFactory.h" Chris@386: Chris@386: #include "WavFileReader.h" Chris@823: #include "DecodingWavFileReader.h" Chris@386: #include "OggVorbisFileReader.h" Chris@386: #include "MP3FileReader.h" Chris@386: #include "QuickTimeFileReader.h" luisf@665: #include "CoreAudioFileReader.h" Chris@386: Chris@386: #include Chris@386: #include Chris@386: #include Chris@386: Chris@386: QString Chris@386: AudioFileReaderFactory::getKnownExtensions() Chris@386: { Chris@386: std::set extensions; Chris@386: Chris@386: WavFileReader::getSupportedExtensions(extensions); Chris@386: #ifdef HAVE_MAD Chris@386: MP3FileReader::getSupportedExtensions(extensions); Chris@386: #endif Chris@386: #ifdef HAVE_OGGZ Chris@386: #ifdef HAVE_FISHSOUND Chris@386: OggVorbisFileReader::getSupportedExtensions(extensions); Chris@386: #endif Chris@386: #endif Chris@386: #ifdef HAVE_QUICKTIME Chris@386: QuickTimeFileReader::getSupportedExtensions(extensions); Chris@386: #endif luisf@665: #ifdef HAVE_COREAUDIO luisf@665: CoreAudioFileReader::getSupportedExtensions(extensions); luisf@665: #endif Chris@386: Chris@386: QString rv; Chris@386: for (std::set::const_iterator i = extensions.begin(); Chris@386: i != extensions.end(); ++i) { Chris@386: if (i != extensions.begin()) rv += " "; Chris@386: rv += "*." + *i; Chris@386: } Chris@386: Chris@386: return rv; Chris@386: } Chris@386: Chris@386: AudioFileReader * Chris@920: AudioFileReaderFactory::createReader(FileSource source, Chris@1040: sv_samplerate_t targetRate, Chris@920: bool normalised, Chris@392: ProgressReporter *reporter) Chris@386: { Chris@920: return create(source, targetRate, normalised, false, reporter); Chris@386: } Chris@386: Chris@386: AudioFileReader * Chris@920: AudioFileReaderFactory::createThreadingReader(FileSource source, Chris@1040: sv_samplerate_t targetRate, Chris@920: bool normalised, Chris@392: ProgressReporter *reporter) Chris@386: { Chris@920: return create(source, targetRate, normalised, true, reporter); Chris@386: } Chris@386: Chris@386: AudioFileReader * Chris@920: AudioFileReaderFactory::create(FileSource source, Chris@1040: sv_samplerate_t targetRate, Chris@920: bool normalised, Chris@920: bool threading, Chris@392: ProgressReporter *reporter) Chris@386: { Chris@386: QString err; Chris@386: Chris@742: SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\"): Requested rate: " << targetRate << endl; Chris@386: Chris@667: if (!source.isOK()) { Chris@843: cerr << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Failed to retrieve source (transmission error?): " << source.getErrorString() << endl; Chris@667: return 0; Chris@667: } Chris@667: Chris@667: if (!source.isAvailable()) { Chris@690: SVDEBUG << "AudioFileReaderFactory::createReader(\"" << source.getLocation() << "\": Source not found" << endl; Chris@386: return 0; Chris@386: } Chris@386: Chris@386: AudioFileReader *reader = 0; Chris@386: Chris@386: // Try to construct a preferred reader based on the extension or Chris@386: // MIME type. Chris@386: Chris@386: if (WavFileReader::supports(source)) { Chris@386: Chris@386: reader = new WavFileReader(source); Chris@386: Chris@1040: sv_samplerate_t fileRate = reader->getSampleRate(); Chris@386: Chris@823: if (reader->isOK() && Chris@823: (!reader->isQuicklySeekable() || Chris@920: normalised || Chris@823: (targetRate != 0 && fileRate != targetRate))) { Chris@823: Chris@920: SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl; Chris@386: Chris@386: delete reader; Chris@823: reader = new DecodingWavFileReader Chris@386: (source, Chris@386: threading ? Chris@823: DecodingWavFileReader::ResampleThreaded : Chris@823: DecodingWavFileReader::ResampleAtOnce, Chris@823: DecodingWavFileReader::CacheInTemporaryFile, Chris@823: targetRate ? targetRate : fileRate, Chris@920: normalised, Chris@392: reporter); Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@386: } Chris@386: } Chris@386: Chris@386: #ifdef HAVE_OGGZ Chris@386: #ifdef HAVE_FISHSOUND Chris@386: if (!reader) { Chris@386: if (OggVorbisFileReader::supports(source)) { Chris@386: reader = new OggVorbisFileReader Chris@386: (source, Chris@386: threading ? Chris@386: OggVorbisFileReader::DecodeThreaded : Chris@386: OggVorbisFileReader::DecodeAtOnce, Chris@386: OggVorbisFileReader::CacheInTemporaryFile, Chris@392: targetRate, Chris@920: normalised, Chris@392: reporter); Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@386: } Chris@386: } Chris@386: #endif Chris@386: #endif Chris@386: Chris@386: #ifdef HAVE_MAD Chris@386: if (!reader) { Chris@386: if (MP3FileReader::supports(source)) { Chris@386: reader = new MP3FileReader Chris@386: (source, Chris@386: threading ? Chris@386: MP3FileReader::DecodeThreaded : Chris@386: MP3FileReader::DecodeAtOnce, Chris@386: MP3FileReader::CacheInTemporaryFile, Chris@392: targetRate, Chris@920: normalised, Chris@392: reporter); Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@386: } Chris@386: } Chris@386: #endif Chris@386: Chris@386: #ifdef HAVE_QUICKTIME Chris@386: if (!reader) { Chris@386: if (QuickTimeFileReader::supports(source)) { Chris@386: reader = new QuickTimeFileReader Chris@386: (source, Chris@386: threading ? Chris@386: QuickTimeFileReader::DecodeThreaded : Chris@386: QuickTimeFileReader::DecodeAtOnce, Chris@386: QuickTimeFileReader::CacheInTemporaryFile, Chris@392: targetRate, Chris@920: normalised, Chris@392: reporter); Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@440: } Chris@440: } Chris@440: #endif Chris@440: luisf@665: #ifdef HAVE_COREAUDIO luisf@665: if (!reader) { luisf@665: if (CoreAudioFileReader::supports(source)) { luisf@665: reader = new CoreAudioFileReader luisf@665: (source, luisf@665: threading ? luisf@665: CoreAudioFileReader::DecodeThreaded : luisf@665: CoreAudioFileReader::DecodeAtOnce, luisf@665: CoreAudioFileReader::CacheInTemporaryFile, luisf@665: targetRate, Chris@920: normalised, luisf@665: reporter); luisf@665: if (!reader->isOK()) { luisf@665: delete reader; luisf@665: reader = 0; luisf@665: } luisf@665: } luisf@665: } luisf@665: #endif luisf@665: luisf@665: Chris@440: // If none of the readers claimed to support this file extension, Chris@440: // perhaps the extension is missing or misleading. Try again, Chris@440: // ignoring it. We have to be confident that the reader won't Chris@440: // open just any old text file or whatever and pretend it's Chris@440: // succeeded Chris@440: Chris@440: if (!reader) { Chris@440: Chris@440: reader = new WavFileReader(source); Chris@440: Chris@1040: sv_samplerate_t fileRate = reader->getSampleRate(); Chris@440: Chris@823: if (reader->isOK() && Chris@823: (!reader->isQuicklySeekable() || Chris@920: normalised || Chris@823: (targetRate != 0 && fileRate != targetRate))) { Chris@823: Chris@920: SVDEBUG << "AudioFileReaderFactory::createReader: WAV file rate: " << reader->getSampleRate() << ", normalised " << normalised << ", seekable " << reader->isQuicklySeekable() << ", creating decoding reader" << endl; Chris@440: Chris@440: delete reader; Chris@823: reader = new DecodingWavFileReader Chris@440: (source, Chris@440: threading ? Chris@823: DecodingWavFileReader::ResampleThreaded : Chris@823: DecodingWavFileReader::ResampleAtOnce, Chris@823: DecodingWavFileReader::CacheInTemporaryFile, Chris@823: targetRate ? targetRate : fileRate, Chris@920: normalised, Chris@440: reporter); Chris@440: } Chris@440: Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@440: } Chris@440: Chris@440: #ifdef HAVE_OGGZ Chris@440: #ifdef HAVE_FISHSOUND Chris@440: if (!reader) { Chris@440: reader = new OggVorbisFileReader Chris@440: (source, Chris@440: threading ? Chris@440: OggVorbisFileReader::DecodeThreaded : Chris@440: OggVorbisFileReader::DecodeAtOnce, Chris@440: OggVorbisFileReader::CacheInTemporaryFile, Chris@440: targetRate, Chris@440: reporter); Chris@440: Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@440: } Chris@440: #endif Chris@440: #endif Chris@440: Chris@440: #ifdef HAVE_MAD Chris@440: if (!reader) { Chris@440: reader = new MP3FileReader Chris@440: (source, Chris@440: threading ? Chris@440: MP3FileReader::DecodeThreaded : Chris@440: MP3FileReader::DecodeAtOnce, Chris@440: MP3FileReader::CacheInTemporaryFile, Chris@440: targetRate, Chris@440: reporter); Chris@440: Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@440: } Chris@440: } Chris@440: #endif Chris@440: Chris@440: #ifdef HAVE_QUICKTIME Chris@440: if (!reader) { Chris@440: reader = new QuickTimeFileReader Chris@440: (source, Chris@440: threading ? Chris@440: QuickTimeFileReader::DecodeThreaded : Chris@440: QuickTimeFileReader::DecodeAtOnce, Chris@440: QuickTimeFileReader::CacheInTemporaryFile, Chris@440: targetRate, Chris@440: reporter); Chris@440: Chris@440: if (!reader->isOK()) { Chris@440: delete reader; Chris@440: reader = 0; Chris@386: } Chris@386: } Chris@386: #endif Chris@386: luisf@665: #ifdef HAVE_COREAUDIO luisf@665: if (!reader) { luisf@665: reader = new CoreAudioFileReader luisf@665: (source, luisf@665: threading ? luisf@665: CoreAudioFileReader::DecodeThreaded : luisf@665: CoreAudioFileReader::DecodeAtOnce, luisf@665: CoreAudioFileReader::CacheInTemporaryFile, luisf@665: targetRate, luisf@665: reporter); luisf@665: luisf@665: if (!reader->isOK()) { luisf@665: delete reader; luisf@665: reader = 0; luisf@665: } luisf@665: } luisf@665: #endif luisf@665: Chris@386: if (reader) { Chris@386: if (reader->isOK()) { Chris@756: SVDEBUG << "AudioFileReaderFactory: Reader is OK" << endl; Chris@386: return reader; Chris@386: } Chris@843: cerr << "AudioFileReaderFactory: Preferred reader for " Chris@844: << "url \"" << source.getLocation() Chris@386: << "\" (content type \"" Chris@686: << source.getContentType() << "\") failed"; Chris@386: Chris@386: if (reader->getError() != "") { Chris@843: cerr << ": \"" << reader->getError() << "\""; Chris@386: } Chris@843: cerr << endl; Chris@386: delete reader; Chris@386: reader = 0; Chris@386: } Chris@386: Chris@843: cerr << "AudioFileReaderFactory: No reader" << endl; Chris@386: return reader; Chris@386: } Chris@386: