# HG changeset patch # User Chris Cannam # Date 1434445956 -3600 # Node ID 96cdf661d5389f269ac8c8cd05619fe61bbc7a9d # Parent a69901aa85d26ab4eda8f34b71dfa3528ed81514# Parent 632c662e95e7088ae78e134729e62dde33e80cc9 Merge from branch vh diff -r a69901aa85d2 -r 96cdf661d538 build/Makefile.mingw32 --- a/build/Makefile.mingw32 Tue Jun 02 14:18:27 2015 +0100 +++ b/build/Makefile.mingw32 Tue Jun 16 10:12:36 2015 +0100 @@ -142,6 +142,7 @@ $(SDKSRCDIR)/acsymbols.o HOSTSDK_OBJECTS = \ + $(HOSTSDKSRCDIR)/Files.o \ $(HOSTSDKSRCDIR)/PluginHostAdapter.o \ $(HOSTSDKSRCDIR)/RealTime.o \ $(HOSTSDKSRCDIR)/PluginBufferingAdapter.o \ @@ -150,6 +151,7 @@ $(HOSTSDKSRCDIR)/PluginLoader.o \ $(HOSTSDKSRCDIR)/PluginSummarisingAdapter.o \ $(HOSTSDKSRCDIR)/PluginWrapper.o \ + $(HOSTSDKSRCDIR)/host-c.o \ $(HOSTSDKSRCDIR)/acsymbols.o SDK_STATIC = \ diff -r a69901aa85d2 -r 96cdf661d538 build/Makefile.mingw64 --- a/build/Makefile.mingw64 Tue Jun 02 14:18:27 2015 +0100 +++ b/build/Makefile.mingw64 Tue Jun 16 10:12:36 2015 +0100 @@ -142,6 +142,7 @@ $(SDKSRCDIR)/acsymbols.o HOSTSDK_OBJECTS = \ + $(HOSTSDKSRCDIR)/Files.o \ $(HOSTSDKSRCDIR)/PluginHostAdapter.o \ $(HOSTSDKSRCDIR)/RealTime.o \ $(HOSTSDKSRCDIR)/PluginBufferingAdapter.o \ @@ -150,6 +151,7 @@ $(HOSTSDKSRCDIR)/PluginLoader.o \ $(HOSTSDKSRCDIR)/PluginSummarisingAdapter.o \ $(HOSTSDKSRCDIR)/PluginWrapper.o \ + $(HOSTSDKSRCDIR)/host-c.o \ $(HOSTSDKSRCDIR)/acsymbols.o SDK_STATIC = \ diff -r a69901aa85d2 -r 96cdf661d538 build/Makefile.osx --- a/build/Makefile.osx Tue Jun 02 14:18:27 2015 +0100 +++ b/build/Makefile.osx Tue Jun 16 10:12:36 2015 +0100 @@ -150,6 +150,7 @@ $(SDKSRCDIR)/acsymbols.o HOSTSDK_OBJECTS = \ + $(HOSTSDKSRCDIR)/Files.o \ $(HOSTSDKSRCDIR)/PluginHostAdapter.o \ $(HOSTSDKSRCDIR)/RealTime.o \ $(HOSTSDKSRCDIR)/PluginBufferingAdapter.o \ @@ -158,6 +159,7 @@ $(HOSTSDKSRCDIR)/PluginLoader.o \ $(HOSTSDKSRCDIR)/PluginSummarisingAdapter.o \ $(HOSTSDKSRCDIR)/PluginWrapper.o \ + $(HOSTSDKSRCDIR)/host-c.o \ $(HOSTSDKSRCDIR)/acsymbols.o SDK_STATIC = \ diff -r a69901aa85d2 -r 96cdf661d538 build/Makefile.osx.106 --- a/build/Makefile.osx.106 Tue Jun 02 14:18:27 2015 +0100 +++ b/build/Makefile.osx.106 Tue Jun 16 10:12:36 2015 +0100 @@ -171,6 +171,7 @@ $(SDKSRCDIR)/acsymbols.o HOSTSDK_OBJECTS = \ + $(HOSTSDKSRCDIR)/Files.o \ $(HOSTSDKSRCDIR)/PluginHostAdapter.o \ $(HOSTSDKSRCDIR)/RealTime.o \ $(HOSTSDKSRCDIR)/PluginBufferingAdapter.o \ @@ -179,6 +180,7 @@ $(HOSTSDKSRCDIR)/PluginLoader.o \ $(HOSTSDKSRCDIR)/PluginSummarisingAdapter.o \ $(HOSTSDKSRCDIR)/PluginWrapper.o \ + $(HOSTSDKSRCDIR)/host-c.o \ $(HOSTSDKSRCDIR)/acsymbols.o SDK_STATIC = \ diff -r a69901aa85d2 -r 96cdf661d538 host/test-c.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/host/test-c.c Tue Jun 16 10:12:36 2015 +0100 @@ -0,0 +1,40 @@ + +#include + +#include + +int main(int argc, char **argv) +{ + int i; + int libcount = vhGetLibraryCount(); + + printf("Vamp plugin libraries found:\n"); + for (i = 0; i < libcount; ++i) { + printf("%d: %s\n", i, vhGetLibraryName(i)); + } + + printf("Going to try loading qm-vamp-plugins...\n"); + int libindex = vhGetLibraryIndex("qm-vamp-plugins"); + vhLibrary lib = vhLoadLibrary(libindex); + if (!lib) { + printf("Failure!\n"); + return 1; + } + + int plugincount = vhGetPluginCount(lib); + printf("Success: it contains %d plugins; they are:\n", plugincount); + + for (i = 0; i < plugincount; ++i) { + const VampPluginDescriptor *descriptor = vhGetPluginDescriptor(lib, i); + if (!descriptor) { + printf("\n"); + } else { + printf("%s\n", descriptor->identifier); + } + } + + vhUnloadLibrary(lib); + + return 0; +} + diff -r a69901aa85d2 -r 96cdf661d538 src/vamp-hostsdk/Files.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vamp-hostsdk/Files.cpp Tue Jun 16 10:12:36 2015 +0100 @@ -0,0 +1,274 @@ +/* -*- 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-2015 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 + +#include "Files.h" + +#include // tolower + +#include + +#ifdef _WIN32 + +#include +#include +#define PLUGIN_SUFFIX "dll" + +#else /* ! _WIN32 */ + +#include +#include + +#ifdef __APPLE__ +#define PLUGIN_SUFFIX "dylib" +#else /* ! __APPLE__ */ +#define PLUGIN_SUFFIX "so" +#endif /* ! __APPLE__ */ + +#endif /* ! _WIN32 */ + +using namespace std; + +vector +Files::listLibraryFiles() +{ + return listLibraryFilesMatching(""); +} + +vector +Files::listLibraryFilesMatching(string libraryName) +{ + vector path = Vamp::PluginHostAdapter::getPluginPath(); + vector libraryFiles; + + // we match case-insensitively + for (size_t i = 0; i < libraryName.length(); ++i) { + libraryName[i] = tolower(libraryName[i]); + } + + for (size_t i = 0; i < path.size(); ++i) { + + vector files = listFiles(path[i], PLUGIN_SUFFIX); + + for (vector::iterator fi = files.begin(); + fi != files.end(); ++fi) { + + if (libraryName != "") { + // we match case-insensitively + string temp = *fi; + for (size_t i = 0; i < temp.length(); ++i) { + temp[i] = 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; + } + } + + string fullPath = path[i]; + fullPath = splicePath(fullPath, *fi); + libraryFiles.push_back(fullPath); + } + } + + return libraryFiles; +} + +void * +Files::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: 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: Unable to load library \"" + << path << "\"" << endl; + } +#else + handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_LOCAL); + if (!handle) { + cerr << "Vamp::HostExt: Unable to load library \"" + << path << "\": " << dlerror() << endl; + } +#endif + return handle; +} + +void +Files::unloadLibrary(void *handle) +{ +#ifdef _WIN32 + FreeLibrary((HINSTANCE)handle); +#else + dlclose(handle); +#endif +} + +void * +Files::lookupInLibrary(void *handle, const char *symbol) +{ +#ifdef _WIN32 + return (void *)GetProcAddress((HINSTANCE)handle, symbol); +#else + return (void *)dlsym(handle, symbol); +#endif +} + +string +Files::lcBasename(string path) +{ + string basename(path); + + 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; +} + +string +Files::splicePath(string a, string b) +{ +#ifdef _WIN32 + return a + "\\" + b; +#else + return a + "/" + b; +#endif +} + +vector +Files::listFiles(string dir, string extension) +{ + vector 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: 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; +} diff -r a69901aa85d2 -r 96cdf661d538 src/vamp-hostsdk/Files.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vamp-hostsdk/Files.h Tue Jun 16 10:12:36 2015 +0100 @@ -0,0 +1,63 @@ +/* -*- 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-2015 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. +*/ + +#ifndef VAMP_FILES_H +#define VAMP_FILES_H + +#include +#include + +/** + * This is a private implementation class for the Vamp Host SDK. + */ +class Files +{ +public: + static std::vector listLibraryFiles(); + static std::vector listLibraryFilesMatching(std::string libname); + + static void *loadLibrary(std::string filename); + static void unloadLibrary(void *); + static void *lookupInLibrary(void *, const char *symbol); + + static std::string lcBasename(std::string path); + static std::string splicePath(std::string a, std::string b); + static std::vector listFiles(std::string dir, std::string ext); +}; + +#endif + + diff -r a69901aa85d2 -r 96cdf661d538 src/vamp-hostsdk/PluginLoader.cpp --- a/src/vamp-hostsdk/PluginLoader.cpp Tue Jun 02 14:18:27 2015 +0100 +++ b/src/vamp-hostsdk/PluginLoader.cpp Tue Jun 16 10:12:36 2015 +0100 @@ -34,35 +34,17 @@ authorization. */ -#include #include #include #include #include +#include + +#include + +#include "Files.h" #include -#include // tolower - -#include - -#ifdef _WIN32 - -#include -#include -#define PLUGIN_SUFFIX "dll" - -#else /* ! _WIN32 */ - -#include -#include - -#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 listFiles(string dir, string ext); - static InstanceCleaner m_cleaner; }; @@ -227,83 +202,64 @@ void PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin) { - vector path = PluginHostAdapter::getPluginPath(); - string libraryName, identifier; + vector 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 files = listFiles(path[i], PLUGIN_SUFFIX); + for (size_t i = 0; i < fullPaths.size(); ++i) { - for (vector::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::iterator i = catpath.begin(); i != catpath.end(); ++i) { - vector files = listFiles(*i, suffix); + vector files = Files::listFiles(*i, suffix); for (vector::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 -PluginLoader::Impl::listFiles(string dir, string extension) -{ - vector 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); } diff -r a69901aa85d2 -r 96cdf661d538 src/vamp-hostsdk/host-c.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/vamp-hostsdk/host-c.cpp Tue Jun 16 10:12:36 2015 +0100 @@ -0,0 +1,151 @@ +/* -*- 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-2015 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 + +#include "Files.h" + +#include +#include + +#include + +using namespace std; + +static vector files; +static map cnames; +static bool haveFiles = false; + +struct vhLibrary_t { + vhLibrary_t(void *h, VampGetPluginDescriptorFunction f) + : handle(h), func(f), nplugins(0) { } + void *handle; + VampGetPluginDescriptorFunction func; + int nplugins; +}; + +static void initFilenames() +{ + if (!haveFiles) { + files = Files::listLibraryFiles(); + for (size_t i = 0; i < files.size(); ++i) { + cnames[files[i]] = strdup(Files::lcBasename(files[i]).c_str()); + } + haveFiles = true; + } +} + +int vhGetLibraryCount() +{ + initFilenames(); + return int(files.size()); +} + +const char *vhGetLibraryName(int index) +{ + initFilenames(); + if (index >= 0 && index < int(files.size())) { + return cnames[files[index]]; + } + else return 0; +} + +int vhGetLibraryIndex(const char *name) +{ + for (size_t i = 0; i < files.size(); ++i) { + if (Files::lcBasename(name) == Files::lcBasename(files[i])) { + return i; + } + } + return -1; +} + +vhLibrary vhLoadLibrary(int index) +{ + initFilenames(); + if (index < 0 || index >= int(files.size())) { + return 0; + } + + string fullPath = files[index]; + void *lib = Files::loadLibrary(fullPath); + + if (!lib) return 0; + + VampGetPluginDescriptorFunction func = + (VampGetPluginDescriptorFunction)Files::lookupInLibrary + (lib, "vampGetPluginDescriptor"); + if (!func) { + cerr << "vhLoadLibrary: No vampGetPluginDescriptor function found in library \"" + << fullPath << "\"" << endl; + Files::unloadLibrary(lib); + return 0; + } + + vhLibrary_t *vhl = new vhLibrary_t(lib, func); + while (vhl->func(VAMP_API_VERSION, vhl->nplugins)) { + ++vhl->nplugins; + } + return vhl; +} + +int vhGetPluginCount(vhLibrary library) +{ + vhLibrary_t *vhl = static_cast(library); + if (vhl) return vhl->nplugins; + else return 0; +} + +const VampPluginDescriptor *vhGetPluginDescriptor(vhLibrary library, + int plugin) +{ + vhLibrary_t *vhl = static_cast(library); + if (vhl && plugin >= 0 && plugin < vhl->nplugins) { + return vhl->func(VAMP_API_VERSION, plugin); + } else { + return 0; + } +} + +void vhUnloadLibrary(vhLibrary library) +{ + vhLibrary_t *vhl = static_cast(library); + if (vhl && vhl->handle) { + Files::unloadLibrary(vhl->handle); + } + delete vhl; +} + diff -r a69901aa85d2 -r 96cdf661d538 vamp-hostsdk/host-c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vamp-hostsdk/host-c.h Tue Jun 16 10:12:36 2015 +0100 @@ -0,0 +1,147 @@ +/* -*- 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-2015 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. +*/ + +/* + This file defines a low-level API for enumerating and loading + plugin libraries using C calling conventions. It could be used in + C programs, or in languages with C-compatible foreign-function + interfaces. Note that this works by calling to the C++ Vamp host + SDK, so any program using this interface must still link against + the rest of the Vamp plugin library and the C++ standard library. + + This is not the simplest or easiest interface for hosting Vamp + plugins -- if you have the capability to use the C++ API, please + do that instead. (Most programs should not even include this + header.) + + The C and C++ interfaces provide different abstraction levels: + + In the C++ interface, the class PluginLoader provides a list of + keys corresponding to the installed plugins (where a key combines + the plugin's library name and plugin identifier into a single + string) plus a method to load a single plugin based on its key + (obtaining an instance of class Plugin). With the C++ interface + you go straight from the key to a live instance of the plugin. The + PluginLoader also provides various facilities to adapt the plugin + based on your requirements (e.g. to do time- to frequency-domain + conversion for you if the plugin requires it). + + This low-level C interface, on the other hand, deals only in + plugin libraries and static descriptors, not in plugin + instances. You can enumerate the installed libraries, getting just + the base .soname of each library. Then you can retrieve each of + the raw C plugin descriptors from a library, and use the + descriptor (whose interface is defined in vamp/vamp.h) to + instantiate the plugin. + + So this header corresponds to the first part of the PluginLoader + class interface: finding and loading plugin libraries and + retrieving plugin descriptors from them. But it does not do any of + the rest, i.e. instantiating and adapting the plugins themselves. + Although this makes the API appear very simple, it means the + resulting plugins are relatively hard to use compared to those + obtained by the PluginLoader API. There is no way to get to the + full C++ abstraction using this API. + + This API is not thread-safe; use it from a single application + thread, or guard access to it with a mutex. + + This header was introduced in version 2.6 of the Vamp plugin SDK. +*/ + +#ifndef VAMPHOST_C_H_INCLUDED +#define VAMPHOST_C_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct vhLibrary_t *vhLibrary; + +/** + * Return the number of Vamp plugin libraries discovered in the + * installation path. This number will remain fixed after the first + * call -- plugins are only discovered once, the first time this + * function is called. + */ +extern int vhGetLibraryCount(); + +/** + * Return the library name (base soname) of the library with the given + * index, in the range 0..(vhGetLibraryCount()-1). + */ +extern const char *vhGetLibraryName(int library); + +/** + * Return the library index for the given library name, or -1 if the + * name is not known. + */ +extern int vhGetLibraryIndex(const char *name); + +/** + * Load the library with the given index. If the library cannot be + * loaded for any reason, the return value is 0; otherwise it is an + * opaque pointer suitable for passing to other functions in this API. + */ +extern vhLibrary vhLoadLibrary(int library); + +/** + * Return the number of Vamp plugins in the given library. + */ +extern int vhGetPluginCount(vhLibrary library); + +/** + * Return a Vamp plugin descriptor for a plugin in a given + * library. This simply calls the vampGetPluginDescriptor function in + * that library with the given plugin index and returns the + * result. See vamp/vamp.h for details about the plugin descriptor. + */ +extern const VampPluginDescriptor *vhGetPluginDescriptor(vhLibrary library, + int plugin); + +/** + * Unload a plugin library. Do not do this while any of its plugins + * are still in use. + */ +extern void vhUnloadLibrary(vhLibrary); + +#ifdef __cplusplus +} +#endif + +#endif