diff src/vamp-hostsdk/PluginLoader.cpp @ 473:0545cd3f1738 enumerate-options

Add plugin enumeration options (for use by piper server, needs testing)
author Chris Cannam
date Wed, 02 Nov 2016 14:22:20 +0000
parents a94ab90dfd53
children 628a5b8ff634
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginLoader.cpp	Fri Oct 28 14:30:26 2016 +0100
+++ b/src/vamp-hostsdk/PluginLoader.cpp	Wed Nov 02 14:22:20 2016 +0000
@@ -61,6 +61,8 @@
     virtual ~Impl();
 
     PluginKeyList listPlugins();
+    PluginKeyList listPluginsIn(vector<string>);
+    PluginKeyList listPluginsNotIn(vector<string>);
 
     Plugin *loadPlugin(PluginKey key,
                        float inputSampleRate,
@@ -96,7 +98,18 @@
 
     map<PluginKey, string> m_pluginLibraryNameMap;
     bool m_allPluginsEnumerated;
-    void enumeratePlugins(PluginKey forPlugin = "");
+
+    struct Enumeration {
+        enum { All, SinglePlugin, InLibraries, NotInLibraries } type;
+        PluginKey key;
+        vector<string> libraryNames;
+        Enumeration() : type(All) { }
+    };
+    vector<string> listLibraryFilesFor(Enumeration);
+
+    /// Populate m_pluginLibraryNameMap and return a list of the keys
+    /// that were added to it
+    vector<PluginKey> enumeratePlugins(Enumeration);
 
     map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
     void generateTaxonomy();
@@ -144,6 +157,18 @@
     return m_impl->listPlugins();
 }
 
+PluginLoader::PluginKeyList
+PluginLoader::listPluginsIn(vector<string> libs) 
+{
+    return m_impl->listPluginsIn(libs);
+}
+
+PluginLoader::PluginKeyList
+PluginLoader::listPluginsNotIn(vector<string> libs) 
+{
+    return m_impl->listPluginsNotIn(libs);
+}
+
 Plugin *
 PluginLoader::loadPlugin(PluginKey key,
                          float inputSampleRate,
@@ -188,34 +213,89 @@
 PluginLoader::PluginKeyList
 PluginLoader::Impl::listPlugins() 
 {
-    if (!m_allPluginsEnumerated) enumeratePlugins();
+    if (!m_allPluginsEnumerated) enumeratePlugins({});
 
     vector<PluginKey> plugins;
-    for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
-         mi != m_pluginLibraryNameMap.end(); ++mi) {
-        plugins.push_back(mi->first);
+    for (const auto &mi: m_pluginLibraryNameMap) {
+        plugins.push_back(mi.first);
     }
 
     return plugins;
 }
 
-void
-PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
+PluginLoader::PluginKeyList
+PluginLoader::Impl::listPluginsIn(vector<string> libs) 
+{
+    Enumeration enumeration;
+    enumeration.type = Enumeration::InLibraries;
+    enumeration.libraryNames = libs;
+    return enumeratePlugins(enumeration);
+}
+
+PluginLoader::PluginKeyList
+PluginLoader::Impl::listPluginsNotIn(vector<string> libs) 
+{
+    Enumeration enumeration;
+    enumeration.type = Enumeration::NotInLibraries;
+    enumeration.libraryNames = libs;
+    return enumeratePlugins(enumeration);
+}
+
+vector<string>
+PluginLoader::Impl::listLibraryFilesFor(Enumeration enumeration)
+{
+    Files::Filter filter;
+    
+    switch (enumeration.type) {
+
+    case Enumeration::All:
+        filter.type = Files::Filter::All;
+        break;
+
+    case Enumeration::SinglePlugin:
+    {
+        string libraryName, identifier;
+        if (!decomposePluginKey(enumeration.key, libraryName, identifier)) {
+            std::cerr << "WARNING: Vamp::HostExt::PluginLoader: "
+                      << "Invalid plugin key \"" << enumeration.key
+                      << "\" in enumerate" << std::endl;
+            return {};
+        }
+        filter.type = Files::Filter::Matching;
+        filter.libraryNames = { libraryName };
+        break;
+    }
+
+    case Enumeration::InLibraries:
+        filter.type = Files::Filter::Matching;
+        filter.libraryNames = enumeration.libraryNames;
+        break;
+
+    case Enumeration::NotInLibraries:
+        filter.type = Files::Filter::NotMatching;
+        filter.libraryNames = enumeration.libraryNames;
+        break;
+    }
+        
+    return Files::listLibraryFilesMatching(filter);
+}
+
+vector<PluginLoader::PluginKey>
+PluginLoader::Impl::enumeratePlugins(Enumeration enumeration)
 {
     string libraryName, identifier;
-    vector<string> fullPaths;
+    if (enumeration.type == Enumeration::SinglePlugin) {
+        decomposePluginKey(enumeration.key, libraryName, identifier);
+    }
     
-    if (forPlugin != "") {
-        if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
-            std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
-                      << forPlugin << "\" in enumerate" << std::endl;
-            return;
-        }
-        fullPaths = Files::listLibraryFilesMatching(libraryName);
-    } else {
-        fullPaths = Files::listLibraryFiles();
-    }
+    vector<string> fullPaths = listLibraryFilesFor(enumeration);
 
+    // For these we should warn if a plugin can be loaded from a library
+    bool specific = (enumeration.type == Enumeration::SinglePlugin ||
+                     enumeration.type == Enumeration::InLibraries);
+
+    vector<PluginKey> added;
+    
     for (size_t i = 0; i < fullPaths.size(); ++i) {
 
         string fullPath = fullPaths[i];
@@ -227,8 +307,9 @@
             (handle, "vampGetPluginDescriptor");
             
         if (!fn) {
-            if (forPlugin != "") {
-                cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \""
+            if (specific) {
+                cerr << "Vamp::HostExt::PluginLoader: "
+                    << "No vampGetPluginDescriptor function found in library \""
                      << fullPath << "\"" << endl;
             }
             Files::unloadLibrary(handle);
@@ -242,18 +323,20 @@
         while ((descriptor = fn(VAMP_API_VERSION, index))) {
             ++index;
             if (identifier != "") {
-                if (descriptor->identifier != identifier) continue;
+                if (descriptor->identifier != identifier) {
+                    continue;
+                }
             }
             found = true;
             PluginKey key = composePluginKey(fullPath, descriptor->identifier);
-//                std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
             if (m_pluginLibraryNameMap.find(key) ==
                 m_pluginLibraryNameMap.end()) {
                 m_pluginLibraryNameMap[key] = fullPath;
             }
+            added.push_back(key);
         }
 
-        if (!found && forPlugin != "") {
+        if (!found && specific) {
             cerr << "Vamp::HostExt::PluginLoader: Plugin \""
                  << identifier << "\" not found in library \""
                  << fullPath << "\"" << endl;
@@ -262,7 +345,11 @@
         Files::unloadLibrary(handle);
     }
 
-    if (forPlugin == "") m_allPluginsEnumerated = true;
+    if (enumeration.type == Enumeration::All) {
+        m_allPluginsEnumerated = true;
+    }
+
+    return added;
 }
 
 PluginLoader::PluginKey
@@ -302,7 +389,10 @@
 {
     if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
         if (m_allPluginsEnumerated) return "";
-        enumeratePlugins(plugin);
+        Enumeration enumeration;
+        enumeration.type = Enumeration::SinglePlugin;
+        enumeration.key = plugin;
+        enumeratePlugins(enumeration);
     }
     if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
         return "";