# HG changeset patch # User Chris Cannam # Date 1478256267 0 # Node ID 8e846c1aed96189f020024cdadd0d37bf69d3e3a # Parent 79a219ba617862adffd78925f1571e5c96760e0a# Parent 0545cd3f1738cb677fadd1672a6b6affaab84189 Merge from branch enumerate-options diff -r 79a219ba6178 -r 8e846c1aed96 src/vamp-hostsdk/Files.cpp --- a/src/vamp-hostsdk/Files.cpp Fri Oct 28 14:30:26 2016 +0100 +++ b/src/vamp-hostsdk/Files.cpp Fri Nov 04 10:44:27 2016 +0000 @@ -66,21 +66,25 @@ vector Files::listLibraryFiles() { - return listLibraryFilesMatching(""); + return listLibraryFilesMatching({}); } vector -Files::listLibraryFilesMatching(string libraryName) +Files::listLibraryFilesMatching(Filter filter) { vector path = Vamp::PluginHostAdapter::getPluginPath(); vector libraryFiles; // we match case-insensitively, but only with ascii range - // characters (this string is expected to be utf-8) - for (size_t i = 0; i < libraryName.length(); ++i) { - if (!(libraryName[i] & 0x80)) { - libraryName[i] = char(tolower(libraryName[i])); + // characters (input strings are expected to be utf-8) + vector libraryNames; + for (auto n: filter.libraryNames) { + for (size_t i = 0; i < n.length(); ++i) { + if (!(n[i] & 0x80)) { + n[i] = char(tolower(n[i])); + } } + libraryNames.push_back(n); } for (size_t i = 0; i < path.size(); ++i) { @@ -89,27 +93,53 @@ for (vector::iterator fi = files.begin(); fi != files.end(); ++fi) { - - if (libraryName != "") { - // we match case-insensitively, but only with ascii - // range characters (this string is expected to be - // utf-8) - string temp = *fi; - for (size_t i = 0; i < temp.length(); ++i) { - if (!(temp[i] & 0x80)) { - temp[i] = char(tolower(temp[i])); - } - } - // libraryName should be lacking an extension, as it - // is supposed to have come from the plugin key - string::size_type pi = temp.find('.'); - if (pi == string::npos) { - if (libraryName != temp) continue; - } else { - if (libraryName != temp.substr(0, pi)) continue; + + // we match case-insensitively, but only with ascii range + // characters (this string is expected to be utf-8) + string cleaned = *fi; + for (size_t i = 0; i < cleaned.length(); ++i) { + if (!(cleaned[i] & 0x80)) { + cleaned[i] = char(tolower(cleaned[i])); } } + // libraryName should be lacking an extension, as it is + // supposed to have come from the plugin key + string::size_type pi = cleaned.find('.'); + if (pi != string::npos) { + cleaned = cleaned.substr(0, pi); + } + + bool matched = false; + + switch (filter.type) { + + case Filter::All: + matched = true; + break; + + case Filter::Matching: + for (const auto &n: libraryNames) { + if (cleaned == n) { + matched = true; + break; + } + } + break; + + case Filter::NotMatching: + matched = true; + for (const auto &n: libraryNames) { + if (cleaned == n) { + matched = false; + break; + } + } + break; + } + + if (!matched) continue; + string fullPath = path[i]; fullPath = splicePath(fullPath, *fi); libraryFiles.push_back(fullPath); diff -r 79a219ba6178 -r 8e846c1aed96 src/vamp-hostsdk/Files.h --- a/src/vamp-hostsdk/Files.h Fri Oct 28 14:30:26 2016 +0100 +++ b/src/vamp-hostsdk/Files.h Fri Nov 04 10:44:27 2016 +0000 @@ -47,7 +47,13 @@ { public: static std::vector listLibraryFiles(); - static std::vector listLibraryFilesMatching(std::string libname); + + struct Filter { + enum { All, Matching, NotMatching } type; + std::vector libraryNames; + Filter() : type(All) { } + }; + static std::vector listLibraryFilesMatching(Filter); static void *loadLibrary(std::string filename); static void unloadLibrary(void *); diff -r 79a219ba6178 -r 8e846c1aed96 src/vamp-hostsdk/PluginLoader.cpp --- a/src/vamp-hostsdk/PluginLoader.cpp Fri Oct 28 14:30:26 2016 +0100 +++ b/src/vamp-hostsdk/PluginLoader.cpp Fri Nov 04 10:44:27 2016 +0000 @@ -61,6 +61,8 @@ virtual ~Impl(); PluginKeyList listPlugins(); + PluginKeyList listPluginsIn(vector); + PluginKeyList listPluginsNotIn(vector); Plugin *loadPlugin(PluginKey key, float inputSampleRate, @@ -96,7 +98,18 @@ map m_pluginLibraryNameMap; bool m_allPluginsEnumerated; - void enumeratePlugins(PluginKey forPlugin = ""); + + struct Enumeration { + enum { All, SinglePlugin, InLibraries, NotInLibraries } type; + PluginKey key; + vector libraryNames; + Enumeration() : type(All) { } + }; + vector listLibraryFilesFor(Enumeration); + + /// Populate m_pluginLibraryNameMap and return a list of the keys + /// that were added to it + vector enumeratePlugins(Enumeration); map m_taxonomy; void generateTaxonomy(); @@ -144,6 +157,18 @@ return m_impl->listPlugins(); } +PluginLoader::PluginKeyList +PluginLoader::listPluginsIn(vector libs) +{ + return m_impl->listPluginsIn(libs); +} + +PluginLoader::PluginKeyList +PluginLoader::listPluginsNotIn(vector 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 plugins; - for (map::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 libs) +{ + Enumeration enumeration; + enumeration.type = Enumeration::InLibraries; + enumeration.libraryNames = libs; + return enumeratePlugins(enumeration); +} + +PluginLoader::PluginKeyList +PluginLoader::Impl::listPluginsNotIn(vector libs) +{ + Enumeration enumeration; + enumeration.type = Enumeration::NotInLibraries; + enumeration.libraryNames = libs; + return enumeratePlugins(enumeration); +} + +vector +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::Impl::enumeratePlugins(Enumeration enumeration) { string libraryName, identifier; - vector 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 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 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 ""; diff -r 79a219ba6178 -r 8e846c1aed96 vamp-hostsdk/PluginLoader.h --- a/vamp-hostsdk/PluginLoader.h Fri Oct 28 14:30:26 2016 +0100 +++ b/vamp-hostsdk/PluginLoader.h Fri Nov 04 10:44:27 2016 +0000 @@ -128,6 +128,34 @@ PluginKeyList listPlugins(); /** + * Search for available Vamp plugins in libraries with the given + * library names, and return a list of them in the order in which + * they were found. Do not attempt to load any plugin libraries + * other than those named. + * + * The library names should be supplied without path or + * suffix. For example, use "vamp-example-plugins" to find plugins + * in /install/path/of/vamp-example-plugins.dll (or .so etc). This + * is the same concept of "library name" as appears in the plugin + * key: \see composePluginKey(). + */ + PluginKeyList listPluginsIn(std::vector libraryNames); + + /** + * Search for available Vamp plugins in libraries other than those + * with the given library names, and return a list of them in the + * order in which they were found. Do not attempt to load any of + * the libraries named. + * + * The library names should be supplied without path or + * suffix. For example, use "vamp-example-plugins" to find plugins + * not appearing in /install/path/of/vamp-example-plugins.dll (or + * .so etc). This is the same concept of "library name" as appears + * in the plugin key: \see composePluginKey(). + */ + PluginKeyList listPluginsNotIn(std::vector libraryNames); + + /** * AdapterFlags contains a set of values that may be OR'd together * to indicate in which circumstances PluginLoader should use a * plugin adapter to make a plugin easier to use for a host that