From ec86c487e8002b50dabcf2e27ac841a70e08e8a1 Mon Sep 17 00:00:00 2001 From: Scott Wheeler Date: Thu, 21 Jul 2005 17:45:23 +0000 Subject: [PATCH] Add a mechanism for extending the file type resolution in JuK using FileRefs. This is generally much better thought out than the current method of creating FileRefs using the native mime system and also allows for extension to additional file formats. git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@437382 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- fileref.cpp | 8 +++++ fileref.h | 75 +++++++++++++++++++++++++++++++----------- tests/toolkit-test.cpp | 2 +- toolkit/tlist.h | 3 ++ toolkit/tlist.tcc | 16 +++++++++ 5 files changed, 84 insertions(+), 20 deletions(-) diff --git a/fileref.cpp b/fileref.cpp index 2da2e71f..6c12749d 100644 --- a/fileref.cpp +++ b/fileref.cpp @@ -39,8 +39,11 @@ public: } File *file; + static List fileTypeResolvers; }; +List FileRef::FileRefPrivate::fileTypeResolvers; + //////////////////////////////////////////////////////////////////////////////// // public members //////////////////////////////////////////////////////////////////////////////// @@ -92,6 +95,11 @@ bool FileRef::save() return d->file->save(); } +void FileRef::addFileTypeResolver(const FileTypeResolver *resolver) // static +{ + FileRefPrivate::fileTypeResolvers.prepend(resolver); +} + bool FileRef::isNull() const { return !d->file || !d->file->isValid(); diff --git a/fileref.h b/fileref.h index ffa7864f..b4e64eea 100644 --- a/fileref.h +++ b/fileref.h @@ -43,32 +43,61 @@ namespace TagLib { * across file types. * * Also note that it is probably a good idea to plug this into your mime - * type system rather than using the constructor that accepts a file name. + * type system rather than using the constructor that accepts a file name using + * the FileTypeResolver. * - * For example in KDE this could be done with: - * - * \code - * - * TagLib::FileRef createFileRef( const QString &fileName ) - * { - * KMimeType::Ptr result = KMimeType::findByPath( fileName, 0, true ); - * - * if( result->name() == "audio/x-mp3" ) - * return FileRef( new MPEG::File( QFile::encodeName( fileName ).data() ) ); - * - * if( result->name() == "application/ogg" ) - * return FileRef( new Vorbis::File( QFile::encodeName( fileName ).data() ) ); - * - * return FileRef( 0 ); - * } - * - * \endcode + * \see FileTypeResolver + * \see addFileTypeResolver() */ class FileRef { public: + //! A class for pluggable file type resolution. + + /*! + * This class is used to add extend TagLib's very basic file name based file + * type resolution. + * + * This can be accomplished with: + * + * \code + * + * class MyFileTypeResolver : FileTypeResolver + * { + * TagLib::File *createFile(const char *fileName) + * { + * if(someCheckForAnMP3File(fileName)) + * return new TagLib::MPEG::File(fileName); + * return 0; + * } + * } + * + * FileRef::addFileTypeResolver(new MyFileTypeResolver); + * + * \endcode + * + * Naturally a less contrived example would be slightly more complex. This + * can be used to plug in mime-type detection systems or to add new file types + * to TagLib. + */ + + class FileTypeResolver + { + public: + /*! + * This method must be overriden to provide an additional file type + * resolver. If the resolver is able to determine the file type it should + * return a valid File object; if not it should return 0. + * + * \note The created file is then owned by the FileRef and should not be + * deleted. Deletion will happen automatically when the FileRef passes + * out of scope. + */ + virtual File *createFile(const char *fileName) = 0; + }; + FileRef(); /*! @@ -139,6 +168,14 @@ namespace TagLib { */ bool save(); + /*! + * Adds a FileTypeResolver to the list of those used by TagLib. Each + * additional FileTypeResolver is added to the front of a list of resolvers + * that are tried. If the FileTypeResolver returns zero the next resolver + * is tried. + */ + static void addFileTypeResolver(const FileTypeResolver *resolver); + /*! * Returns true if the file (and as such other pointers) are null. */ diff --git a/tests/toolkit-test.cpp b/tests/toolkit-test.cpp index aa1042d2..e5b8ae3f 100644 --- a/tests/toolkit-test.cpp +++ b/tests/toolkit-test.cpp @@ -233,11 +233,11 @@ void testList() List l1; List l2; List l3; - l1.append(1); l1.append(2); l2.append(3); l2.append(4); l1.append(l2); + l1.prepend(1); l3.append(1); l3.append(2); l3.append(3); diff --git a/toolkit/tlist.h b/toolkit/tlist.h index 3ea7a669..371543a5 100644 --- a/toolkit/tlist.h +++ b/toolkit/tlist.h @@ -120,6 +120,9 @@ namespace TagLib { */ List &append(const List &l); + List &prepend(const T &item); + List &prepend(const List &l); + /*! * Clears the list. If auto deletion is enabled and this list contains a * pointer type the members are also deleted. diff --git a/toolkit/tlist.tcc b/toolkit/tlist.tcc index ae3f9a22..38a150a8 100644 --- a/toolkit/tlist.tcc +++ b/toolkit/tlist.tcc @@ -164,6 +164,22 @@ List &List::append(const List &l) return *this; } +template +List &List::prepend(const T &item) +{ + detach(); + d->list.push_front(item); + return *this; +} + +template +List &List::prepend(const List &l) +{ + detach(); + d->list.insert(d->list.begin(), l.begin(), l.end()); + return *this; +} + template void List::clear() {