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