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
|