diff options
Diffstat (limited to 'libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp')
-rw-r--r-- | libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp | 707 |
1 files changed, 0 insertions, 707 deletions
diff --git a/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp b/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp deleted file mode 100644 index b3b2b45c68..0000000000 --- a/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ - -/* - Vamp - - An API for audio analysis and feature extraction plugins. - - Centre for Digital Music, Queen Mary, University of London. - Copyright 2006-2009 Chris Cannam and QMUL. - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR - ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - - Except as contained in this notice, the names of the Centre for - Digital Music; Queen Mary, University of London; and Chris Cannam - shall not be used in advertising or otherwise to promote the sale, - use or other dealings in this Software without prior written - 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 <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; - -_VAMP_SDK_HOSTSPACE_BEGIN(PluginLoader.cpp) - -namespace Vamp { - -namespace HostExt { - -class PluginLoader::Impl -{ -public: - Impl(); - virtual ~Impl(); - - PluginKeyList listPlugins(); - - Plugin *loadPlugin(PluginKey key, - float inputSampleRate, - int adapterFlags); - - PluginKey composePluginKey(string libraryName, string identifier); - - PluginCategoryHierarchy getPluginCategory(PluginKey key); - - string getLibraryPathForPlugin(PluginKey key); - - static void setInstanceToClean(PluginLoader *instance); - -protected: - class PluginDeletionNotifyAdapter : public PluginWrapper { - public: - PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader); - virtual ~PluginDeletionNotifyAdapter(); - protected: - Impl *m_loader; - }; - - class InstanceCleaner { - public: - InstanceCleaner() : m_instance(0) { } - ~InstanceCleaner() { delete m_instance; } - void setInstance(PluginLoader *instance) { m_instance = instance; } - protected: - PluginLoader *m_instance; - }; - - virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter); - - map<PluginKey, string> m_pluginLibraryNameMap; - bool m_allPluginsEnumerated; - void enumeratePlugins(PluginKey forPlugin = ""); - - map<PluginKey, PluginCategoryHierarchy> m_taxonomy; - void generateTaxonomy(); - - map<Plugin *, void *> m_pluginLibraryHandleMap; - - 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; -}; - -PluginLoader * -PluginLoader::m_instance = 0; - -PluginLoader::Impl::InstanceCleaner -PluginLoader::Impl::m_cleaner; - -PluginLoader::PluginLoader() -{ - m_impl = new Impl(); -} - -PluginLoader::~PluginLoader() -{ - delete m_impl; -} - -PluginLoader * -PluginLoader::getInstance() -{ - if (!m_instance) { - // The cleaner doesn't own the instance, because we leave the - // instance pointer in the base class for binary backwards - // compatibility reasons and to avoid waste - m_instance = new PluginLoader(); - Impl::setInstanceToClean(m_instance); - } - return m_instance; -} - -vector<PluginLoader::PluginKey> -PluginLoader::listPlugins() -{ - return m_impl->listPlugins(); -} - -Plugin * -PluginLoader::loadPlugin(PluginKey key, - float inputSampleRate, - int adapterFlags) -{ - return m_impl->loadPlugin(key, inputSampleRate, adapterFlags); -} - -PluginLoader::PluginKey -PluginLoader::composePluginKey(string libraryName, string identifier) -{ - return m_impl->composePluginKey(libraryName, identifier); -} - -PluginLoader::PluginCategoryHierarchy -PluginLoader::getPluginCategory(PluginKey key) -{ - return m_impl->getPluginCategory(key); -} - -string -PluginLoader::getLibraryPathForPlugin(PluginKey key) -{ - return m_impl->getLibraryPathForPlugin(key); -} - -PluginLoader::Impl::Impl() : - m_allPluginsEnumerated(false) -{ -} - -PluginLoader::Impl::~Impl() -{ -} - -void -PluginLoader::Impl::setInstanceToClean(PluginLoader *instance) -{ - m_cleaner.setInstance(instance); -} - -vector<PluginLoader::PluginKey> -PluginLoader::Impl::listPlugins() -{ - 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); - } - - return plugins; -} - -void -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); - - for (vector<string>::iterator fi = files.begin(); - fi != files.end(); ++fi) { - - 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)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); - - 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; - } - - unloadLibrary(handle); - } - } - - if (forPlugin == "") m_allPluginsEnumerated = true; -} - -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]); - } - - 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) -{ - if (m_taxonomy.empty()) generateTaxonomy(); - if (m_taxonomy.find(plugin) == m_taxonomy.end()) { - return PluginCategoryHierarchy(); - } - return m_taxonomy[plugin]; -} - -string -PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin) -{ - 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]; -} - -Plugin * -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 == "") { - std::cerr << "Vamp::HostExt::PluginLoader: No library found in Vamp path for plugin \"" << key << "\"" << std::endl; - return 0; - } - - void *handle = loadLibrary(fullPath); - if (!handle) return 0; - - VampGetPluginDescriptorFunction fn = - (VampGetPluginDescriptorFunction)lookupInLibrary - (handle, "vampGetPluginDescriptor"); - - if (!fn) { - cerr << "Vamp::HostExt::PluginLoader: No vampGetPluginDescriptor function found in library \"" - << fullPath << "\"" << endl; - unloadLibrary(handle); - return 0; - } - - int index = 0; - const VampPluginDescriptor *descriptor = 0; - - while ((descriptor = fn(VAMP_API_VERSION, index))) { - - if (string(descriptor->identifier) == identifier) { - - Vamp::PluginHostAdapter *plugin = - new Vamp::PluginHostAdapter(descriptor, inputSampleRate); - - Plugin *adapter = new PluginDeletionNotifyAdapter(plugin, this); - - m_pluginLibraryHandleMap[adapter] = handle; - - if (adapterFlags & ADAPT_BUFFER_SIZE) { - PluginBufferingAdapter* a = new PluginBufferingAdapter(adapter); - adapter = a; - } - - if (adapterFlags & ADAPT_INPUT_DOMAIN) { - if (adapter->getInputDomain() == Plugin::FrequencyDomain) { - adapter = new PluginInputDomainAdapter(adapter); - } - } - - if (adapterFlags & ADAPT_CHANNEL_COUNT) { - adapter = new PluginChannelAdapter(adapter); - } - - return adapter; - } - - ++index; - } - - cerr << "Vamp::HostExt::PluginLoader: Plugin \"" - << identifier << "\" not found in library \"" - << fullPath << "\"" << endl; - - return 0; -} - -void -PluginLoader::Impl::generateTaxonomy() -{ -// cerr << "PluginLoader::Impl::generateTaxonomy" << endl; - - vector<string> path = PluginHostAdapter::getPluginPath(); - string libfragment = "/lib/"; - vector<string> catpath; - - string suffix = "cat"; - - for (vector<string>::iterator i = path.begin(); - i != path.end(); ++i) { - - // It doesn't matter that we're using literal forward-slash in - // this bit, as it's only relevant if the path contains - // "/lib/", which is only meaningful and only plausible on - // systems with forward-slash delimiters - - string dir = *i; - string::size_type li = dir.find(libfragment); - - if (li != string::npos) { - catpath.push_back - (dir.substr(0, li) - + "/share/" - + dir.substr(li + libfragment.length())); - } - - catpath.push_back(dir); - } - - char buffer[1024]; - - for (vector<string>::iterator i = catpath.begin(); - i != catpath.end(); ++i) { - - vector<string> files = listFiles(*i, suffix); - - for (vector<string>::iterator fi = files.begin(); - fi != files.end(); ++fi) { - - string filepath = splicePath(*i, *fi); - ifstream is(filepath.c_str(), ifstream::in | ifstream::binary); - - if (is.fail()) { -// cerr << "failed to open: " << filepath << endl; - continue; - } - -// cerr << "opened: " << filepath << endl; - - while (!!is.getline(buffer, 1024)) { - - string line(buffer); - -// cerr << "line = " << line << endl; - - string::size_type di = line.find("::"); - if (di == string::npos) continue; - - string id = line.substr(0, di); - string encodedCat = line.substr(di + 2); - - if (id.substr(0, 5) != "vamp:") continue; - id = id.substr(5); - - while (encodedCat.length() >= 1 && - encodedCat[encodedCat.length()-1] == '\r') { - encodedCat = encodedCat.substr(0, encodedCat.length()-1); - } - -// cerr << "id = " << id << ", cat = " << encodedCat << endl; - - PluginCategoryHierarchy category; - string::size_type ai; - while ((ai = encodedCat.find(" > ")) != string::npos) { - category.push_back(encodedCat.substr(0, ai)); - encodedCat = encodedCat.substr(ai + 3); - } - if (encodedCat != "") category.push_back(encodedCat); - - m_taxonomy[id] = category; - } - } - } -} - -void * -PluginLoader::Impl::loadLibrary(string path) -{ - void *handle = 0; -#ifdef _WIN32 -#ifdef UNICODE - int len = path.length(); // 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(); // 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); - 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); - m_pluginLibraryHandleMap.erase(adapter); -} - -PluginLoader::Impl::PluginDeletionNotifyAdapter::PluginDeletionNotifyAdapter(Plugin *plugin, - Impl *loader) : - PluginWrapper(plugin), - m_loader(loader) -{ -} - -PluginLoader::Impl::PluginDeletionNotifyAdapter::~PluginDeletionNotifyAdapter() -{ - // We need to delete the plugin before calling pluginDeleted, as - // the delete call may require calling through to the descriptor - // (for e.g. cleanup) but pluginDeleted may unload the required - // library for the call. To prevent a double deletion when our - // parent's destructor runs (after this one), be sure to set - // m_plugin to 0 after deletion. - delete m_plugin; - m_plugin = 0; - - if (m_loader) m_loader->pluginDeleted(this); -} - -} - -} - -_VAMP_SDK_HOSTSPACE_END(PluginLoader.cpp) - |