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