diff vamp-sdk/hostext/PluginLoader.cpp @ 72:65add4f460e9

* make PluginLoader quicker to load a single named plugin (don't always have to bother enumerating them all first)
author cannam
date Wed, 06 Jun 2007 12:20:16 +0000
parents 64697dca0d48
children 6d16c376fd2f
line wrap: on
line diff
--- a/vamp-sdk/hostext/PluginLoader.cpp	Wed Jun 06 10:02:37 2007 +0000
+++ b/vamp-sdk/hostext/PluginLoader.cpp	Wed Jun 06 12:20:16 2007 +0000
@@ -69,7 +69,8 @@
 class PluginLoader::Impl
 {
 public:
-    virtual ~Impl() { }
+    Impl();
+    virtual ~Impl();
 
     PluginKeyList listPlugins();
 
@@ -81,7 +82,7 @@
 
     PluginCategoryHierarchy getPluginCategory(PluginKey key);
 
-    std::string getLibraryPathForPlugin(PluginKey key);
+    string getLibraryPathForPlugin(PluginKey key);
 
 protected:
     class PluginDeletionNotifyAdapter : public PluginWrapper {
@@ -94,20 +95,24 @@
 
     virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
 
-    std::map<PluginKey, std::string> m_pluginLibraryNameMap;
-    void generateLibraryMap();
+    map<PluginKey, string> m_pluginLibraryNameMap;
+    bool m_allPluginsEnumerated;
+    void enumeratePlugins(PluginKey forPlugin = "");
 
-    std::map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
+    map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
     void generateTaxonomy();
 
-    std::map<Plugin *, void *> m_pluginLibraryHandleMap;
+    map<Plugin *, void *> m_pluginLibraryHandleMap;
 
-    void *loadLibrary(std::string path);
+    bool decomposePluginKey(PluginKey key,
+                            string &libraryName, string &identifier);
+
+    void *loadLibrary(string path);
     void unloadLibrary(void *handle);
     void *lookupInLibrary(void *handle, const char *symbol);
 
-    std::string splicePath(std::string a, std::string b);
-    std::vector<std::string> listFiles(std::string dir, std::string ext);
+    string splicePath(string a, string b);
+    vector<string> listFiles(string dir, string ext);
 };
 
 PluginLoader *
@@ -161,15 +166,23 @@
 {
     return m_impl->getLibraryPathForPlugin(key);
 }
+ 
+PluginLoader::Impl::Impl() :
+    m_allPluginsEnumerated(false)
+{
+}
+
+PluginLoader::Impl::~Impl()
+{
+}
 
 vector<PluginLoader::PluginKey>
 PluginLoader::Impl::listPlugins() 
 {
-    if (m_pluginLibraryNameMap.empty()) generateLibraryMap();
+    if (!m_allPluginsEnumerated) enumeratePlugins();
 
     vector<PluginKey> plugins;
-    for (map<PluginKey, string>::iterator mi =
-             m_pluginLibraryNameMap.begin();
+    for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
          mi != m_pluginLibraryNameMap.end(); ++mi) {
         plugins.push_back(mi->first);
     }
@@ -178,10 +191,19 @@
 }
 
 void
-PluginLoader::Impl::generateLibraryMap()
+PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
 {
     vector<string> path = PluginHostAdapter::getPluginPath();
 
+    string libraryName, identifier;
+    if (forPlugin != "") {
+        if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
+            std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
+                      << forPlugin << "\" in enumerate" << std::endl;
+            return;
+        }
+    }
+
     for (size_t i = 0; i < path.size(); ++i) {
         
         vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
@@ -189,6 +211,15 @@
         for (vector<string>::iterator fi = files.begin();
              fi != files.end(); ++fi) {
             
+            if (libraryName != "") {
+                string::size_type pi = fi->find('.');
+                if (pi == string::npos) {
+                    if (libraryName != *fi) continue;
+                } else {
+                    if (libraryName != fi->substr(0, pi)) continue;
+                }
+            }
+
             string fullPath = path[i];
             fullPath = splicePath(fullPath, *fi);
             void *handle = loadLibrary(fullPath);
@@ -207,22 +238,30 @@
             const VampPluginDescriptor *descriptor = 0;
             
             while ((descriptor = fn(VAMP_API_VERSION, index))) {
+                ++index;
+                if (identifier != "") {
+                    if (descriptor->identifier != identifier) continue;
+                }
                 PluginKey key = composePluginKey(*fi, descriptor->identifier);
+//                std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
                 if (m_pluginLibraryNameMap.find(key) ==
                     m_pluginLibraryNameMap.end()) {
                     m_pluginLibraryNameMap[key] = fullPath;
                 }
-                ++index;
             }
             
             unloadLibrary(handle);
         }
     }
+
+    if (forPlugin == "") m_allPluginsEnumerated = true;
 }
 
 PluginLoader::PluginKey
 PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
 {
+    //!!! deal with case issues
+    
     string basename = libraryName;
 
     string::size_type li = basename.rfind('/');
@@ -234,6 +273,21 @@
     return basename + ":" + identifier;
 }
 
+bool
+PluginLoader::Impl::decomposePluginKey(PluginKey key,
+                                       string &libraryName,
+                                       string &identifier)
+{
+    string::size_type ki = key.find(':');
+    if (ki == string::npos) {
+        return false;
+    }
+
+    libraryName = key.substr(0, ki);
+    identifier = key.substr(ki + 1);
+    return true;
+}
+
 PluginLoader::PluginCategoryHierarchy
 PluginLoader::Impl::getPluginCategory(PluginKey plugin)
 {
@@ -247,8 +301,13 @@
 string
 PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
 {
-    if (m_pluginLibraryNameMap.empty()) generateLibraryMap();
-    if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) return "";
+    if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+        if (m_allPluginsEnumerated) return "";
+        enumeratePlugins(plugin);
+    }
+    if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
+        return "";
+    }
     return m_pluginLibraryNameMap[plugin];
 }    
 
@@ -256,17 +315,16 @@
 PluginLoader::Impl::loadPlugin(PluginKey key,
                                float inputSampleRate, int adapterFlags)
 {
+    string libname, identifier;
+    if (!decomposePluginKey(key, libname, identifier)) {
+        std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
+                  << key << "\" in loadPlugin" << std::endl;
+        return 0;
+    }
+        
     string fullPath = getLibraryPathForPlugin(key);
     if (fullPath == "") return 0;
     
-    string::size_type ki = key.find(':');
-    if (ki == string::npos) {
-        //!!! flag error
-        return 0;
-    }
-
-    string identifier = key.substr(ki + 1);
-    
     void *handle = loadLibrary(fullPath);
     if (!handle) return 0;