summaryrefslogtreecommitdiff
path: root/libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp')
-rw-r--r--libs/vamp-sdk/src/vamp-hostsdk/PluginLoader.cpp707
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)
-