Mercurial > hg > vamp-plugin-sdk
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 = |