merge new directory/file structure from newer vamp version via 2.0 (3993:4905)
[ardour.git] / libs / vamp-sdk / src / vamp-sdk / PluginAdapter.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-sdk/PluginAdapter.h>
38
39 #include <cstring>
40 #include <cstdlib>
41
42 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 0 )
43 #error Incorrect Vamp SDK header included (not the expected 2.0 SDK)
44 #endif
45
46
47 //#define DEBUG_PLUGIN_ADAPTER 1
48
49 _VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.cpp)
50
51 namespace Vamp {
52
53 class PluginAdapterBase::Impl
54 {
55 public:
56     Impl(PluginAdapterBase *);
57     ~Impl();
58
59     const VampPluginDescriptor *getDescriptor();
60
61 protected:
62     PluginAdapterBase *m_base;
63
64     static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
65                                             float inputSampleRate);
66
67     static void vampCleanup(VampPluginHandle handle);
68
69     static int vampInitialise(VampPluginHandle handle, unsigned int channels,
70                              unsigned int stepSize, unsigned int blockSize);
71
72     static void vampReset(VampPluginHandle handle);
73
74     static float vampGetParameter(VampPluginHandle handle, int param);
75     static void vampSetParameter(VampPluginHandle handle, int param, float value);
76
77     static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
78     static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
79
80     static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
81     static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
82     static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
83     static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
84
85     static unsigned int vampGetOutputCount(VampPluginHandle handle);
86
87     static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
88                                                        unsigned int i);
89
90     static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
91
92     static VampFeatureList *vampProcess(VampPluginHandle handle,
93                                         const float *const *inputBuffers,
94                                         int sec,
95                                         int nsec);
96
97     static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
98
99     static void vampReleaseFeatureSet(VampFeatureList *fs);
100
101     void checkOutputMap(Plugin *plugin);
102     void markOutputsChanged(Plugin *plugin);
103
104     void cleanup(Plugin *plugin);
105     unsigned int getOutputCount(Plugin *plugin);
106     VampOutputDescriptor *getOutputDescriptor(Plugin *plugin,
107                                              unsigned int i);
108     VampFeatureList *process(Plugin *plugin,
109                              const float *const *inputBuffers,
110                              int sec, int nsec);
111     VampFeatureList *getRemainingFeatures(Plugin *plugin);
112     VampFeatureList *convertFeatures(Plugin *plugin,
113                                      const Plugin::FeatureSet &features);
114     
115     // maps both plugins and descriptors to adapters
116     typedef std::map<const void *, Impl *> AdapterMap;
117     static AdapterMap *m_adapterMap;
118     static Impl *lookupAdapter(VampPluginHandle);
119
120     bool m_populated;
121     VampPluginDescriptor m_descriptor;
122     Plugin::ParameterList m_parameters;
123     Plugin::ProgramList m_programs;
124     
125     typedef std::map<Plugin *, Plugin::OutputList *> OutputMap;
126     OutputMap m_pluginOutputs;
127
128     std::map<Plugin *, VampFeatureList *> m_fs;
129     std::map<Plugin *, std::vector<size_t> > m_fsizes;
130     std::map<Plugin *, std::vector<std::vector<size_t> > > m_fvsizes;
131     void resizeFS(Plugin *plugin, int n);
132     void resizeFL(Plugin *plugin, int n, size_t sz);
133     void resizeFV(Plugin *plugin, int n, int j, size_t sz);
134 };
135
136 PluginAdapterBase::PluginAdapterBase()
137 {
138     m_impl = new Impl(this);
139 }
140
141 PluginAdapterBase::~PluginAdapterBase()
142 {
143     delete m_impl;
144 }
145
146 const VampPluginDescriptor *
147 PluginAdapterBase::getDescriptor()
148 {
149     return m_impl->getDescriptor();
150 }
151
152 PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
153     m_base(base),
154     m_populated(false)
155 {
156 #ifdef DEBUG_PLUGIN_ADAPTER
157     std::cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << std::endl;
158 #endif
159 }
160
161 const VampPluginDescriptor *
162 PluginAdapterBase::Impl::getDescriptor()
163 {
164 #ifdef DEBUG_PLUGIN_ADAPTER
165     std::cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << std::endl;
166 #endif
167
168     if (m_populated) return &m_descriptor;
169
170     Plugin *plugin = m_base->createPlugin(48000);
171
172     if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
173         std::cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
174                   << "API version " << plugin->getVampApiVersion()
175                   << " for\nplugin \"" << plugin->getIdentifier() << "\" "
176                   << "differs from version "
177                   << VAMP_API_VERSION << " for adapter.\n"
178                   << "This plugin is probably linked against a different version of the Vamp SDK\n"
179                   << "from the version it was compiled with.  It will need to be re-linked correctly\n"
180                   << "before it can be used." << std::endl;
181         delete plugin;
182         return 0;
183     }
184
185     m_parameters = plugin->getParameterDescriptors();
186     m_programs = plugin->getPrograms();
187
188     m_descriptor.vampApiVersion = plugin->getVampApiVersion();
189     m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
190     m_descriptor.name = strdup(plugin->getName().c_str());
191     m_descriptor.description = strdup(plugin->getDescription().c_str());
192     m_descriptor.maker = strdup(plugin->getMaker().c_str());
193     m_descriptor.pluginVersion = plugin->getPluginVersion();
194     m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
195     
196     m_descriptor.parameterCount = m_parameters.size();
197     m_descriptor.parameters = (const VampParameterDescriptor **)
198         malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
199
200     unsigned int i;
201     
202     for (i = 0; i < m_parameters.size(); ++i) {
203         VampParameterDescriptor *desc = (VampParameterDescriptor *)
204             malloc(sizeof(VampParameterDescriptor));
205         desc->identifier = strdup(m_parameters[i].identifier.c_str());
206         desc->name = strdup(m_parameters[i].name.c_str());
207         desc->description = strdup(m_parameters[i].description.c_str());
208         desc->unit = strdup(m_parameters[i].unit.c_str());
209         desc->minValue = m_parameters[i].minValue;
210         desc->maxValue = m_parameters[i].maxValue;
211         desc->defaultValue = m_parameters[i].defaultValue;
212         desc->isQuantized = m_parameters[i].isQuantized;
213         desc->quantizeStep = m_parameters[i].quantizeStep;
214         desc->valueNames = 0;
215         if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
216             desc->valueNames = (const char **)
217                 malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
218             for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
219                 desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
220             }
221             desc->valueNames[m_parameters[i].valueNames.size()] = 0;
222         }
223         m_descriptor.parameters[i] = desc;
224     }
225     
226     m_descriptor.programCount = m_programs.size();
227     m_descriptor.programs = (const char **)
228         malloc(m_programs.size() * sizeof(const char *));
229     
230     for (i = 0; i < m_programs.size(); ++i) {
231         m_descriptor.programs[i] = strdup(m_programs[i].c_str());
232     }
233     
234     if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
235         m_descriptor.inputDomain = vampFrequencyDomain;
236     } else {
237         m_descriptor.inputDomain = vampTimeDomain;
238     }
239
240     m_descriptor.instantiate = vampInstantiate;
241     m_descriptor.cleanup = vampCleanup;
242     m_descriptor.initialise = vampInitialise;
243     m_descriptor.reset = vampReset;
244     m_descriptor.getParameter = vampGetParameter;
245     m_descriptor.setParameter = vampSetParameter;
246     m_descriptor.getCurrentProgram = vampGetCurrentProgram;
247     m_descriptor.selectProgram = vampSelectProgram;
248     m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
249     m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
250     m_descriptor.getMinChannelCount = vampGetMinChannelCount;
251     m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
252     m_descriptor.getOutputCount = vampGetOutputCount;
253     m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
254     m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
255     m_descriptor.process = vampProcess;
256     m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
257     m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
258     
259     if (!m_adapterMap) {
260         m_adapterMap = new AdapterMap;
261     }
262     (*m_adapterMap)[&m_descriptor] = this;
263
264     delete plugin;
265
266     m_populated = true;
267     return &m_descriptor;
268 }
269
270 PluginAdapterBase::Impl::~Impl()
271 {
272 #ifdef DEBUG_PLUGIN_ADAPTER
273     std::cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << std::endl;
274 #endif
275
276     if (!m_populated) return;
277
278     free((void *)m_descriptor.identifier);
279     free((void *)m_descriptor.name);
280     free((void *)m_descriptor.description);
281     free((void *)m_descriptor.maker);
282     free((void *)m_descriptor.copyright);
283         
284     for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
285         const VampParameterDescriptor *desc = m_descriptor.parameters[i];
286         free((void *)desc->identifier);
287         free((void *)desc->name);
288         free((void *)desc->description);
289         free((void *)desc->unit);
290         if (desc->valueNames) {
291             for (unsigned int j = 0; desc->valueNames[j]; ++j) {
292                 free((void *)desc->valueNames[j]);
293             }
294             free((void *)desc->valueNames);
295         }
296     }
297     free((void *)m_descriptor.parameters);
298
299     for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
300         free((void *)m_descriptor.programs[i]);
301     }
302     free((void *)m_descriptor.programs);
303
304     if (m_adapterMap) {
305         
306         m_adapterMap->erase(&m_descriptor);
307
308         if (m_adapterMap->empty()) {
309             delete m_adapterMap;
310             m_adapterMap = 0;
311         }
312     }
313 }
314
315 PluginAdapterBase::Impl *
316 PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
317 {
318 #ifdef DEBUG_PLUGIN_ADAPTER
319     std::cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << std::endl;
320 #endif
321
322     if (!m_adapterMap) return 0;
323     AdapterMap::const_iterator i = m_adapterMap->find(handle);
324     if (i == m_adapterMap->end()) return 0;
325     return i->second;
326 }
327
328 VampPluginHandle
329 PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
330                                          float inputSampleRate)
331 {
332 #ifdef DEBUG_PLUGIN_ADAPTER
333     std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << std::endl;
334 #endif
335
336     if (!m_adapterMap) {
337         m_adapterMap = new AdapterMap();
338     }
339
340     if (m_adapterMap->find(desc) == m_adapterMap->end()) {
341         std::cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << std::endl;
342         return 0;
343     }
344
345     Impl *adapter = (*m_adapterMap)[desc];
346     if (desc != &adapter->m_descriptor) return 0;
347
348     Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
349     if (plugin) {
350         (*m_adapterMap)[plugin] = adapter;
351     }
352
353 #ifdef DEBUG_PLUGIN_ADAPTER
354     std::cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << std::endl;
355 #endif
356
357     return plugin;
358 }
359
360 void
361 PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
362 {
363 #ifdef DEBUG_PLUGIN_ADAPTER
364     std::cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << std::endl;
365 #endif
366
367     Impl *adapter = lookupAdapter(handle);
368     if (!adapter) {
369         delete ((Plugin *)handle);
370         return;
371     }
372     adapter->cleanup(((Plugin *)handle));
373 }
374
375 int
376 PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
377                                         unsigned int channels,
378                                         unsigned int stepSize,
379                                         unsigned int blockSize)
380 {
381 #ifdef DEBUG_PLUGIN_ADAPTER
382     std::cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << std::endl;
383 #endif
384
385     Impl *adapter = lookupAdapter(handle);
386     if (!adapter) return 0;
387     bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize);
388     adapter->markOutputsChanged((Plugin *)handle);
389     return result ? 1 : 0;
390 }
391
392 void
393 PluginAdapterBase::Impl::vampReset(VampPluginHandle handle) 
394 {
395 #ifdef DEBUG_PLUGIN_ADAPTER
396     std::cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << std::endl;
397 #endif
398
399     ((Plugin *)handle)->reset();
400 }
401
402 float
403 PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
404                                     int param) 
405 {
406 #ifdef DEBUG_PLUGIN_ADAPTER
407     std::cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << std::endl;
408 #endif
409
410     Impl *adapter = lookupAdapter(handle);
411     if (!adapter) return 0.0;
412     Plugin::ParameterList &list = adapter->m_parameters;
413     return ((Plugin *)handle)->getParameter(list[param].identifier);
414 }
415
416 void
417 PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
418                                     int param, float value)
419 {
420 #ifdef DEBUG_PLUGIN_ADAPTER
421     std::cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << std::endl;
422 #endif
423
424     Impl *adapter = lookupAdapter(handle);
425     if (!adapter) return;
426     Plugin::ParameterList &list = adapter->m_parameters;
427     ((Plugin *)handle)->setParameter(list[param].identifier, value);
428     adapter->markOutputsChanged((Plugin *)handle);
429 }
430
431 unsigned int
432 PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
433 {
434 #ifdef DEBUG_PLUGIN_ADAPTER
435     std::cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << std::endl;
436 #endif
437
438     Impl *adapter = lookupAdapter(handle);
439     if (!adapter) return 0;
440     Plugin::ProgramList &list = adapter->m_programs;
441     std::string program = ((Plugin *)handle)->getCurrentProgram();
442     for (unsigned int i = 0; i < list.size(); ++i) {
443         if (list[i] == program) return i;
444     }
445     return 0;
446 }
447
448 void
449 PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
450                                            unsigned int program)
451 {
452 #ifdef DEBUG_PLUGIN_ADAPTER
453     std::cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << std::endl;
454 #endif
455
456     Impl *adapter = lookupAdapter(handle);
457     if (!adapter) return;
458
459     Plugin::ProgramList &list = adapter->m_programs;
460     ((Plugin *)handle)->selectProgram(list[program]);
461
462     adapter->markOutputsChanged((Plugin *)handle);
463 }
464
465 unsigned int
466 PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
467 {
468 #ifdef DEBUG_PLUGIN_ADAPTER
469     std::cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << std::endl;
470 #endif
471
472     return ((Plugin *)handle)->getPreferredStepSize();
473 }
474
475 unsigned int
476 PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle) 
477 {
478 #ifdef DEBUG_PLUGIN_ADAPTER
479     std::cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << std::endl;
480 #endif
481
482     return ((Plugin *)handle)->getPreferredBlockSize();
483 }
484
485 unsigned int
486 PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
487 {
488 #ifdef DEBUG_PLUGIN_ADAPTER
489     std::cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << std::endl;
490 #endif
491
492     return ((Plugin *)handle)->getMinChannelCount();
493 }
494
495 unsigned int
496 PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
497 {
498 #ifdef DEBUG_PLUGIN_ADAPTER
499     std::cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << std::endl;
500 #endif
501
502     return ((Plugin *)handle)->getMaxChannelCount();
503 }
504
505 unsigned int
506 PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
507 {
508 #ifdef DEBUG_PLUGIN_ADAPTER
509     std::cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << std::endl;
510 #endif
511
512     Impl *adapter = lookupAdapter(handle);
513
514 //    std::cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << std::endl;
515
516     if (!adapter) return 0;
517     return adapter->getOutputCount((Plugin *)handle);
518 }
519
520 VampOutputDescriptor *
521 PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
522                                                  unsigned int i)
523 {
524 #ifdef DEBUG_PLUGIN_ADAPTER
525     std::cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << std::endl;
526 #endif
527
528     Impl *adapter = lookupAdapter(handle);
529
530 //    std::cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << std::endl;
531
532     if (!adapter) return 0;
533     return adapter->getOutputDescriptor((Plugin *)handle, i);
534 }
535
536 void
537 PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
538 {
539 #ifdef DEBUG_PLUGIN_ADAPTER
540     std::cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << std::endl;
541 #endif
542
543     if (desc->identifier) free((void *)desc->identifier);
544     if (desc->name) free((void *)desc->name);
545     if (desc->description) free((void *)desc->description);
546     if (desc->unit) free((void *)desc->unit);
547     if (desc->hasFixedBinCount && desc->binNames) {
548         for (unsigned int i = 0; i < desc->binCount; ++i) {
549             if (desc->binNames[i]) {
550                 free((void *)desc->binNames[i]);
551             }
552         }
553     }
554     if (desc->binNames) free((void *)desc->binNames);
555     free((void *)desc);
556 }
557
558 VampFeatureList *
559 PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
560                                      const float *const *inputBuffers,
561                                      int sec,
562                                      int nsec)
563 {
564 #ifdef DEBUG_PLUGIN_ADAPTER
565     std::cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << std::endl;
566 #endif
567
568     Impl *adapter = lookupAdapter(handle);
569     if (!adapter) return 0;
570     return adapter->process((Plugin *)handle, inputBuffers, sec, nsec);
571 }
572
573 VampFeatureList *
574 PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
575 {
576 #ifdef DEBUG_PLUGIN_ADAPTER
577     std::cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << std::endl;
578 #endif
579
580     Impl *adapter = lookupAdapter(handle);
581     if (!adapter) return 0;
582     return adapter->getRemainingFeatures((Plugin *)handle);
583 }
584
585 void
586 PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *fs)
587 {
588 #ifdef DEBUG_PLUGIN_ADAPTER
589     std::cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << std::endl;
590 #endif
591 }
592
593 void 
594 PluginAdapterBase::Impl::cleanup(Plugin *plugin)
595 {
596     if (m_fs.find(plugin) != m_fs.end()) {
597         size_t outputCount = 0;
598         if (m_pluginOutputs[plugin]) {
599             outputCount = m_pluginOutputs[plugin]->size();
600         }
601         VampFeatureList *list = m_fs[plugin];
602         for (unsigned int i = 0; i < outputCount; ++i) {
603             for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
604                 if (list[i].features[j].v1.label) {
605                     free(list[i].features[j].v1.label);
606                 }
607                 if (list[i].features[j].v1.values) {
608                     free(list[i].features[j].v1.values);
609                 }
610             }
611             if (list[i].features) free(list[i].features);
612         }
613         m_fs.erase(plugin);
614         m_fsizes.erase(plugin);
615         m_fvsizes.erase(plugin);
616     }
617
618     if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
619         delete m_pluginOutputs[plugin];
620         m_pluginOutputs.erase(plugin);
621     }
622
623     if (m_adapterMap) {
624         m_adapterMap->erase(plugin);
625
626         if (m_adapterMap->empty()) {
627             delete m_adapterMap;
628             m_adapterMap = 0;
629         }
630     }
631
632     delete ((Plugin *)plugin);
633 }
634
635 void 
636 PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
637 {
638     OutputMap::iterator i = m_pluginOutputs.find(plugin);
639
640     if (i == m_pluginOutputs.end() || !i->second) {
641
642         m_pluginOutputs[plugin] = new Plugin::OutputList
643             (plugin->getOutputDescriptors());
644
645 //        std::cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << std::endl;
646     }
647 }
648
649 void
650 PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin)
651 {
652     OutputMap::iterator i = m_pluginOutputs.find(plugin);
653
654 //    std::cerr << "PluginAdapterBase::Impl::markOutputsChanged" << std::endl;
655
656     if (i != m_pluginOutputs.end()) {
657
658         Plugin::OutputList *list = i->second;
659         m_pluginOutputs.erase(i);
660         delete list;
661     }
662 }
663
664 unsigned int 
665 PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
666 {
667     checkOutputMap(plugin);
668
669     return m_pluginOutputs[plugin]->size();
670 }
671
672 VampOutputDescriptor *
673 PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
674                                              unsigned int i)
675 {
676     checkOutputMap(plugin);
677
678     Plugin::OutputDescriptor &od =
679         (*m_pluginOutputs[plugin])[i];
680
681     VampOutputDescriptor *desc = (VampOutputDescriptor *)
682         malloc(sizeof(VampOutputDescriptor));
683
684     desc->identifier = strdup(od.identifier.c_str());
685     desc->name = strdup(od.name.c_str());
686     desc->description = strdup(od.description.c_str());
687     desc->unit = strdup(od.unit.c_str());
688     desc->hasFixedBinCount = od.hasFixedBinCount;
689     desc->binCount = od.binCount;
690
691     if (od.hasFixedBinCount && od.binCount > 0
692         // We would like to do "&& !od.binNames.empty()" here -- but we
693         // can't, because it will crash older versions of the host adapter
694         // which try to copy the names across whenever the bin count is
695         // non-zero, regardless of whether they exist or not
696         ) {
697         desc->binNames = (const char **)
698             malloc(od.binCount * sizeof(const char *));
699         
700         for (unsigned int i = 0; i < od.binCount; ++i) {
701             if (i < od.binNames.size()) {
702                 desc->binNames[i] = strdup(od.binNames[i].c_str());
703             } else {
704                 desc->binNames[i] = 0;
705             }
706         }
707     } else {
708         desc->binNames = 0;
709     }
710
711     desc->hasKnownExtents = od.hasKnownExtents;
712     desc->minValue = od.minValue;
713     desc->maxValue = od.maxValue;
714     desc->isQuantized = od.isQuantized;
715     desc->quantizeStep = od.quantizeStep;
716
717     switch (od.sampleType) {
718     case Plugin::OutputDescriptor::OneSamplePerStep:
719         desc->sampleType = vampOneSamplePerStep; break;
720     case Plugin::OutputDescriptor::FixedSampleRate:
721         desc->sampleType = vampFixedSampleRate; break;
722     case Plugin::OutputDescriptor::VariableSampleRate:
723         desc->sampleType = vampVariableSampleRate; break;
724     }
725
726     desc->sampleRate = od.sampleRate;
727     desc->hasDuration = od.hasDuration;
728
729     return desc;
730 }
731     
732 VampFeatureList *
733 PluginAdapterBase::Impl::process(Plugin *plugin,
734                                  const float *const *inputBuffers,
735                                  int sec, int nsec)
736 {
737 //    std::cerr << "PluginAdapterBase::Impl::process" << std::endl;
738     RealTime rt(sec, nsec);
739     checkOutputMap(plugin);
740     return convertFeatures(plugin, plugin->process(inputBuffers, rt));
741 }
742     
743 VampFeatureList *
744 PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
745 {
746 //    std::cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << std::endl;
747     checkOutputMap(plugin);
748     return convertFeatures(plugin, plugin->getRemainingFeatures());
749 }
750
751 VampFeatureList *
752 PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
753                                          const Plugin::FeatureSet &features)
754 {
755     int lastN = -1;
756
757     int outputCount = 0;
758     if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
759     
760     resizeFS(plugin, outputCount);
761     VampFeatureList *fs = m_fs[plugin];
762
763 //    std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << std::endl;
764
765     for (Plugin::FeatureSet::const_iterator fi = features.begin();
766          fi != features.end(); ++fi) {
767
768         int n = fi->first;
769         
770 //        std::cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << std::endl;
771
772         if (n >= int(outputCount)) {
773             std::cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << std::endl;
774             continue;
775         }
776
777         if (n > lastN + 1) {
778             for (int i = lastN + 1; i < n; ++i) {
779                 fs[i].featureCount = 0;
780             }
781         }
782
783         const Plugin::FeatureList &fl = fi->second;
784
785         size_t sz = fl.size();
786         if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
787         fs[n].featureCount = sz;
788         
789         for (size_t j = 0; j < sz; ++j) {
790
791 //            std::cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << std::endl;
792
793             VampFeature *feature = &fs[n].features[j].v1;
794
795             feature->hasTimestamp = fl[j].hasTimestamp;
796             feature->sec = fl[j].timestamp.sec;
797             feature->nsec = fl[j].timestamp.nsec;
798             feature->valueCount = fl[j].values.size();
799
800             VampFeatureV2 *v2 = &fs[n].features[j + sz].v2;
801             
802             v2->hasDuration = fl[j].hasDuration;
803             v2->durationSec = fl[j].duration.sec;
804             v2->durationNsec = fl[j].duration.nsec;
805
806             if (feature->label) free(feature->label);
807
808             if (fl[j].label.empty()) {
809                 feature->label = 0;
810             } else {
811                 feature->label = strdup(fl[j].label.c_str());
812             }
813
814             if (feature->valueCount > m_fvsizes[plugin][n][j]) {
815                 resizeFV(plugin, n, j, feature->valueCount);
816             }
817
818             for (unsigned int k = 0; k < feature->valueCount; ++k) {
819 //                std::cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << std::endl;
820                 feature->values[k] = fl[j].values[k];
821             }
822         }
823
824         lastN = n;
825     }
826
827     if (lastN == -1) return 0;
828
829     if (int(outputCount) > lastN + 1) {
830         for (int i = lastN + 1; i < int(outputCount); ++i) {
831             fs[i].featureCount = 0;
832         }
833     }
834
835 //    std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << std::endl;
836 //    for (int i = 0; i < outputCount; ++i) {
837 //        std::cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << std::endl;
838 //    }
839
840
841     return fs;
842 }
843
844 void
845 PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
846 {
847 //    std::cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << std::endl;
848
849     int i = m_fsizes[plugin].size();
850     if (i >= n) return;
851
852 //    std::cerr << "resizing from " << i << std::endl;
853
854     m_fs[plugin] = (VampFeatureList *)realloc
855         (m_fs[plugin], n * sizeof(VampFeatureList));
856
857     while (i < n) {
858         m_fs[plugin][i].featureCount = 0;
859         m_fs[plugin][i].features = 0;
860         m_fsizes[plugin].push_back(0);
861         m_fvsizes[plugin].push_back(std::vector<size_t>());
862         i++;
863     }
864 }
865
866 void
867 PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
868 {
869 //    std::cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
870 //              << sz << ")" << std::endl;
871
872     size_t i = m_fsizes[plugin][n];
873     if (i >= sz) return;
874
875 //    std::cerr << "resizing from " << i << std::endl;
876
877     m_fs[plugin][n].features = (VampFeatureUnion *)realloc
878         (m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion));
879
880     while (m_fsizes[plugin][n] < sz) {
881         m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0;
882         m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0;
883         m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0;
884         m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0;
885         m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0;
886         m_fvsizes[plugin][n].push_back(0);
887         m_fsizes[plugin][n]++;
888     }
889 }
890
891 void
892 PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
893 {
894 //    std::cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
895 //              << j << ", " << sz << ")" << std::endl;
896
897     size_t i = m_fvsizes[plugin][n][j];
898     if (i >= sz) return;
899
900 //    std::cerr << "resizing from " << i << std::endl;
901
902     m_fs[plugin][n].features[j].v1.values = (float *)realloc
903         (m_fs[plugin][n].features[j].v1.values, sz * sizeof(float));
904
905     m_fvsizes[plugin][n][j] = sz;
906 }
907   
908 PluginAdapterBase::Impl::AdapterMap *
909 PluginAdapterBase::Impl::m_adapterMap = 0;
910
911 }
912
913 _VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp)
914