comparison vamp-sdk/hostext/PluginLoader.cpp @ 72:65add4f460e9

* make PluginLoader quicker to load a single named plugin (don't always have to bother enumerating them all first)
author cannam
date Wed, 06 Jun 2007 12:20:16 +0000
parents 64697dca0d48
children 6d16c376fd2f
comparison
equal deleted inserted replaced
71:64697dca0d48 72:65add4f460e9
67 namespace HostExt { 67 namespace HostExt {
68 68
69 class PluginLoader::Impl 69 class PluginLoader::Impl
70 { 70 {
71 public: 71 public:
72 virtual ~Impl() { } 72 Impl();
73 virtual ~Impl();
73 74
74 PluginKeyList listPlugins(); 75 PluginKeyList listPlugins();
75 76
76 Plugin *loadPlugin(PluginKey key, 77 Plugin *loadPlugin(PluginKey key,
77 float inputSampleRate, 78 float inputSampleRate,
79 80
80 PluginKey composePluginKey(string libraryName, string identifier); 81 PluginKey composePluginKey(string libraryName, string identifier);
81 82
82 PluginCategoryHierarchy getPluginCategory(PluginKey key); 83 PluginCategoryHierarchy getPluginCategory(PluginKey key);
83 84
84 std::string getLibraryPathForPlugin(PluginKey key); 85 string getLibraryPathForPlugin(PluginKey key);
85 86
86 protected: 87 protected:
87 class PluginDeletionNotifyAdapter : public PluginWrapper { 88 class PluginDeletionNotifyAdapter : public PluginWrapper {
88 public: 89 public:
89 PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader); 90 PluginDeletionNotifyAdapter(Plugin *plugin, Impl *loader);
92 Impl *m_loader; 93 Impl *m_loader;
93 }; 94 };
94 95
95 virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter); 96 virtual void pluginDeleted(PluginDeletionNotifyAdapter *adapter);
96 97
97 std::map<PluginKey, std::string> m_pluginLibraryNameMap; 98 map<PluginKey, string> m_pluginLibraryNameMap;
98 void generateLibraryMap(); 99 bool m_allPluginsEnumerated;
99 100 void enumeratePlugins(PluginKey forPlugin = "");
100 std::map<PluginKey, PluginCategoryHierarchy> m_taxonomy; 101
102 map<PluginKey, PluginCategoryHierarchy> m_taxonomy;
101 void generateTaxonomy(); 103 void generateTaxonomy();
102 104
103 std::map<Plugin *, void *> m_pluginLibraryHandleMap; 105 map<Plugin *, void *> m_pluginLibraryHandleMap;
104 106
105 void *loadLibrary(std::string path); 107 bool decomposePluginKey(PluginKey key,
108 string &libraryName, string &identifier);
109
110 void *loadLibrary(string path);
106 void unloadLibrary(void *handle); 111 void unloadLibrary(void *handle);
107 void *lookupInLibrary(void *handle, const char *symbol); 112 void *lookupInLibrary(void *handle, const char *symbol);
108 113
109 std::string splicePath(std::string a, std::string b); 114 string splicePath(string a, string b);
110 std::vector<std::string> listFiles(std::string dir, std::string ext); 115 vector<string> listFiles(string dir, string ext);
111 }; 116 };
112 117
113 PluginLoader * 118 PluginLoader *
114 PluginLoader::m_instance = 0; 119 PluginLoader::m_instance = 0;
115 120
159 string 164 string
160 PluginLoader::getLibraryPathForPlugin(PluginKey key) 165 PluginLoader::getLibraryPathForPlugin(PluginKey key)
161 { 166 {
162 return m_impl->getLibraryPathForPlugin(key); 167 return m_impl->getLibraryPathForPlugin(key);
163 } 168 }
169
170 PluginLoader::Impl::Impl() :
171 m_allPluginsEnumerated(false)
172 {
173 }
174
175 PluginLoader::Impl::~Impl()
176 {
177 }
164 178
165 vector<PluginLoader::PluginKey> 179 vector<PluginLoader::PluginKey>
166 PluginLoader::Impl::listPlugins() 180 PluginLoader::Impl::listPlugins()
167 { 181 {
168 if (m_pluginLibraryNameMap.empty()) generateLibraryMap(); 182 if (!m_allPluginsEnumerated) enumeratePlugins();
169 183
170 vector<PluginKey> plugins; 184 vector<PluginKey> plugins;
171 for (map<PluginKey, string>::iterator mi = 185 for (map<PluginKey, string>::iterator mi = m_pluginLibraryNameMap.begin();
172 m_pluginLibraryNameMap.begin();
173 mi != m_pluginLibraryNameMap.end(); ++mi) { 186 mi != m_pluginLibraryNameMap.end(); ++mi) {
174 plugins.push_back(mi->first); 187 plugins.push_back(mi->first);
175 } 188 }
176 189
177 return plugins; 190 return plugins;
178 } 191 }
179 192
180 void 193 void
181 PluginLoader::Impl::generateLibraryMap() 194 PluginLoader::Impl::enumeratePlugins(PluginKey forPlugin)
182 { 195 {
183 vector<string> path = PluginHostAdapter::getPluginPath(); 196 vector<string> path = PluginHostAdapter::getPluginPath();
197
198 string libraryName, identifier;
199 if (forPlugin != "") {
200 if (!decomposePluginKey(forPlugin, libraryName, identifier)) {
201 std::cerr << "WARNING: Vamp::HostExt::PluginLoader: Invalid plugin key \""
202 << forPlugin << "\" in enumerate" << std::endl;
203 return;
204 }
205 }
184 206
185 for (size_t i = 0; i < path.size(); ++i) { 207 for (size_t i = 0; i < path.size(); ++i) {
186 208
187 vector<string> files = listFiles(path[i], PLUGIN_SUFFIX); 209 vector<string> files = listFiles(path[i], PLUGIN_SUFFIX);
188 210
189 for (vector<string>::iterator fi = files.begin(); 211 for (vector<string>::iterator fi = files.begin();
190 fi != files.end(); ++fi) { 212 fi != files.end(); ++fi) {
191 213
214 if (libraryName != "") {
215 string::size_type pi = fi->find('.');
216 if (pi == string::npos) {
217 if (libraryName != *fi) continue;
218 } else {
219 if (libraryName != fi->substr(0, pi)) continue;
220 }
221 }
222
192 string fullPath = path[i]; 223 string fullPath = path[i];
193 fullPath = splicePath(fullPath, *fi); 224 fullPath = splicePath(fullPath, *fi);
194 void *handle = loadLibrary(fullPath); 225 void *handle = loadLibrary(fullPath);
195 if (!handle) continue; 226 if (!handle) continue;
196 227
205 236
206 int index = 0; 237 int index = 0;
207 const VampPluginDescriptor *descriptor = 0; 238 const VampPluginDescriptor *descriptor = 0;
208 239
209 while ((descriptor = fn(VAMP_API_VERSION, index))) { 240 while ((descriptor = fn(VAMP_API_VERSION, index))) {
241 ++index;
242 if (identifier != "") {
243 if (descriptor->identifier != identifier) continue;
244 }
210 PluginKey key = composePluginKey(*fi, descriptor->identifier); 245 PluginKey key = composePluginKey(*fi, descriptor->identifier);
246 // std::cerr << "enumerate: " << key << " (path: " << fullPath << ")" << std::endl;
211 if (m_pluginLibraryNameMap.find(key) == 247 if (m_pluginLibraryNameMap.find(key) ==
212 m_pluginLibraryNameMap.end()) { 248 m_pluginLibraryNameMap.end()) {
213 m_pluginLibraryNameMap[key] = fullPath; 249 m_pluginLibraryNameMap[key] = fullPath;
214 } 250 }
215 ++index;
216 } 251 }
217 252
218 unloadLibrary(handle); 253 unloadLibrary(handle);
219 } 254 }
220 } 255 }
256
257 if (forPlugin == "") m_allPluginsEnumerated = true;
221 } 258 }
222 259
223 PluginLoader::PluginKey 260 PluginLoader::PluginKey
224 PluginLoader::Impl::composePluginKey(string libraryName, string identifier) 261 PluginLoader::Impl::composePluginKey(string libraryName, string identifier)
225 { 262 {
263 //!!! deal with case issues
264
226 string basename = libraryName; 265 string basename = libraryName;
227 266
228 string::size_type li = basename.rfind('/'); 267 string::size_type li = basename.rfind('/');
229 if (li != string::npos) basename = basename.substr(li + 1); 268 if (li != string::npos) basename = basename.substr(li + 1);
230 269
231 li = basename.find('.'); 270 li = basename.find('.');
232 if (li != string::npos) basename = basename.substr(0, li); 271 if (li != string::npos) basename = basename.substr(0, li);
233 272
234 return basename + ":" + identifier; 273 return basename + ":" + identifier;
274 }
275
276 bool
277 PluginLoader::Impl::decomposePluginKey(PluginKey key,
278 string &libraryName,
279 string &identifier)
280 {
281 string::size_type ki = key.find(':');
282 if (ki == string::npos) {
283 return false;
284 }
285
286 libraryName = key.substr(0, ki);
287 identifier = key.substr(ki + 1);
288 return true;
235 } 289 }
236 290
237 PluginLoader::PluginCategoryHierarchy 291 PluginLoader::PluginCategoryHierarchy
238 PluginLoader::Impl::getPluginCategory(PluginKey plugin) 292 PluginLoader::Impl::getPluginCategory(PluginKey plugin)
239 { 293 {
245 } 299 }
246 300
247 string 301 string
248 PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin) 302 PluginLoader::Impl::getLibraryPathForPlugin(PluginKey plugin)
249 { 303 {
250 if (m_pluginLibraryNameMap.empty()) generateLibraryMap(); 304 if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
251 if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) return ""; 305 if (m_allPluginsEnumerated) return "";
306 enumeratePlugins(plugin);
307 }
308 if (m_pluginLibraryNameMap.find(plugin) == m_pluginLibraryNameMap.end()) {
309 return "";
310 }
252 return m_pluginLibraryNameMap[plugin]; 311 return m_pluginLibraryNameMap[plugin];
253 } 312 }
254 313
255 Plugin * 314 Plugin *
256 PluginLoader::Impl::loadPlugin(PluginKey key, 315 PluginLoader::Impl::loadPlugin(PluginKey key,
257 float inputSampleRate, int adapterFlags) 316 float inputSampleRate, int adapterFlags)
258 { 317 {
318 string libname, identifier;
319 if (!decomposePluginKey(key, libname, identifier)) {
320 std::cerr << "Vamp::HostExt::PluginLoader: Invalid plugin key \""
321 << key << "\" in loadPlugin" << std::endl;
322 return 0;
323 }
324
259 string fullPath = getLibraryPathForPlugin(key); 325 string fullPath = getLibraryPathForPlugin(key);
260 if (fullPath == "") return 0; 326 if (fullPath == "") return 0;
261
262 string::size_type ki = key.find(':');
263 if (ki == string::npos) {
264 //!!! flag error
265 return 0;
266 }
267
268 string identifier = key.substr(ki + 1);
269 327
270 void *handle = loadLibrary(fullPath); 328 void *handle = loadLibrary(fullPath);
271 if (!handle) return 0; 329 if (!handle) return 0;
272 330
273 VampGetPluginDescriptorFunction fn = 331 VampGetPluginDescriptorFunction fn =