part 2 of 3 of the 2.8 -> 3.0 merge
[ardour.git] / libs / vamp-sdk / src / vamp-hostsdk / 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 "vamp-hostsdk/PluginHostAdapter.h"
38 #include <cstdlib>
39
40 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
41 #error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
42 #endif
43
44 _VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
45
46 namespace Vamp
47 {
48
49 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
50                                      float inputSampleRate) :
51     Plugin(inputSampleRate),
52     m_descriptor(descriptor)
53 {
54 //    std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
55     m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
56     if (!m_handle) {
57 //        std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
58     }
59 }
60
61 PluginHostAdapter::~PluginHostAdapter()
62 {
63 //    std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
64     if (m_handle) m_descriptor->cleanup(m_handle);
65 }
66
67 std::vector<std::string>
68 PluginHostAdapter::getPluginPath()
69 {
70     std::vector<std::string> path;
71     std::string envPath;
72
73     char *cpath = getenv("VAMP_PATH");
74     if (cpath) envPath = cpath;
75
76 #ifdef _WIN32
77 #define PATH_SEPARATOR ';'
78 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
79 #else
80 #define PATH_SEPARATOR ':'
81 #ifdef __APPLE__
82 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
83 #else
84 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
85 #endif
86 #endif
87
88     if (envPath == "") {
89         envPath = DEFAULT_VAMP_PATH;
90         char *chome = getenv("HOME");
91         if (chome) {
92             std::string home(chome);
93             std::string::size_type f;
94             while ((f = envPath.find("$HOME")) != std::string::npos &&
95                     f < envPath.length()) {
96                 envPath.replace(f, 5, home);
97             }
98         }
99 #ifdef _WIN32
100         char *cpfiles = getenv("ProgramFiles");
101         if (!cpfiles) cpfiles = (char *)"C:\\Program Files";
102         std::string pfiles(cpfiles);
103         std::string::size_type f;
104         while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
105                f < envPath.length()) {
106             envPath.replace(f, 14, pfiles);
107         }
108 #endif
109     }
110
111     std::string::size_type index = 0, newindex = 0;
112
113     while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
114         path.push_back(envPath.substr(index, newindex - index));
115         index = newindex + 1;
116     }
117     
118     path.push_back(envPath.substr(index));
119
120     return path;
121 }
122
123 bool
124 PluginHostAdapter::initialise(size_t channels,
125                               size_t stepSize,
126                               size_t blockSize)
127 {
128     if (!m_handle) return false;
129     return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
130         true : false;
131 }
132
133 void
134 PluginHostAdapter::reset()
135 {
136     if (!m_handle) {
137 //        std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
138         return;
139     }
140 //    std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
141     m_descriptor->reset(m_handle);
142 }
143
144 PluginHostAdapter::InputDomain
145 PluginHostAdapter::getInputDomain() const
146 {
147     if (m_descriptor->inputDomain == vampFrequencyDomain) {
148         return FrequencyDomain;
149     } else {
150         return TimeDomain;
151     }
152 }
153
154 unsigned int
155 PluginHostAdapter::getVampApiVersion() const
156 {
157     return m_descriptor->vampApiVersion;
158 }
159
160 std::string
161 PluginHostAdapter::getIdentifier() const
162 {
163     return m_descriptor->identifier;
164 }
165
166 std::string
167 PluginHostAdapter::getName() const
168 {
169     return m_descriptor->name;
170 }
171
172 std::string
173 PluginHostAdapter::getDescription() const
174 {
175     return m_descriptor->description;
176 }
177
178 std::string
179 PluginHostAdapter::getMaker() const
180 {
181     return m_descriptor->maker;
182 }
183
184 int
185 PluginHostAdapter::getPluginVersion() const
186 {
187     return m_descriptor->pluginVersion;
188 }
189
190 std::string
191 PluginHostAdapter::getCopyright() const
192 {
193     return m_descriptor->copyright;
194 }
195
196 PluginHostAdapter::ParameterList
197 PluginHostAdapter::getParameterDescriptors() const
198 {
199     ParameterList list;
200     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
201         const VampParameterDescriptor *spd = m_descriptor->parameters[i];
202         ParameterDescriptor pd;
203         pd.identifier = spd->identifier;
204         pd.name = spd->name;
205         pd.description = spd->description;
206         pd.unit = spd->unit;
207         pd.minValue = spd->minValue;
208         pd.maxValue = spd->maxValue;
209         pd.defaultValue = spd->defaultValue;
210         pd.isQuantized = spd->isQuantized;
211         pd.quantizeStep = spd->quantizeStep;
212         if (pd.isQuantized && spd->valueNames) {
213             for (unsigned int j = 0; spd->valueNames[j]; ++j) {
214                 pd.valueNames.push_back(spd->valueNames[j]);
215             }
216         }
217         list.push_back(pd);
218     }
219     return list;
220 }
221
222 float
223 PluginHostAdapter::getParameter(std::string param) const
224 {
225     if (!m_handle) return 0.0;
226
227     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
228         if (param == m_descriptor->parameters[i]->identifier) {
229             return m_descriptor->getParameter(m_handle, i);
230         }
231     }
232
233     return 0.0;
234 }
235
236 void
237 PluginHostAdapter::setParameter(std::string param, 
238                                 float value)
239 {
240     if (!m_handle) return;
241
242     for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
243         if (param == m_descriptor->parameters[i]->identifier) {
244             m_descriptor->setParameter(m_handle, i, value);
245             return;
246         }
247     }
248 }
249
250 PluginHostAdapter::ProgramList
251 PluginHostAdapter::getPrograms() const
252 {
253     ProgramList list;
254     
255     for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
256         list.push_back(m_descriptor->programs[i]);
257     }
258     
259     return list;
260 }
261
262 std::string
263 PluginHostAdapter::getCurrentProgram() const
264 {
265     if (!m_handle) return "";
266
267     int pn = m_descriptor->getCurrentProgram(m_handle);
268     return m_descriptor->programs[pn];
269 }
270
271 void
272 PluginHostAdapter::selectProgram(std::string program)
273 {
274     if (!m_handle) return;
275
276     for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
277         if (program == m_descriptor->programs[i]) {
278             m_descriptor->selectProgram(m_handle, i);
279             return;
280         }
281     }
282 }
283
284 size_t
285 PluginHostAdapter::getPreferredStepSize() const
286 {
287     if (!m_handle) return 0;
288     return m_descriptor->getPreferredStepSize(m_handle);
289 }
290
291 size_t
292 PluginHostAdapter::getPreferredBlockSize() const
293 {
294     if (!m_handle) return 0;
295     return m_descriptor->getPreferredBlockSize(m_handle);
296 }
297
298 size_t
299 PluginHostAdapter::getMinChannelCount() const
300 {
301     if (!m_handle) return 0;
302     return m_descriptor->getMinChannelCount(m_handle);
303 }
304
305 size_t
306 PluginHostAdapter::getMaxChannelCount() const
307 {
308     if (!m_handle) return 0;
309     return m_descriptor->getMaxChannelCount(m_handle);
310 }
311
312 PluginHostAdapter::OutputList
313 PluginHostAdapter::getOutputDescriptors() const
314 {
315     OutputList list;
316     if (!m_handle) {
317 //        std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
318         return list;
319     }
320
321     unsigned int count = m_descriptor->getOutputCount(m_handle);
322
323     for (unsigned int i = 0; i < count; ++i) {
324         VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
325         OutputDescriptor d;
326         d.identifier = sd->identifier;
327         d.name = sd->name;
328         d.description = sd->description;
329         d.unit = sd->unit;
330         d.hasFixedBinCount = sd->hasFixedBinCount;
331         d.binCount = sd->binCount;
332         if (d.hasFixedBinCount && sd->binNames) {
333             for (unsigned int j = 0; j < sd->binCount; ++j) {
334                 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
335             }
336         }
337         d.hasKnownExtents = sd->hasKnownExtents;
338         d.minValue = sd->minValue;
339         d.maxValue = sd->maxValue;
340         d.isQuantized = sd->isQuantized;
341         d.quantizeStep = sd->quantizeStep;
342
343         switch (sd->sampleType) {
344         case vampOneSamplePerStep:
345             d.sampleType = OutputDescriptor::OneSamplePerStep; break;
346         case vampFixedSampleRate:
347             d.sampleType = OutputDescriptor::FixedSampleRate; break;
348         case vampVariableSampleRate:
349             d.sampleType = OutputDescriptor::VariableSampleRate; break;
350         }
351
352         d.sampleRate = sd->sampleRate;
353
354         if (m_descriptor->vampApiVersion >= 2) {
355             d.hasDuration = sd->hasDuration;
356         } else {
357             d.hasDuration = false;
358         }
359
360         list.push_back(d);
361
362         m_descriptor->releaseOutputDescriptor(sd);
363     }
364
365     return list;
366 }
367
368 PluginHostAdapter::FeatureSet
369 PluginHostAdapter::process(const float *const *inputBuffers,
370                            RealTime timestamp)
371 {
372     FeatureSet fs;
373     if (!m_handle) return fs;
374
375     int sec = timestamp.sec;
376     int nsec = timestamp.nsec;
377     
378     VampFeatureList *features = m_descriptor->process(m_handle,
379                                                       inputBuffers,
380                                                       sec, nsec);
381     
382     convertFeatures(features, fs);
383     m_descriptor->releaseFeatureSet(features);
384     return fs;
385 }
386
387 PluginHostAdapter::FeatureSet
388 PluginHostAdapter::getRemainingFeatures()
389 {
390     FeatureSet fs;
391     if (!m_handle) return fs;
392     
393     VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle); 
394
395     convertFeatures(features, fs);
396     m_descriptor->releaseFeatureSet(features);
397     return fs;
398 }
399
400 void
401 PluginHostAdapter::convertFeatures(VampFeatureList *features,
402                                    FeatureSet &fs)
403 {
404     if (!features) return;
405
406     unsigned int outputs = m_descriptor->getOutputCount(m_handle);
407
408     for (unsigned int i = 0; i < outputs; ++i) {
409         
410         VampFeatureList &list = features[i];
411
412         if (list.featureCount > 0) {
413
414             Feature feature;
415             feature.values.reserve(list.features[0].v1.valueCount);
416
417             for (unsigned int j = 0; j < list.featureCount; ++j) {
418
419                 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
420                 feature.timestamp = RealTime(list.features[j].v1.sec,
421                                              list.features[j].v1.nsec);
422                 feature.hasDuration = false;
423
424                 if (m_descriptor->vampApiVersion >= 2) {
425                     unsigned int j2 = j + list.featureCount;
426                     feature.hasDuration = list.features[j2].v2.hasDuration;
427                     feature.duration = RealTime(list.features[j2].v2.durationSec,
428                                                 list.features[j2].v2.durationNsec);
429                 }
430
431                 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
432                     feature.values.push_back(list.features[j].v1.values[k]);
433                 }
434
435                 if (list.features[j].v1.label) {
436                     feature.label = list.features[j].v1.label;
437                 }
438
439                 fs[i].push_back(feature);
440
441                 if (list.features[j].v1.valueCount > 0) {
442                     feature.values.clear();
443                 }
444
445                 if (list.features[j].v1.label) {
446                     feature.label = "";
447                 }
448             }
449         }
450     }
451 }
452
453 }
454
455 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
456