Mercurial > hg > vamp-plugin-sdk
diff src/vamp-hostsdk/PluginLoader.cpp @ 390:06988ce35ff0 vh
Initial draft of C API for plugin loading
author | Chris Cannam |
---|---|
date | Wed, 20 May 2015 16:12:18 +0100 |
parents | 9648ba9812d6 |
children | 8c45dee08a95 |
line wrap: on
line diff
--- a/src/vamp-hostsdk/PluginLoader.cpp Wed May 20 13:54:46 2015 +0100 +++ b/src/vamp-hostsdk/PluginLoader.cpp Wed May 20 16:12:18 2015 +0100 @@ -34,35 +34,17 @@ authorization. */ -#include <vamp-hostsdk/PluginHostAdapter.h> #include <vamp-hostsdk/PluginLoader.h> #include <vamp-hostsdk/PluginInputDomainAdapter.h> #include <vamp-hostsdk/PluginChannelAdapter.h> #include <vamp-hostsdk/PluginBufferingAdapter.h> +#include <vamp-hostsdk/PluginHostAdapter.h> + +#include <vamp/vamp.h> + +#include "Files.h" #include <fstream> -#include <cctype> // tolower - -#include <cstring> - -#ifdef _WIN32 - -#include <windows.h> -#include <tchar.h> -#define PLUGIN_SUFFIX "dll" - -#else /* ! _WIN32 */ - -#include <dirent.h> -#include <dlfcn.h> - -#ifdef __APPLE__ -#define PLUGIN_SUFFIX "dylib" -#else /* ! __APPLE__ */ -#define PLUGIN_SUFFIX "so" -#endif /* ! __APPLE__ */ - -#endif /* ! _WIN32 */ using namespace std; @@ -124,13 +106,6 @@ bool decomposePluginKey(PluginKey key, string &libraryName, string &identifier); - void *loadLibrary(string path); - void unloadLibrary(void *handle); - void *lookupInLibrary(void *handle, const char *symbol); - - string splicePath(string a, string b); - vector<string> listFiles(string dir, string ext); - static InstanceCleaner m_cleaner; }; @@ -227,83 +202,64 @@ void PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin) { - vector<string> path = PluginHostAdapter::getPluginPath(); - string libraryName, identifier; + vector<string> fullPaths; + 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(); } - for (size_t i = 0; i < path.size(); ++i) { - - vector<string> files = listFiles(path[i], PLUGIN_SUFFIX); + for (size_t i = 0; i < fullPaths.size(); ++i) { - for (vector<string>::iterator fi = files.begin(); - fi != files.end(); ++fi) { + string fullPath = fullPaths[i]; + void *handle = Files::loadLibrary(fullPath); + if (!handle) continue; - if (libraryName != "") { - // libraryName is lowercased and lacking an extension, - // as it came from the plugin key - string temp = *fi; - for (size_t i = 0; i < temp.length(); ++i) { - temp[i] = tolower(temp[i]); - } - string::size_type pi = temp.find('.'); - if (pi == string::npos) { - if (libraryName != temp) continue; - } else { - if (libraryName != temp.substr(0, pi)) continue; - } - } - - string fullPath = path[i]; - fullPath = splicePath(fullPath, *fi); - void *handle = loadLibrary(fullPath); - if (!handle) continue; + VampGetPluginDescriptorFunction fn = + (VampGetPluginDescriptorFunction)Files::lookupInLibrary + (handle, "vampGetPluginDescriptor"); - VampGetPluginDescriptorFunction fn = - (VampGetPluginDescriptorFunction)lookupInLibrary - (handle, "vampGetPluginDescriptor"); - - if (!fn) { - if (forPlugin != "") { - cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" - << fullPath << "\"" << endl; - } - unloadLibrary(handle); - continue; - } - - int index = 0; - const VampPluginDescriptor *descriptor = 0; - bool found = false; - - while ((descriptor = fn(VAMP_API_VERSION, index))) { - ++index; - if (identifier != "") { - if (descriptor->identifier != identifier) continue; - } - found = true; - 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; - } - } - - if (!found && forPlugin != "") { - cerr << "Vamp::HostExt::PluginLoader: Plugin \"" - << identifier << "\" not found in library \"" + if (!fn) { + if (forPlugin != "") { + cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" << fullPath << "\"" << endl; } + Files::unloadLibrary(handle); + continue; + } - unloadLibrary(handle); + int index = 0; + const VampPluginDescriptor *descriptor = 0; + bool found = false; + + while ((descriptor = fn(VAMP_API_VERSION, index))) { + ++index; + if (identifier != "") { + 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; + } } + + if (!found && forPlugin != "") { + cerr << "Vamp::HostExt::PluginLoader: Plugin \"" + << identifier << "\" not found in library \"" + << fullPath << "\"" << endl; + } + + Files::unloadLibrary(handle); } if (forPlugin == "") m_allPluginsEnumerated = true; @@ -312,18 +268,7 @@ PluginLoader::PluginKey PluginLoader::Impl::composePluginKey(string libraryName, string identifier) { - string basename = libraryName; - - string::size_type li = basename.rfind('/'); - if (li != string::npos) basename = basename.substr(li + 1); - - li = basename.find('.'); - if (li != string::npos) basename = basename.substr(0, li); - - for (size_t i = 0; i < basename.length(); ++i) { - basename[i] = tolower(basename[i]); - } - + string basename = Files::lcBasename(libraryName); return basename + ":" + identifier; } @@ -382,17 +327,17 @@ return 0; } - void *handle = loadLibrary(fullPath); + void *handle = Files::loadLibrary(fullPath); if (!handle) return 0; VampGetPluginDescriptorFunction fn = - (VampGetPluginDescriptorFunction)lookupInLibrary + (VampGetPluginDescriptorFunction)Files::lookupInLibrary (handle, "vampGetPluginDescriptor"); if (!fn) { cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" << fullPath << "\"" << endl; - unloadLibrary(handle); + Files::unloadLibrary(handle); return 0; } @@ -474,12 +419,12 @@ for (vector<string>::iterator i = catpath.begin(); i != catpath.end(); ++i) { - vector<string> files = listFiles(*i, suffix); + vector<string> files = Files::listFiles(*i, suffix); for (vector<string>::iterator fi = files.begin(); fi != files.end(); ++fi) { - string filepath = splicePath(*i, *fi); + string filepath = Files::splicePath(*i, *fi); ifstream is(filepath.c_str(), ifstream::in | ifstream::binary); if (is.fail()) { @@ -525,154 +470,11 @@ } } -void * -PluginLoader::Impl::loadLibrary(string path) -{ - void *handle = 0; -#ifdef _WIN32 -#ifdef UNICODE - int len = path.length() + 1; // cannot be more wchars than length in bytes of utf8 string - wchar_t *buffer = new wchar_t[len]; - int rv = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), len, buffer, len); - if (rv <= 0) { - cerr << "Vamp::HostExt::PluginLoader: Unable to convert library path \"" - << path << "\" to wide characters " << endl; - delete[] buffer; - return handle; - } - handle = LoadLibrary(buffer); - delete[] buffer; -#else - handle = LoadLibrary(path.c_str()); -#endif - if (!handle) { - cerr << "Vamp::HostExt::PluginLoader: Unable to load library \"" - << path << "\"" << endl; - } -#else - handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); - if (!handle) { - cerr << "Vamp::HostExt::PluginLoader: Unable to load library \"" - << path << "\": " << dlerror() << endl; - } -#endif - return handle; -} - -void -PluginLoader::Impl::unloadLibrary(void *handle) -{ -#ifdef _WIN32 - FreeLibrary((HINSTANCE)handle); -#else - dlclose(handle); -#endif -} - -void * -PluginLoader::Impl::lookupInLibrary(void *handle, const char *symbol) -{ -#ifdef _WIN32 - return (void *)GetProcAddress((HINSTANCE)handle, symbol); -#else - return (void *)dlsym(handle, symbol); -#endif -} - -string -PluginLoader::Impl::splicePath(string a, string b) -{ -#ifdef _WIN32 - return a + "\\" + b; -#else - return a + "/" + b; -#endif -} - -vector<string> -PluginLoader::Impl::listFiles(string dir, string extension) -{ - vector<string> files; - -#ifdef _WIN32 - string expression = dir + "\\*." + extension; -#ifdef UNICODE - int len = expression.length() + 1; // cannot be more wchars than length in bytes of utf8 string - wchar_t *buffer = new wchar_t[len]; - int rv = MultiByteToWideChar(CP_UTF8, 0, expression.c_str(), len, buffer, len); - if (rv <= 0) { - cerr << "Vamp::HostExt::PluginLoader: Unable to convert wildcard path \"" - << expression << "\" to wide characters" << endl; - delete[] buffer; - return files; - } - WIN32_FIND_DATA data; - HANDLE fh = FindFirstFile(buffer, &data); - if (fh == INVALID_HANDLE_VALUE) { - delete[] buffer; - return files; - } - - bool ok = true; - while (ok) { - wchar_t *fn = data.cFileName; - int wlen = wcslen(fn) + 1; - int maxlen = wlen * 6; - char *conv = new char[maxlen]; - int rv = WideCharToMultiByte(CP_UTF8, 0, fn, wlen, conv, maxlen, 0, 0); - if (rv > 0) { - files.push_back(conv); - } - delete[] conv; - ok = FindNextFile(fh, &data); - } - - FindClose(fh); - delete[] buffer; -#else - WIN32_FIND_DATA data; - HANDLE fh = FindFirstFile(expression.c_str(), &data); - if (fh == INVALID_HANDLE_VALUE) return files; - - bool ok = true; - while (ok) { - files.push_back(data.cFileName); - ok = FindNextFile(fh, &data); - } - - FindClose(fh); -#endif -#else - - size_t extlen = extension.length(); - DIR *d = opendir(dir.c_str()); - if (!d) return files; - - struct dirent *e = 0; - while ((e = readdir(d))) { - - if (!e->d_name) continue; - - size_t len = strlen(e->d_name); - if (len < extlen + 2 || - e->d_name + len - extlen - 1 != "." + extension) { - continue; - } - - files.push_back(e->d_name); - } - - closedir(d); -#endif - - return files; -} - void PluginLoader::Impl::pluginDeleted(PluginDeletionNotifyAdapter *adapter) { void *handle = m_pluginLibraryHandleMap[adapter]; - if (handle) unloadLibrary(handle); + if (handle) Files::unloadLibrary(handle); m_pluginLibraryHandleMap.erase(adapter); }