cannam@0: cannam@0: cannam@0: VampPluginSDK: PluginLoader.cpp Source File cannam@0: cannam@0: cannam@0: cannam@0: cannam@0: cannam@0: cannam@0:

PluginLoader.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: */
cannam@0: 00002 
cannam@0: 00003 /*
cannam@0: 00004     Vamp
cannam@0: 00005 
cannam@0: 00006     An API for audio analysis and feature extraction plugins.
cannam@0: 00007 
cannam@0: 00008     Centre for Digital Music, Queen Mary, University of London.
cannam@0: 00009     Copyright 2006-2007 Chris Cannam and QMUL.
cannam@0: 00010   
cannam@0: 00011     Permission is hereby granted, free of charge, to any person
cannam@0: 00012     obtaining a copy of this software and associated documentation
cannam@0: 00013     files (the "Software"), to deal in the Software without
cannam@0: 00014     restriction, including without limitation the rights to use, copy,
cannam@0: 00015     modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@0: 00016     of the Software, and to permit persons to whom the Software is
cannam@0: 00017     furnished to do so, subject to the following conditions:
cannam@0: 00018 
cannam@0: 00019     The above copyright notice and this permission notice shall be
cannam@0: 00020     included in all copies or substantial portions of the Software.
cannam@0: 00021 
cannam@0: 00022     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@0: 00023     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@0: 00024     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@0: 00025     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@0: 00026     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@0: 00027     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@0: 00028     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@0: 00029 
cannam@0: 00030     Except as contained in this notice, the names of the Centre for
cannam@0: 00031     Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@0: 00032     shall not be used in advertising or otherwise to promote the sale,
cannam@0: 00033     use or other dealings in this Software without prior written
cannam@0: 00034     authorization.
cannam@0: 00035 */
cannam@0: 00036 
cannam@0: 00037 #include "vamp-sdk/PluginHostAdapter.h"
cannam@0: 00038 #include "PluginLoader.h"
cannam@0: 00039 #include "PluginInputDomainAdapter.h"
cannam@0: 00040 #include "PluginChannelAdapter.h"
cannam@0: 00041 #include "PluginBufferingAdapter.h"
cannam@0: 00042 
cannam@0: 00043 #include <fstream>
cannam@0: 00044 #include <cctype> // tolower
cannam@0: 00045 
cannam@0: 00046 #include <cstring>
cannam@0: 00047 
cannam@0: 00048 #ifdef _WIN32
cannam@0: 00049 
cannam@0: 00050 #include <windows.h>
cannam@0: 00051 #include <tchar.h>
cannam@0: 00052 #define PLUGIN_SUFFIX "dll"
cannam@0: 00053 
cannam@0: 00054 #else /* ! _WIN32 */
cannam@0: 00055 
cannam@0: 00056 #include <dirent.h>
cannam@0: 00057 #include <dlfcn.h>
cannam@0: 00058 
cannam@0: 00059 #ifdef __APPLE__
cannam@0: 00060 #define PLUGIN_SUFFIX "dylib"
cannam@0: 00061 #else /* ! __APPLE__ */
cannam@0: 00062 #define PLUGIN_SUFFIX "so"
cannam@0: 00063 #endif /* ! __APPLE__ */
cannam@0: 00064 
cannam@0: 00065 #endif /* ! _WIN32 */
cannam@0: 00066 
cannam@0: 00067 using namespace std;
cannam@0: 00068 
cannam@0: 00069 namespace Vamp {
cannam@0: 00070         
cannam@0: 00071 namespace HostExt {
cannam@0: 00072 
cannam@0: 00073 class PluginLoader::Impl
cannam@0: 00074 {
cannam@0: 00075 public:
cannam@0: 00076     Impl();
cannam@0: 00077     virtual ~Impl();
cannam@0: 00078 
cannam@0: 00079     PluginKeyList listPlugins();
cannam@0: 00080 
cannam@0: 00081     Plugin *loadPlugin(PluginKey key,
cannam@0: 00082                        float inputSampleRate,
cannam@0: 00083                        int adapterFlags);
cannam@0: 00084 
cannam@0: 00085     PluginKey composePluginKey(string libraryName, string identifier);
cannam@0: 00086 
cannam@0: 00087     PluginCategoryHierarchy getPluginCategory(PluginKey key);
cannam@0: 00088 
cannam@0: 00089     string getLibraryPathForPlugin(PluginKey key);
cannam@0: 00090 
cannam@0: 00091     static void setInstanceToClean(PluginLoader *instance);
cannam@0: 00092 
cannam@0: 00093 protected:
cannam@0: 00094     class PluginDeletionNotifyAdapter : public PluginWrapper {
cannam@0: 00095     public:
cannam@0: 00096         PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
cannam@0: 00097         virtual ~PluginDeletionNotifyAdapter();
cannam@0: 00098     protected:
cannam@0: 00099         Impl *m_loader;
cannam@0: 00100     };
cannam@0: 00101 
cannam@0: 00102     class InstanceCleaner {
cannam@0: 00103     public:
cannam@0: 00104         InstanceCleaner() : m_instance(0) { }
cannam@0: 00105         ~InstanceCleaner() { delete m_instance; }
cannam@0: 00106         void setInstance(PluginLoader *instance) { m_instance = instance; }
cannam@0: 00107     protected:
cannam@0: 00108         PluginLoader *m_instance;
cannam@0: 00109     };
cannam@0: 00110 
cannam@0: 00111     virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
cannam@0: 00112 
cannam@0: 00113     map<PluginKey, string> m_pluginLibraryNameMap;
cannam@0: 00114     bool m_allPluginsEnumerated;
cannam@0: 00115     void enumeratePlugins(PluginKey forPlugin = "");
cannam@0: 00116 
cannam@0: 00117     map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
cannam@0: 00118     void generateTaxonomy();
cannam@0: 00119 
cannam@0: 00120     map<Plugin *, void *> m_pluginLibraryHandleMap;
cannam@0: 00121 
cannam@0: 00122     bool decomposePluginKey(PluginKey key,
cannam@0: 00123                             string &libraryName, string &identifier);
cannam@0: 00124 
cannam@0: 00125     void *loadLibrary(string path);
cannam@0: 00126     void unloadLibrary(void *handle);
cannam@0: 00127     void *lookupInLibrary(void *handle, const char *symbol);
cannam@0: 00128 
cannam@0: 00129     string splicePath(string a, string b);
cannam@0: 00130     vector<string> listFiles(string dir, string ext);
cannam@0: 00131     
cannam@0: 00132     static InstanceCleaner m_cleaner;
cannam@0: 00133 };
cannam@0: 00134 
cannam@0: 00135 PluginLoader *
cannam@0: 00136 PluginLoader::m_instance = 0;
cannam@0: 00137 
cannam@0: 00138 PluginLoader::Impl::InstanceCleaner
cannam@0: 00139 PluginLoader::Impl::m_cleaner;
cannam@0: 00140 
cannam@0: 00141 PluginLoader::PluginLoader()
cannam@0: 00142 {
cannam@0: 00143     m_impl = new Impl();
cannam@0: 00144 }
cannam@0: 00145 
cannam@0: 00146 PluginLoader::~PluginLoader()
cannam@0: 00147 {
cannam@0: 00148     delete m_impl;
cannam@0: 00149 }
cannam@0: 00150 
cannam@0: 00151 PluginLoader *
cannam@0: 00152 PluginLoader::getInstance()
cannam@0: 00153 {
cannam@0: 00154     if (!m_instance) {
cannam@0: 00155         // The cleaner doesn't own the instance, because we leave the
cannam@0: 00156         // instance pointer in the base class for binary backwards
cannam@0: 00157         // compatibility reasons and to avoid waste
cannam@0: 00158         m_instance = new PluginLoader();
cannam@0: 00159         Impl::setInstanceToClean(m_instance);
cannam@0: 00160     }
cannam@0: 00161     return m_instance;
cannam@0: 00162 }
cannam@0: 00163 
cannam@0: 00164 vector<PluginLoader::PluginKey>
cannam@0: 00165 PluginLoader::listPlugins() 
cannam@0: 00166 {
cannam@0: 00167     return m_impl->listPlugins();
cannam@0: 00168 }
cannam@0: 00169 
cannam@0: 00170 Plugin *
cannam@0: 00171 PluginLoader::loadPlugin(PluginKey key,
cannam@0: 00172                          float inputSampleRate,
cannam@0: 00173                          int adapterFlags)
cannam@0: 00174 {
cannam@0: 00175     return m_impl->loadPlugin(key, inputSampleRate, adapterFlags);
cannam@0: 00176 }
cannam@0: 00177 
cannam@0: 00178 PluginLoader::PluginKey
cannam@0: 00179 PluginLoader::composePluginKey(string libraryName, string identifier) 
cannam@0: 00180 {
cannam@0: 00181     return m_impl->composePluginKey(libraryName, identifier);
cannam@0: 00182 }
cannam@0: 00183 
cannam@0: 00184 PluginLoader::PluginCategoryHierarchy
cannam@0: 00185 PluginLoader::getPluginCategory(PluginKey key)
cannam@0: 00186 {
cannam@0: 00187     return m_impl->getPluginCategory(key);
cannam@0: 00188 }
cannam@0: 00189 
cannam@0: 00190 string
cannam@0: 00191 PluginLoader::getLibraryPathForPlugin(PluginKey key)
cannam@0: 00192 {
cannam@0: 00193     return m_impl->getLibraryPathForPlugin(key);
cannam@0: 00194 }
cannam@0: 00195  
cannam@0: 00196 PluginLoader::Impl::Impl() :
cannam@0: 00197     m_allPluginsEnumerated(false)
cannam@0: 00198 {
cannam@0: 00199 }
cannam@0: 00200 
cannam@0: 00201 PluginLoader::Impl::~Impl()
cannam@0: 00202 {
cannam@0: 00203 }
cannam@0: 00204 
cannam@0: 00205 void
cannam@0: 00206 PluginLoader::Impl::setInstanceToClean(PluginLoader *instance)
cannam@0: 00207 {
cannam@0: 00208     m_cleaner.setInstance(instance);
cannam@0: 00209 }
cannam@0: 00210 
cannam@0: 00211 vector<PluginLoader::PluginKey>
cannam@0: 00212 PluginLoader::Impl::listPlugins() 
cannam@0: 00213 {
cannam@0: 00214     if (!m_allPluginsEnumerated) enumeratePlugins();
cannam@0: 00215 
cannam@0: 00216     vector<PluginKey> plugins;
cannam@0: 00217     for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
cannam@0: 00218          mi != m_pluginLibraryNameMap.end(); ++mi) {
cannam@0: 00219         plugins.push_back(mi->first);
cannam@0: 00220     }
cannam@0: 00221 
cannam@0: 00222     return plugins;
cannam@0: 00223 }
cannam@0: 00224 
cannam@0: 00225 void
cannam@0: 00226 PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
cannam@0: 00227 {
cannam@0: 00228     vector<string> path = PluginHostAdapter::getPluginPath();
cannam@0: 00229 
cannam@0: 00230     string libraryName, identifier;
cannam@0: 00231     if (forPlugin != "") {
cannam@0: 00232         if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
cannam@0: 00233             std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
cannam@0: 00234                       << forPlugin << "\" in enumerate" << std::endl;
cannam@0: 00235             return;
cannam@0: 00236         }
cannam@0: 00237     }
cannam@0: 00238 
cannam@0: 00239     for (size_t i = 0; i < path.size(); ++i) {
cannam@0: 00240         
cannam@0: 00241         vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
cannam@0: 00242 
cannam@0: 00243         for (vector<string>::iterator fi = files.begin();
cannam@0: 00244              fi != files.end(); ++fi) {
cannam@0: 00245             
cannam@0: 00246             if (libraryName != "") {
cannam@0: 00247                 // libraryName is lowercased and lacking an extension,
cannam@0: 00248                 // as it came from the plugin key
cannam@0: 00249                 string temp = *fi;
cannam@0: 00250                 for (size_t i = 0; i < temp.length(); ++i) {
cannam@0: 00251                     temp[i] = tolower(temp[i]);
cannam@0: 00252                 }
cannam@0: 00253                 string::size_type pi = temp.find('.');
cannam@0: 00254                 if (pi == string::npos) {
cannam@0: 00255                     if (libraryName != temp) continue;
cannam@0: 00256                 } else {
cannam@0: 00257                     if (libraryName != temp.substr(0, pi)) continue;
cannam@0: 00258                 }
cannam@0: 00259             }
cannam@0: 00260 
cannam@0: 00261             string fullPath = path[i];
cannam@0: 00262             fullPath = splicePath(fullPath, *fi);
cannam@0: 00263             void *handle = loadLibrary(fullPath);
cannam@0: 00264             if (!handle) continue;
cannam@0: 00265             
cannam@0: 00266             VampGetPluginDescriptorFunction fn =
cannam@0: 00267                 (VampGetPluginDescriptorFunction)lookupInLibrary
cannam@0: 00268                 (handle, "vampGetPluginDescriptor");
cannam@0: 00269             
cannam@0: 00270             if (!fn) {
cannam@0: 00271                 unloadLibrary(handle);
cannam@0: 00272                 continue;
cannam@0: 00273             }
cannam@0: 00274             
cannam@0: 00275             int index = 0;
cannam@0: 00276             const VampPluginDescriptor *descriptor = 0;
cannam@0: 00277             
cannam@0: 00278             while ((descriptor = fn(VAMP_API_VERSION, index))) {
cannam@0: 00279                 ++index;
cannam@0: 00280                 if (identifier != "") {
cannam@0: 00281                     if (descriptor->identifier != identifier) continue;
cannam@0: 00282                 }
cannam@0: 00283                 PluginKey key = composePluginKey(*fi, descriptor->identifier);
cannam@0: 00284 //                std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
cannam@0: 00285                 if (m_pluginLibraryNameMap.find(key) ==
cannam@0: 00286                     m_pluginLibraryNameMap.end()) {
cannam@0: 00287                     m_pluginLibraryNameMap[key] = fullPath;
cannam@0: 00288                 }
cannam@0: 00289             }
cannam@0: 00290             
cannam@0: 00291             unloadLibrary(handle);
cannam@0: 00292         }
cannam@0: 00293     }
cannam@0: 00294 
cannam@0: 00295     if (forPlugin == "") m_allPluginsEnumerated = true;
cannam@0: 00296 }
cannam@0: 00297 
cannam@0: 00298 PluginLoader::PluginKey
cannam@0: 00299 PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
cannam@0: 00300 {
cannam@0: 00301     string basename = libraryName;
cannam@0: 00302 
cannam@0: 00303     string::size_type li = basename.rfind('/');
cannam@0: 00304     if (li != string::npos) basename = basename.substr(li + 1);
cannam@0: 00305 
cannam@0: 00306     li = basename.find('.');
cannam@0: 00307     if (li != string::npos) basename = basename.substr(0, li);
cannam@0: 00308 
cannam@0: 00309     for (size_t i = 0; i < basename.length(); ++i) {
cannam@0: 00310         basename[i] = tolower(basename[i]);
cannam@0: 00311     }
cannam@0: 00312 
cannam@0: 00313     return basename + ":" + identifier;
cannam@0: 00314 }
cannam@0: 00315 
cannam@0: 00316 bool
cannam@0: 00317 PluginLoader::Impl::decomposePluginKey(PluginKey key,
cannam@0: 00318                                        string &libraryName,
cannam@0: 00319                                        string &identifier)
cannam@0: 00320 {
cannam@0: 00321     string::size_type ki = key.find(':');
cannam@0: 00322     if (ki == string::npos) {
cannam@0: 00323         return false;
cannam@0: 00324     }
cannam@0: 00325 
cannam@0: 00326     libraryName = key.substr(0, ki);
cannam@0: 00327     identifier = key.substr(ki + 1);
cannam@0: 00328     return true;
cannam@0: 00329 }
cannam@0: 00330 
cannam@0: 00331 PluginLoader::PluginCategoryHierarchy
cannam@0: 00332 PluginLoader::Impl::getPluginCategory(PluginKey plugin)
cannam@0: 00333 {
cannam@0: 00334     if (m_taxonomy.empty()) generateTaxonomy();
cannam@0: 00335     if (m_taxonomy.find(plugin) == m_taxonomy.end()) {
cannam@0: 00336         return PluginCategoryHierarchy();
cannam@0: 00337     }
cannam@0: 00338     return m_taxonomy[plugin];
cannam@0: 00339 }
cannam@0: 00340 
cannam@0: 00341 string
cannam@0: 00342 PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
cannam@0: 00343 {
cannam@0: 00344     if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
cannam@0: 00345         if (m_allPluginsEnumerated) return "";
cannam@0: 00346         enumeratePlugins(plugin);
cannam@0: 00347     }
cannam@0: 00348     if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
cannam@0: 00349         return "";
cannam@0: 00350     }
cannam@0: 00351     return m_pluginLibraryNameMap[plugin];
cannam@0: 00352 }    
cannam@0: 00353 
cannam@0: 00354 Plugin *
cannam@0: 00355 PluginLoader::Impl::loadPlugin(PluginKey key,
cannam@0: 00356                                float inputSampleRate, int adapterFlags)
cannam@0: 00357 {
cannam@0: 00358     string libname, identifier;
cannam@0: 00359     if (!decomposePluginKey(key, libname, identifier)) {
cannam@0: 00360         std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
cannam@0: 00361                   << key << "\" in loadPlugin" << std::endl;
cannam@0: 00362         return 0;
cannam@0: 00363     }
cannam@0: 00364         
cannam@0: 00365     string fullPath = getLibraryPathForPlugin(key);
cannam@0: 00366     if (fullPath == "") return 0;
cannam@0: 00367     
cannam@0: 00368     void *handle = loadLibrary(fullPath);
cannam@0: 00369     if (!handle) return 0;
cannam@0: 00370     
cannam@0: 00371     VampGetPluginDescriptorFunction fn =
cannam@0: 00372         (VampGetPluginDescriptorFunction)lookupInLibrary
cannam@0: 00373         (handle, "vampGetPluginDescriptor");
cannam@0: 00374 
cannam@0: 00375     if (!fn) {
cannam@0: 00376         unloadLibrary(handle);
cannam@0: 00377         return 0;
cannam@0: 00378     }
cannam@0: 00379 
cannam@0: 00380     int index = 0;
cannam@0: 00381     const VampPluginDescriptor *descriptor = 0;
cannam@0: 00382 
cannam@0: 00383     while ((descriptor = fn(VAMP_API_VERSION, index))) {
cannam@0: 00384 
cannam@0: 00385         if (string(descriptor->identifier) == identifier) {
cannam@0: 00386 
cannam@0: 00387             Vamp::PluginHostAdapter *plugin =
cannam@0: 00388                 new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
cannam@0: 00389 
cannam@0: 00390             Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this);
cannam@0: 00391 
cannam@0: 00392             m_pluginLibraryHandleMap[adapter] = handle;
cannam@0: 00393 
cannam@0: 00394             if (adapterFlags & ADAPT_INPUT_DOMAIN) {
cannam@0: 00395                 if (adapter->getInputDomain() == Plugin::FrequencyDomain) {
cannam@0: 00396                     adapter = new PluginInputDomainAdapter(adapter);
cannam@0: 00397                 }
cannam@0: 00398             }
cannam@0: 00399 
cannam@0: 00400             if (adapterFlags & ADAPT_BUFFER_SIZE) {
cannam@0: 00401                 adapter = new PluginBufferingAdapter(adapter);
cannam@0: 00402             }
cannam@0: 00403 
cannam@0: 00404             if (adapterFlags & ADAPT_CHANNEL_COUNT) {
cannam@0: 00405                 adapter = new PluginChannelAdapter(adapter);
cannam@0: 00406             }
cannam@0: 00407 
cannam@0: 00408             return adapter;
cannam@0: 00409         }
cannam@0: 00410 
cannam@0: 00411         ++index;
cannam@0: 00412     }
cannam@0: 00413 
cannam@0: 00414     cerr << "Vamp::HostExt::PluginLoader: Plugin \""
cannam@0: 00415          << identifier << "\" not found in library \""
cannam@0: 00416          << fullPath << "\"" << endl;
cannam@0: 00417 
cannam@0: 00418     return 0;
cannam@0: 00419 }
cannam@0: 00420 
cannam@0: 00421 void
cannam@0: 00422 PluginLoader::Impl::generateTaxonomy()
cannam@0: 00423 {
cannam@0: 00424 //    cerr << "PluginLoader::Impl::generateTaxonomy" << endl;
cannam@0: 00425 
cannam@0: 00426     vector<string> path = PluginHostAdapter::getPluginPath();
cannam@0: 00427     string libfragment = "/lib/";
cannam@0: 00428     vector<string> catpath;
cannam@0: 00429 
cannam@0: 00430     string suffix = "cat";
cannam@0: 00431 
cannam@0: 00432     for (vector<string>::iterator i = path.begin();
cannam@0: 00433          i != path.end(); ++i) {
cannam@0: 00434 
cannam@0: 00435         // It doesn't matter that we're using literal forward-slash in
cannam@0: 00436         // this bit, as it's only relevant if the path contains
cannam@0: 00437         // "/lib/", which is only meaningful and only plausible on
cannam@0: 00438         // systems with forward-slash delimiters
cannam@0: 00439         
cannam@0: 00440         string dir = *i;
cannam@0: 00441         string::size_type li = dir.find(libfragment);
cannam@0: 00442 
cannam@0: 00443         if (li != string::npos) {
cannam@0: 00444             catpath.push_back
cannam@0: 00445                 (dir.substr(0, li)
cannam@0: 00446                  + "/share/"
cannam@0: 00447                  + dir.substr(li + libfragment.length()));
cannam@0: 00448         }
cannam@0: 00449 
cannam@0: 00450         catpath.push_back(dir);
cannam@0: 00451     }
cannam@0: 00452 
cannam@0: 00453     char buffer[1024];
cannam@0: 00454 
cannam@0: 00455     for (vector<string>::iterator i = catpath.begin();
cannam@0: 00456          i != catpath.end(); ++i) {
cannam@0: 00457         
cannam@0: 00458         vector<string> files = listFiles(*i, suffix);
cannam@0: 00459 
cannam@0: 00460         for (vector<string>::iterator fi = files.begin();
cannam@0: 00461              fi != files.end(); ++fi) {
cannam@0: 00462 
cannam@0: 00463             string filepath = splicePath(*i, *fi);
cannam@0: 00464             ifstream is(filepath.c_str(), ifstream::in | ifstream::binary);
cannam@0: 00465 
cannam@0: 00466             if (is.fail()) {
cannam@0: 00467 //                cerr << "failed to open: " << filepath << endl;
cannam@0: 00468                 continue;
cannam@0: 00469             }
cannam@0: 00470 
cannam@0: 00471 //            cerr << "opened: " << filepath << endl;
cannam@0: 00472 
cannam@0: 00473             while (!!is.getline(buffer, 1024)) {
cannam@0: 00474 
cannam@0: 00475                 string line(buffer);
cannam@0: 00476 
cannam@0: 00477 //                cerr << "line = " << line << endl;
cannam@0: 00478 
cannam@0: 00479                 string::size_type di = line.find("::");
cannam@0: 00480                 if (di == string::npos) continue;
cannam@0: 00481 
cannam@0: 00482                 string id = line.substr(0, di);
cannam@0: 00483                 string encodedCat = line.substr(di + 2);
cannam@0: 00484 
cannam@0: 00485                 if (id.substr(0, 5) != "vamp:") continue;
cannam@0: 00486                 id = id.substr(5);
cannam@0: 00487 
cannam@0: 00488                 while (encodedCat.length() >= 1 &&
cannam@0: 00489                        encodedCat[encodedCat.length()-1] == '\r') {
cannam@0: 00490                     encodedCat = encodedCat.substr(0, encodedCat.length()-1);
cannam@0: 00491                 }
cannam@0: 00492 
cannam@0: 00493 //                cerr << "id = " << id << ", cat = " << encodedCat << endl;
cannam@0: 00494 
cannam@0: 00495                 PluginCategoryHierarchy category;
cannam@0: 00496                 string::size_type ai;
cannam@0: 00497                 while ((ai = encodedCat.find(" > ")) != string::npos) {
cannam@0: 00498                     category.push_back(encodedCat.substr(0, ai));
cannam@0: 00499                     encodedCat = encodedCat.substr(ai + 3);
cannam@0: 00500                 }
cannam@0: 00501                 if (encodedCat != "") category.push_back(encodedCat);
cannam@0: 00502 
cannam@0: 00503                 m_taxonomy[id] = category;
cannam@0: 00504             }
cannam@0: 00505         }
cannam@0: 00506     }
cannam@0: 00507 }    
cannam@0: 00508 
cannam@0: 00509 void *
cannam@0: 00510 PluginLoader::Impl::loadLibrary(string path)
cannam@0: 00511 {
cannam@0: 00512     void *handle = 0;
cannam@0: 00513 #ifdef _WIN32
cannam@0: 00514     handle = LoadLibrary(path.c_str());
cannam@0: 00515     if (!handle) {
cannam@0: 00516         cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
cannam@0: 00517              << path << "\"" << endl;
cannam@0: 00518     }
cannam@0: 00519 #else
cannam@0: 00520     handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL);
cannam@0: 00521     if (!handle) {
cannam@0: 00522         cerr << "Vamp::HostExt::PluginLoader: Unable to load library \""
cannam@0: 00523              << path << "\": " << dlerror() << endl;
cannam@0: 00524     }
cannam@0: 00525 #endif
cannam@0: 00526     return handle;
cannam@0: 00527 }
cannam@0: 00528 
cannam@0: 00529 void
cannam@0: 00530 PluginLoader::Impl::unloadLibrary(void *handle)
cannam@0: 00531 {
cannam@0: 00532 #ifdef _WIN32
cannam@0: 00533     FreeLibrary((HINSTANCE)handle);
cannam@0: 00534 #else
cannam@0: 00535     dlclose(handle);
cannam@0: 00536 #endif
cannam@0: 00537 }
cannam@0: 00538 
cannam@0: 00539 void *
cannam@0: 00540 PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol)
cannam@0: 00541 {
cannam@0: 00542 #ifdef _WIN32
cannam@0: 00543     return (void *)GetProcAddress((HINSTANCE)handle, symbol);
cannam@0: 00544 #else
cannam@0: 00545     return (void *)dlsym(handle, symbol);
cannam@0: 00546 #endif
cannam@0: 00547 }
cannam@0: 00548 
cannam@0: 00549 string
cannam@0: 00550 PluginLoader::Impl::splicePath(string a, string b)
cannam@0: 00551 {
cannam@0: 00552 #ifdef _WIN32
cannam@0: 00553     return a + "\\" + b;
cannam@0: 00554 #else
cannam@0: 00555     return a + "/" + b;
cannam@0: 00556 #endif
cannam@0: 00557 }
cannam@0: 00558 
cannam@0: 00559 vector<string>
cannam@0: 00560 PluginLoader::Impl::listFiles(string dir, string extension)
cannam@0: 00561 {
cannam@0: 00562     vector<string> files;
cannam@0: 00563 
cannam@0: 00564 #ifdef _WIN32
cannam@0: 00565 
cannam@0: 00566     string expression = dir + "\\*." + extension;
cannam@0: 00567     WIN32_FIND_DATA data;
cannam@0: 00568     HANDLE fh = FindFirstFile(expression.c_str(), &data);
cannam@0: 00569     if (fh == INVALID_HANDLE_VALUE) return files;
cannam@0: 00570 
cannam@0: 00571     bool ok = true;
cannam@0: 00572     while (ok) {
cannam@0: 00573         files.push_back(data.cFileName);
cannam@0: 00574         ok = FindNextFile(fh, &data);
cannam@0: 00575     }
cannam@0: 00576 
cannam@0: 00577     FindClose(fh);
cannam@0: 00578 
cannam@0: 00579 #else
cannam@0: 00580 
cannam@0: 00581     size_t extlen = extension.length();
cannam@0: 00582     DIR *d = opendir(dir.c_str());
cannam@0: 00583     if (!d) return files;
cannam@0: 00584             
cannam@0: 00585     struct dirent *e = 0;
cannam@0: 00586     while ((e = readdir(d))) {
cannam@0: 00587  
cannam@0: 00588         if (!e->d_name) continue;
cannam@0: 00589        
cannam@0: 00590         size_t len = strlen(e->d_name);
cannam@0: 00591         if (len < extlen + 2 ||
cannam@0: 00592             e->d_name + len - extlen - 1 != "." + extension) {
cannam@0: 00593             continue;
cannam@0: 00594         }
cannam@0: 00595 
cannam@0: 00596         files.push_back(e->d_name);
cannam@0: 00597     }
cannam@0: 00598 
cannam@0: 00599     closedir(d);
cannam@0: 00600 #endif
cannam@0: 00601 
cannam@0: 00602     return files;
cannam@0: 00603 }
cannam@0: 00604 
cannam@0: 00605 void
cannam@0: 00606 PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter)
cannam@0: 00607 {
cannam@0: 00608     void *handle = m_pluginLibraryHandleMap[adapter];
cannam@0: 00609     if (handle) unloadLibrary(handle);
cannam@0: 00610     m_pluginLibraryHandleMap.erase(adapter);
cannam@0: 00611 }
cannam@0: 00612 
cannam@0: 00613 PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin,
cannam@0: 00614                                                                              Impl *loader) :
cannam@0: 00615     PluginWrapper(plugin),
cannam@0: 00616     m_loader(loader)
cannam@0: 00617 {
cannam@0: 00618 }
cannam@0: 00619 
cannam@0: 00620 PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter()
cannam@0: 00621 {
cannam@0: 00622     // We need to delete the plugin before calling pluginDeleted, as
cannam@0: 00623     // the delete call may require calling through to the descriptor
cannam@0: 00624     // (for e.g. cleanup) but pluginDeleted may unload the required
cannam@0: 00625     // library for the call.  To prevent a double deletion when our
cannam@0: 00626     // parent's destructor runs (after this one), be sure to set
cannam@0: 00627     // m_plugin to 0 after deletion.
cannam@0: 00628     delete m_plugin;
cannam@0: 00629     m_plugin = 0;
cannam@0: 00630 
cannam@0: 00631     if (m_loader) m_loader->pluginDeleted(this);
cannam@0: 00632 }
cannam@0: 00633 
cannam@0: 00634 }
cannam@0: 00635 
cannam@0: 00636 }
cannam@0: 
cannam@0:
Generated on Wed Jul 9 11:36:07 2008 for VampPluginSDK by  cannam@0: cannam@0: doxygen 1.5.5
cannam@0: cannam@0: