using namespace TagLib;
- if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2")
+namespace
+{
+ typedef List<const FileRef::FileTypeResolver *> ResolverList;
+ ResolverList fileTypeResolvers;
+
+ // Templatized internal functions. T should be String or IOStream*.
+
+ template <typename T>
+ inline FileName toFileName(T arg)
+ {
+ debug("FileRef::toFileName<T>(): This version should never be called.");
+ return FileName(L"");
+ }
+
+ template <>
+ inline FileName toFileName<IOStream *>(IOStream *arg)
+ {
+ return arg->name();
+ }
+
+ template <>
+ inline FileName toFileName<FileName>(FileName arg)
+ {
+ return arg;
+ }
+
+ template <typename T>
+ inline File *resolveFileType(T arg, bool readProperties,
+ AudioProperties::ReadStyle style)
+ {
+ debug("FileRef::resolveFileType<T>(): This version should never be called.");
+ return 0;
+ }
+
+ template <>
+ inline File *resolveFileType<IOStream *>(IOStream *arg, bool readProperties,
+ AudioProperties::ReadStyle style)
+ {
+ return 0;
+ }
+
+ template <>
+ inline File *resolveFileType<FileName>(FileName arg, bool readProperties,
+ AudioProperties::ReadStyle style)
+ {
+ ResolverList::ConstIterator it = fileTypeResolvers.begin();
+ for(; it != fileTypeResolvers.end(); ++it) {
+ File *file = (*it)->createFile(arg, readProperties, style);
+ if(file)
+ return file;
+ }
+
+ return 0;
+ }
+
+ template <typename T>
+ File* createInternal(T arg, bool readAudioProperties,
+ AudioProperties::ReadStyle audioPropertiesStyle)
+ {
+ File *file = resolveFileType(arg, readAudioProperties, audioPropertiesStyle);
+ if(file)
+ return file;
+
+#ifdef _WIN32
+ const String s = toFileName(arg).toString();
+#else
+ const String s(toFileName(arg));
+#endif
+
+ String ext;
+ const int pos = s.rfind(".");
+ if(pos != -1)
+ ext = s.substr(pos + 1).upper();
+
+ // If this list is updated, the method defaultFileExtensions() should also be
+ // updated. However at some point that list should be created at the same time
+ // that a default file type resolver is created.
+
+ if(ext.isEmpty())
+ return 0;
+
+ if(ext == "MP3")
+ return new MPEG::File(arg, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
+ if(ext == "OGG")
+ return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "OGA") {
+ /* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
+ File *file = new Ogg::FLAC::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(file->isValid())
+ return file;
+ delete file;
+ return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
+ }
+ if(ext == "FLAC")
+ return new FLAC::File(arg, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
+ if(ext == "MPC")
+ return new MPC::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "WV")
+ return new WavPack::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "SPX")
+ return new Ogg::Speex::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "OPUS")
+ return new Ogg::Opus::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "TTA")
+ return new TrueAudio::File(arg, readAudioProperties, audioPropertiesStyle);
++ if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
+ return new MP4::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "WMA" || ext == "ASF")
+ return new ASF::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
+ return new RIFF::AIFF::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "WAV")
+ return new RIFF::WAV::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "APE")
+ return new APE::File(arg, readAudioProperties, audioPropertiesStyle);
+ // module, nst and wow are possible but uncommon extensions
+ if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
+ return new Mod::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "S3M")
+ return new S3M::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "IT")
+ return new IT::File(arg, readAudioProperties, audioPropertiesStyle);
+ if(ext == "XM")
+ return new XM::File(arg, readAudioProperties, audioPropertiesStyle);
+
+ return 0;
+ }
+}
+
class FileRef::FileRefPrivate : public RefCounter
{
public: