12e15393fc4da33659b7e9e70ad61cddfcb35d81
[ardour.git] / libs / vamp-sdk / vamp-sdk / PluginHostAdapter.cpp
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2
3 /*
4     Vamp
5
6     An API for audio analysis and feature extraction plugins.
7
8     Centre for Digital Music, Queen Mary, University of London.
9     Copyright 2006 Chris Cannam.
10   
11     Permission is hereby granted, free of charge, to any person
12     obtaining a copy of this software and associated documentation
13     files (the "Software"), to deal in the Software without
14     restriction, including without limitation the rights to use, copy,
15     modify, merge, publish, distribute, sublicense, and/or sell copies
16     of the Software, and to permit persons to whom the Software is
17     furnished to do so, subject to the following conditions:
18
19     The above copyright notice and this permission notice shall be
20     included in all copies or substantial portions of the Software.
21
22     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30     Except as contained in this notice, the names of the Centre for
31     Digital Music; Queen Mary, University of London; and Chris Cannam
32     shall not be used in advertising or otherwise to promote the sale,
33     use or other dealings in this Software without prior written
34     authorization.
35 */
36
37 #include "PluginHostAdapter.h"
38
39 namespace Vamp
40 {
41
42 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
43                                      float inputSampleRate) :
44     Plugin(inputSampleRate),
45     m_descriptor(descriptor)
46 {
47 //    std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
48     m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
49     if (!m_handle) {
50 //        std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
51     }
52 }
53
54 PluginHostAdapter::~PluginHostAdapter()
55 {
56 //    std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
57     if (m_handle) m_descriptor->cleanup(m_handle);
58 }
59
60 std::vector<std::string>
61 PluginHostAdapter::getPluginPath()
62 {
63     std::vector<std::string> path;
64     std::string envPath;
65
66     char *cpath = getenv("VAMP_PATH");
67     if (cpath) envPath = cpath;
68
69 #ifdef _WIN32
70 #define PATH_SEPARATOR ';'
71 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
72 #else
73 #define PATH_SEPARATOR ':'
74 #ifdef __APPLE__
75 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
76 #else
77 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
78 #endif
79 #endif
80
81     if (envPath == "") {
82         envPath = DEFAULT_VAMP_PATH;
83         char *chome = getenv("HOME");
84         if (chome) {
85             std::string home(chome);
86             std::string::size_type f;
87             while ((f = envPath.find("$HOME")) != std::string::npos &&
88                     f < envPath.length()) {
89                 envPath.replace(f, 5, home);
90             }
91         }
92 #ifdef _WIN32
93         char *cpfiles = getenv("ProgramFiles");
94         if (!cpfiles) cpfiles = "C:\\Program Files";
95         std::string pfiles(cpfiles);
96         std::string::size_type f;
97         while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
98                f < envPath.length()) {
99             envPath.replace(f, 14, pfiles);
100         }
101 #endif
102     }
103
104     std::string::size_type index = 0, newindex = 0;
105
106     while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
107         path.push_back(envPath.substr(index, newindex - index));
108         index = newindex + 1;
109     }
110     
111     path.push_back(envPath.substr(index));
112
113     return path;
114 }
115
116 bool
117 PluginHostAdapter::initialise(size_t channels,
118                               size_t stepSize,
119                               size_t blockSize)
120 {
121     if (!m_handle) return false;
122     return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
123         true : false;
124 }
125
126 void
127 PluginHostAdapter::reset()
128 {
129     if (!m_handle) return;
130     m_descriptor->reset(m_handle);
131 }
132
133 PluginHostAdapter::InputDomain
134 PluginHostAdapter::getInputDomain() const
135 {
136     if (m_descriptor->inputDomain == vampFrequencyDomain) {
137         return FrequencyDomain;
138     } else {
139         return TimeDomain;
140     }
141 }
142
143 unsigned int
144 PluginHostAdapter::getVampApiVersion() const
145 {
146     return m_descriptor->vampApiVersion;
147 }
148
149 std::string
150 PluginHostAdapter::getIdentifier() const
151 {
152     return m_descriptor->identifier;
153 }
154
155 std::string
156 PluginHostAdapter::getName() const
157 {
158     return m_descriptor->name;
159 }
160
161 std::string
162 PluginHostAdapter::getDescription() const
163 {
164     return m_descriptor->description;
165 }
166
167 std::string
168 PluginHostAdapter::getMaker() const
169 {
170     return m_descriptor->maker;
171 }
172
173 int
174 PluginHostAdapter::getPluginVersion() const
175 {
176     return m_descriptor->pluginVersion;
177 }
178
179 std::string
180 PluginHostAdapter::getCopyright() const
181 {
182     return m_descriptor->copyright;
183 }
184
185 PluginHostAdapter::ParameterList
186 PluginHostAdapter::getParameterDescriptors() const
187 {
188     ParameterList list;
189     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
190         const VampParameterDescriptor *spd = m_descriptor->parameters[i];
191         ParameterDescriptor pd;
192         pd.identifier = spd->identifier;
193         pd.name = spd->name;
194         pd.description = spd->description;
195         pd.unit = spd->unit;
196         pd.minValue = spd->minValue;
197         pd.maxValue = spd->maxValue;
198         pd.defaultValue = spd->defaultValue;
199         pd.isQuantized = spd->isQuantized;
200         pd.quantizeStep = spd->quantizeStep;
201         if (pd.isQuantized && spd->valueNames) {
202             for (unsigned int j = 0; spd->valueNames[j]; ++j) {
203                 pd.valueNames.push_back(spd->valueNames[j]);
204             }
205         }
206         list.push_back(pd);
207     }
208     return list;
209 }
210
211 float
212 PluginHostAdapter::getParameter(std::string param) const
213 {
214     if (!m_handle) return 0.0;
215
216     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
217         if (param == m_descriptor->parameters[i]->identifier) {
218             return m_descriptor->getParameter(m_handle, i);
219         }
220     }
221
222     return 0.0;
223 }
224
225 void
226 PluginHostAdapter::setParameter(std::string param, 
227                                 float value)
228 {
229     if (!m_handle) return;
230
231     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
232         if (param == m_descriptor->parameters[i]->identifier) {
233             m_descriptor->setParameter(m_handle, i, value);
234             return;
235         }
236     }
237 }
238
239 PluginHostAdapter::ProgramList
240 PluginHostAdapter::getPrograms() const
241 {
242     ProgramList list;
243     
244     for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
245         list.push_back(m_descriptor->programs[i]);
246     }
247     
248     return list;
249 }
250
251 std::string
252 PluginHostAdapter::getCurrentProgram() const
253 {
254     if (!m_handle) return "";
255
256     int pn = m_descriptor->getCurrentProgram(m_handle);
257     return m_descriptor->programs[pn];
258 }
259
260 void
261 PluginHostAdapter::selectProgram(std::string program)
262 {
263     if (!m_handle) return;
264
265     for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
266         if (program == m_descriptor->programs[i]) {
267             m_descriptor->selectProgram(m_handle, i);
268             return;
269         }
270     }
271 }
272
273 size_t
274 PluginHostAdapter::getPreferredStepSize() const
275 {
276     if (!m_handle) return 0;
277     return m_descriptor->getPreferredStepSize(m_handle);
278 }
279
280 size_t
281 PluginHostAdapter::getPreferredBlockSize() const
282 {
283     if (!m_handle) return 0;
284     return m_descriptor->getPreferredBlockSize(m_handle);
285 }
286
287 size_t
288 PluginHostAdapter::getMinChannelCount() const
289 {
290     if (!m_handle) return 0;
291     return m_descriptor->getMinChannelCount(m_handle);
292 }
293
294 size_t
295 PluginHostAdapter::getMaxChannelCount() const
296 {
297     if (!m_handle) return 0;
298     return m_descriptor->getMaxChannelCount(m_handle);
299 }
300
301 PluginHostAdapter::OutputList
302 PluginHostAdapter::getOutputDescriptors() const
303 {
304     OutputList list;
305     if (!m_handle) {
306 //        std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
307         return list;
308     }
309
310     unsigned int count = m_descriptor->getOutputCount(m_handle);
311
312     for (unsigned int i = 0; i < count; ++i) {
313         VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
314         OutputDescriptor d;
315         d.identifier = sd->identifier;
316         d.name = sd->name;
317         d.description = sd->description;
318         d.unit = sd->unit;
319         d.hasFixedBinCount = sd->hasFixedBinCount;
320         d.binCount = sd->binCount;
321         if (d.hasFixedBinCount) {
322             for (unsigned int j = 0; j < sd->binCount; ++j) {
323                 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
324             }
325         }
326         d.hasKnownExtents = sd->hasKnownExtents;
327         d.minValue = sd->minValue;
328         d.maxValue = sd->maxValue;
329         d.isQuantized = sd->isQuantized;
330         d.quantizeStep = sd->quantizeStep;
331
332         switch (sd->sampleType) {
333         case vampOneSamplePerStep:
334             d.sampleType = OutputDescriptor::OneSamplePerStep; break;
335         case vampFixedSampleRate:
336             d.sampleType = OutputDescriptor::FixedSampleRate; break;
337         case vampVariableSampleRate:
338             d.sampleType = OutputDescriptor::VariableSampleRate; break;
339         }
340
341         d.sampleRate = sd->sampleRate;
342
343         list.push_back(d);
344
345         m_descriptor->releaseOutputDescriptor(sd);
346     }
347
348     return list;
349 }
350
351 PluginHostAdapter::FeatureSet
352 PluginHostAdapter::process(const float *const *inputBuffers,
353                            RealTime timestamp)
354 {
355     FeatureSet fs;
356     if (!m_handle) return fs;
357
358     int sec = timestamp.sec;
359     int nsec = timestamp.nsec;
360     
361     VampFeatureList *features = m_descriptor->process(m_handle,
362                                                       inputBuffers,
363                                                       sec, nsec);
364     
365     convertFeatures(features, fs);
366     m_descriptor->releaseFeatureSet(features);
367     return fs;
368 }
369
370 PluginHostAdapter::FeatureSet
371 PluginHostAdapter::getRemainingFeatures()
372 {
373     FeatureSet fs;
374     if (!m_handle) return fs;
375     
376     VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle); 
377
378     convertFeatures(features, fs);
379     m_descriptor->releaseFeatureSet(features);
380     return fs;
381 }
382
383 void
384 PluginHostAdapter::convertFeatures(VampFeatureList *features,
385                                    FeatureSet &fs)
386 {
387     if (!features) return;
388
389     unsigned int outputs = m_descriptor->getOutputCount(m_handle);
390
391     for (unsigned int i = 0; i < outputs; ++i) {
392         
393         VampFeatureList &list = features[i];
394
395         if (list.featureCount > 0) {
396
397             for (unsigned int j = 0; j < list.featureCount; ++j) {
398                 
399                 Feature feature;
400                 feature.hasTimestamp = list.features[j].hasTimestamp;
401                 feature.timestamp = RealTime(list.features[j].sec,
402                                              list.features[j].nsec);
403
404                 for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
405                     feature.values.push_back(list.features[j].values[k]);
406                 }
407
408                 if (list.features[j].label) {
409                     feature.label = list.features[j].label;
410                 }
411
412                 fs[i].push_back(feature);
413             }
414         }
415     }
416 }
417
418 }