annotate vamp-hostsdk/PluginLoader.cpp @ 56:4ab6224110ef host-factory-stuff

* implement plugin loader and plugin input-domain adapter (to do basic ffts)
author cannam
date Fri, 04 May 2007 15:21:12 +0000
parents
children 09a1aac6c362
rev   line source
cannam@56 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@56 2
cannam@56 3 /*
cannam@56 4 Vamp
cannam@56 5
cannam@56 6 An API for audio analysis and feature extraction plugins.
cannam@56 7
cannam@56 8 Centre for Digital Music, Queen Mary, University of London.
cannam@56 9 Copyright 2006 Chris Cannam.
cannam@56 10
cannam@56 11 Permission is hereby granted, free of charge, to any person
cannam@56 12 obtaining a copy of this software and associated documentation
cannam@56 13 files (the "Software"), to deal in the Software without
cannam@56 14 restriction, including without limitation the rights to use, copy,
cannam@56 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@56 16 of the Software, and to permit persons to whom the Software is
cannam@56 17 furnished to do so, subject to the following conditions:
cannam@56 18
cannam@56 19 The above copyright notice and this permission notice shall be
cannam@56 20 included in all copies or substantial portions of the Software.
cannam@56 21
cannam@56 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@56 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@56 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@56 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@56 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@56 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@56 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@56 29
cannam@56 30 Except as contained in this notice, the names of the Centre for
cannam@56 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@56 32 shall not be used in advertising or otherwise to promote the sale,
cannam@56 33 use or other dealings in this Software without prior written
cannam@56 34 authorization.
cannam@56 35 */
cannam@56 36
cannam@56 37 #include "PluginLoader.h"
cannam@56 38 #include "PluginHostAdapter.h"
cannam@56 39
cannam@56 40 #include "system.h"
cannam@56 41
cannam@56 42 #include <dirent.h> // POSIX directory open and read
cannam@56 43
cannam@56 44 namespace Vamp {
cannam@56 45
cannam@56 46 PluginLoader::PluginLoader()
cannam@56 47 {
cannam@56 48 }
cannam@56 49
cannam@56 50 PluginLoader::~PluginLoader()
cannam@56 51 {
cannam@56 52 }
cannam@56 53
cannam@56 54 std::vector<PluginLoader::PluginKey>
cannam@56 55 PluginLoader::listPlugins()
cannam@56 56 {
cannam@56 57 if (m_pluginLibraryMap.empty()) {
cannam@56 58
cannam@56 59 std::vector<std::string> path = PluginHostAdapter::getPluginPath();
cannam@56 60
cannam@56 61 size_t suffixLen = strlen(PLUGIN_SUFFIX);
cannam@56 62
cannam@56 63 for (size_t i = 0; i < path.size(); ++i) {
cannam@56 64
cannam@56 65 DIR *d = opendir(path[i].c_str());
cannam@56 66 if (!d) {
cannam@56 67 // perror("Failed to open directory");
cannam@56 68 continue;
cannam@56 69 }
cannam@56 70
cannam@56 71 struct dirent *e = 0;
cannam@56 72 while ((e = readdir(d))) {
cannam@56 73
cannam@56 74 if (!(e->d_type & DT_REG) || !e->d_name) {
cannam@56 75 continue;
cannam@56 76 }
cannam@56 77
cannam@56 78 int len = strlen(e->d_name);
cannam@56 79 if (len < int(suffixLen + 2) ||
cannam@56 80 e->d_name[len - suffixLen - 1] != '.' ||
cannam@56 81 strcmp(e->d_name + len - suffixLen, PLUGIN_SUFFIX)) {
cannam@56 82 continue;
cannam@56 83 }
cannam@56 84
cannam@56 85 std::string basename = e->d_name;
cannam@56 86 basename = basename.substr(0, basename.length() - suffixLen - 1);
cannam@56 87 std::string fullPath = path[i].c_str();
cannam@56 88 fullPath = fullPath + "/" + e->d_name;
cannam@56 89 void *handle = DLOPEN(fullPath, RTLD_LAZY);
cannam@56 90
cannam@56 91 if (!handle) {
cannam@56 92 std::cerr << "Vamp::PluginLoader: " << e->d_name
cannam@56 93 << ": unable to load library (" << DLERROR()
cannam@56 94 << ")" << std::endl;
cannam@56 95 continue;
cannam@56 96 }
cannam@56 97
cannam@56 98 VampGetPluginDescriptorFunction fn =
cannam@56 99 (VampGetPluginDescriptorFunction)DLSYM
cannam@56 100 (handle, "vampGetPluginDescriptor");
cannam@56 101
cannam@56 102 if (!fn) {
cannam@56 103 DLCLOSE(handle);
cannam@56 104 continue;
cannam@56 105 }
cannam@56 106
cannam@56 107 int index = 0;
cannam@56 108 const VampPluginDescriptor *descriptor = 0;
cannam@56 109
cannam@56 110 while ((descriptor = fn(VAMP_API_VERSION, index))) {
cannam@56 111 PluginKey key = basename + ":" + descriptor->identifier;
cannam@56 112 if (m_pluginLibraryMap.find(key) ==
cannam@56 113 m_pluginLibraryMap.end()) {
cannam@56 114 m_pluginLibraryMap[key] = fullPath;
cannam@56 115 }
cannam@56 116 ++index;
cannam@56 117 }
cannam@56 118
cannam@56 119 DLCLOSE(handle);
cannam@56 120 }
cannam@56 121
cannam@56 122 closedir(d);
cannam@56 123 }
cannam@56 124 }
cannam@56 125
cannam@56 126 std::vector<PluginKey> plugins;
cannam@56 127 for (std::map<PluginKey, std::string>::iterator mi =
cannam@56 128 m_pluginLibraryMap.begin();
cannam@56 129 mi != m_pluginLibraryMap.end(); ++mi) {
cannam@56 130 plugins.push_back(mi->first);
cannam@56 131 }
cannam@56 132
cannam@56 133 return plugins;
cannam@56 134 }
cannam@56 135
cannam@56 136 std::string
cannam@56 137 PluginLoader::getLibraryPath(PluginKey key)
cannam@56 138 {
cannam@56 139 if (m_pluginLibraryMap.empty()) (void)listPlugins();
cannam@56 140 if (m_pluginLibraryMap.find(key) == m_pluginLibraryMap.end()) return "";
cannam@56 141 return m_pluginLibraryMap[key];
cannam@56 142 }
cannam@56 143
cannam@56 144 Plugin *
cannam@56 145 PluginLoader::load(PluginKey key, float inputSampleRate)
cannam@56 146 {
cannam@56 147 std::string fullPath = getLibraryPath(key);
cannam@56 148 if (fullPath == "") return 0;
cannam@56 149
cannam@56 150 std::string::size_type ki = key.find(':');
cannam@56 151 if (ki == std::string::npos) {
cannam@56 152 //!!! flag error
cannam@56 153 return 0;
cannam@56 154 }
cannam@56 155
cannam@56 156 std::string identifier = key.substr(ki + 1);
cannam@56 157
cannam@56 158 void *handle = DLOPEN(fullPath, RTLD_LAZY);
cannam@56 159
cannam@56 160 if (!handle) {
cannam@56 161 std::cerr << "Vamp::PluginLoader: " << fullPath
cannam@56 162 << ": unable to load library (" << DLERROR()
cannam@56 163 << ")" << std::endl;
cannam@56 164 return 0;
cannam@56 165 }
cannam@56 166
cannam@56 167 VampGetPluginDescriptorFunction fn =
cannam@56 168 (VampGetPluginDescriptorFunction)DLSYM
cannam@56 169 (handle, "vampGetPluginDescriptor");
cannam@56 170
cannam@56 171 if (!fn) {
cannam@56 172 //!!! refcount this! --!!! no, POSIX says dlopen/dlclose will
cannam@56 173 // reference count. check on win32
cannam@56 174 DLCLOSE(handle);
cannam@56 175 return 0;
cannam@56 176 }
cannam@56 177
cannam@56 178 int index = 0;
cannam@56 179 const VampPluginDescriptor *descriptor = 0;
cannam@56 180
cannam@56 181 while ((descriptor = fn(VAMP_API_VERSION, index))) {
cannam@56 182 if (std::string(descriptor->identifier) == identifier) {
cannam@56 183 return new Vamp::PluginHostAdapter(descriptor, inputSampleRate);
cannam@56 184 }
cannam@56 185 ++index;
cannam@56 186 }
cannam@56 187
cannam@56 188 //!!! flag error
cannam@56 189 return 0;
cannam@56 190 }
cannam@56 191
cannam@56 192 }
cannam@56 193