To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / src / vamp-sdk / PluginAdapter.cpp @ 539:15a89a89aa9b

History | View | Annotate | Download (31.9 KB)

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
#include <mutex>
43

    
44
#if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 10 )
45
#error Unexpected version of Vamp SDK header included
46
#endif
47

    
48
using std::map;
49
using std::vector;
50
using std::string;
51
using std::cerr;
52
using std::endl;
53
using std::mutex;
54
using std::lock_guard;
55

    
56
//#define DEBUG_PLUGIN_ADAPTER 1
57

    
58
_VAMP_SDK_PLUGSPACE_BEGIN(PluginAdapter.cpp)
59

    
60
namespace Vamp {
61

    
62
class PluginAdapterBase::Impl
63
{
64
public:
65
    Impl(PluginAdapterBase *);
66
    ~Impl();
67

    
68
    const VampPluginDescriptor *getDescriptor();
69

    
70
protected:
71
    PluginAdapterBase *m_base;
72

    
73
    static VampPluginHandle vampInstantiate(const VampPluginDescriptor *desc,
74
                                            float inputSampleRate);
75

    
76
    static void vampCleanup(VampPluginHandle handle);
77

    
78
    static int vampInitialise(VampPluginHandle handle, unsigned int channels,
79
                             unsigned int stepSize, unsigned int blockSize);
80

    
81
    static void vampReset(VampPluginHandle handle);
82

    
83
    static float vampGetParameter(VampPluginHandle handle, int param);
84
    static void vampSetParameter(VampPluginHandle handle, int param, float value);
85

    
86
    static unsigned int vampGetCurrentProgram(VampPluginHandle handle);
87
    static void vampSelectProgram(VampPluginHandle handle, unsigned int program);
88

    
89
    static unsigned int vampGetPreferredStepSize(VampPluginHandle handle);
90
    static unsigned int vampGetPreferredBlockSize(VampPluginHandle handle);
91
    static unsigned int vampGetMinChannelCount(VampPluginHandle handle);
92
    static unsigned int vampGetMaxChannelCount(VampPluginHandle handle);
93

    
94
    static unsigned int vampGetOutputCount(VampPluginHandle handle);
95

    
96
    static VampOutputDescriptor *vampGetOutputDescriptor(VampPluginHandle handle,
97
                                                       unsigned int i);
98

    
99
    static void vampReleaseOutputDescriptor(VampOutputDescriptor *desc);
100

    
101
    static VampFeatureList *vampProcess(VampPluginHandle handle,
102
                                        const float *const *inputBuffers,
103
                                        int sec,
104
                                        int nsec);
105

    
106
    static VampFeatureList *vampGetRemainingFeatures(VampPluginHandle handle);
107

    
108
    static void vampReleaseFeatureSet(VampFeatureList *fs);
109

    
110
    void checkOutputMap(Plugin *plugin);
111
    void markOutputsChanged(Plugin *plugin);
112

    
113
    void cleanup(Plugin *plugin);
114
    unsigned int getOutputCount(Plugin *plugin);
115
    VampOutputDescriptor *getOutputDescriptor(Plugin *plugin, unsigned int i);
116
    VampFeatureList *process(Plugin *plugin,
117
                             const float *const *inputBuffers,
118
                             int sec, int nsec);
119
    VampFeatureList *getRemainingFeatures(Plugin *plugin);
120
    VampFeatureList *convertFeatures(Plugin *plugin,
121
                                     const Plugin::FeatureSet &features);
122
    
123
    // maps both plugins and descriptors to adapters
124
    typedef map<const void *, Impl *> AdapterMap;
125

    
126
    static AdapterMap *m_adapterMap;
127

    
128
    static mutex &adapterMapMutex() {
129
        // If this mutex was a global static, then it might be
130
        // destroyed before the last adapter, and we would end up
131
        // trying to lock an invalid mutex when removing an adapter
132
        // from the adapter map. To ensure it outlasts the adapters,
133
        // we need to ensure it is constructed before the construction
134
        // of any of them is complete, since destruction order is
135
        // reverse of construction. So we have to make sure this is
136
        // called from the PluginAdapterBase::Impl constructor below.
137
        static mutex m;
138
        return m;
139
    }
140
        
141
    static Impl *lookupAdapter(VampPluginHandle);
142

    
143
    mutex m_mutex; // guards all of the below
144
    
145
    bool m_populated;
146
    VampPluginDescriptor m_descriptor;
147
    Plugin::ParameterList m_parameters;
148
    Plugin::ProgramList m_programs;
149
    
150
    typedef map<Plugin *, Plugin::OutputList *> OutputMap;
151
    OutputMap m_pluginOutputs;
152

    
153
    map<Plugin *, VampFeatureList *> m_fs;
154
    map<Plugin *, vector<size_t> > m_fsizes;
155
    map<Plugin *, vector<vector<size_t> > > m_fvsizes;
156
    void resizeFS(Plugin *plugin, int n);
157
    void resizeFL(Plugin *plugin, int n, size_t sz);
158
    void resizeFV(Plugin *plugin, int n, int j, size_t sz);
159
};
160

    
161
PluginAdapterBase::PluginAdapterBase()
162
{
163
    m_impl = new Impl(this);
164
}
165

    
166
PluginAdapterBase::~PluginAdapterBase()
167
{
168
    delete m_impl;
169
}
170

    
171
const VampPluginDescriptor *
172
PluginAdapterBase::getDescriptor()
173
{
174
    return m_impl->getDescriptor();
175
}
176

    
177
PluginAdapterBase::Impl::Impl(PluginAdapterBase *base) :
178
    m_base(base),
179
    m_populated(false)
180
{
181
#ifdef DEBUG_PLUGIN_ADAPTER
182
    cerr << "PluginAdapterBase::Impl[" << this << "]::Impl" << endl;
183
#endif
184

    
185
    (void)adapterMapMutex(); // see comment in adapterMapMutex function above
186
}
187

    
188
const VampPluginDescriptor *
189
PluginAdapterBase::Impl::getDescriptor()
190
{
191
#ifdef DEBUG_PLUGIN_ADAPTER
192
    cerr << "PluginAdapterBase::Impl[" << this << "]::getDescriptor" << endl;
193
#endif
194

    
195
    lock_guard<mutex> guard(m_mutex);
196
    
197
    if (m_populated) return &m_descriptor;
198
    
199
    Plugin *plugin = m_base->createPlugin(48000);
200
  
201
    if (!plugin) {
202
        cerr << "PluginAdapterBase::Impl::getDescriptor: Failed to create plugin" << endl;
203
        return 0;
204
    }
205

    
206
    if (plugin->getVampApiVersion() != VAMP_API_VERSION) {
207
        cerr << "Vamp::PluginAdapterBase::Impl::getDescriptor: ERROR: "
208
             << "API version " << plugin->getVampApiVersion()
209
             << " for\nplugin \"" << plugin->getIdentifier() << "\" "
210
             << "differs from version "
211
             << VAMP_API_VERSION << " for adapter.\n"
212
             << "This plugin is probably linked against a different version of the Vamp SDK\n"
213
             << "from the version it was compiled with.  It will need to be re-linked correctly\n"
214
             << "before it can be used." << endl;
215
        delete plugin;
216
        return 0;
217
    }
218

    
219
    m_parameters = plugin->getParameterDescriptors();
220
    m_programs = plugin->getPrograms();
221

    
222
    m_descriptor.vampApiVersion = plugin->getVampApiVersion();
223
    m_descriptor.identifier = strdup(plugin->getIdentifier().c_str());
224
    m_descriptor.name = strdup(plugin->getName().c_str());
225
    m_descriptor.description = strdup(plugin->getDescription().c_str());
226
    m_descriptor.maker = strdup(plugin->getMaker().c_str());
227
    m_descriptor.pluginVersion = plugin->getPluginVersion();
228
    m_descriptor.copyright = strdup(plugin->getCopyright().c_str());
229
    
230
    m_descriptor.parameterCount = m_parameters.size();
231
    m_descriptor.parameters = (const VampParameterDescriptor **)
232
        malloc(m_parameters.size() * sizeof(VampParameterDescriptor));
233

    
234
    unsigned int i;
235
    
236
    for (i = 0; i < m_parameters.size(); ++i) {
237
        VampParameterDescriptor *desc = (VampParameterDescriptor *)
238
            malloc(sizeof(VampParameterDescriptor));
239
        desc->identifier = strdup(m_parameters[i].identifier.c_str());
240
        desc->name = strdup(m_parameters[i].name.c_str());
241
        desc->description = strdup(m_parameters[i].description.c_str());
242
        desc->unit = strdup(m_parameters[i].unit.c_str());
243
        desc->minValue = m_parameters[i].minValue;
244
        desc->maxValue = m_parameters[i].maxValue;
245
        desc->defaultValue = m_parameters[i].defaultValue;
246
        desc->isQuantized = m_parameters[i].isQuantized;
247
        desc->quantizeStep = m_parameters[i].quantizeStep;
248
        desc->valueNames = 0;
249
        if (desc->isQuantized && !m_parameters[i].valueNames.empty()) {
250
            desc->valueNames = (const char **)
251
                malloc((m_parameters[i].valueNames.size()+1) * sizeof(char *));
252
            for (unsigned int j = 0; j < m_parameters[i].valueNames.size(); ++j) {
253
                desc->valueNames[j] = strdup(m_parameters[i].valueNames[j].c_str());
254
            }
255
            desc->valueNames[m_parameters[i].valueNames.size()] = 0;
256
        }
257
        m_descriptor.parameters[i] = desc;
258
    }
259
    
260
    m_descriptor.programCount = m_programs.size();
261
    m_descriptor.programs = (const char **)
262
        malloc(m_programs.size() * sizeof(const char *));
263
    
264
    for (i = 0; i < m_programs.size(); ++i) {
265
        m_descriptor.programs[i] = strdup(m_programs[i].c_str());
266
    }
267
    
268
    if (plugin->getInputDomain() == Plugin::FrequencyDomain) {
269
        m_descriptor.inputDomain = vampFrequencyDomain;
270
    } else {
271
        m_descriptor.inputDomain = vampTimeDomain;
272
    }
273

    
274
    m_descriptor.instantiate = vampInstantiate;
275
    m_descriptor.cleanup = vampCleanup;
276
    m_descriptor.initialise = vampInitialise;
277
    m_descriptor.reset = vampReset;
278
    m_descriptor.getParameter = vampGetParameter;
279
    m_descriptor.setParameter = vampSetParameter;
280
    m_descriptor.getCurrentProgram = vampGetCurrentProgram;
281
    m_descriptor.selectProgram = vampSelectProgram;
282
    m_descriptor.getPreferredStepSize = vampGetPreferredStepSize;
283
    m_descriptor.getPreferredBlockSize = vampGetPreferredBlockSize;
284
    m_descriptor.getMinChannelCount = vampGetMinChannelCount;
285
    m_descriptor.getMaxChannelCount = vampGetMaxChannelCount;
286
    m_descriptor.getOutputCount = vampGetOutputCount;
287
    m_descriptor.getOutputDescriptor = vampGetOutputDescriptor;
288
    m_descriptor.releaseOutputDescriptor = vampReleaseOutputDescriptor;
289
    m_descriptor.process = vampProcess;
290
    m_descriptor.getRemainingFeatures = vampGetRemainingFeatures;
291
    m_descriptor.releaseFeatureSet = vampReleaseFeatureSet;
292

    
293
    lock_guard<mutex> adapterMapGuard(adapterMapMutex());
294
    
295
    if (!m_adapterMap) {
296
        m_adapterMap = new AdapterMap;
297
    }
298
    (*m_adapterMap)[&m_descriptor] = this;
299

    
300
    delete plugin;
301

    
302
    m_populated = true;
303
    return &m_descriptor;
304
}
305

    
306
PluginAdapterBase::Impl::~Impl()
307
{
308
#ifdef DEBUG_PLUGIN_ADAPTER
309
    cerr << "PluginAdapterBase::Impl[" << this << "]::~Impl" << endl;
310
#endif
311

    
312
    lock_guard<mutex> guard(m_mutex);
313

    
314
    if (!m_populated) return;
315

    
316
    free((void *)m_descriptor.identifier);
317
    free((void *)m_descriptor.name);
318
    free((void *)m_descriptor.description);
319
    free((void *)m_descriptor.maker);
320
    free((void *)m_descriptor.copyright);
321
        
322
    for (unsigned int i = 0; i < m_descriptor.parameterCount; ++i) {
323
        const VampParameterDescriptor *desc = m_descriptor.parameters[i];
324
        free((void *)desc->identifier);
325
        free((void *)desc->name);
326
        free((void *)desc->description);
327
        free((void *)desc->unit);
328
        if (desc->valueNames) {
329
            for (unsigned int j = 0; desc->valueNames[j]; ++j) {
330
                free((void *)desc->valueNames[j]);
331
            }
332
            free((void *)desc->valueNames);
333
        }
334
        free((void *)desc);
335
    }
336
    free((void *)m_descriptor.parameters);
337

    
338
    for (unsigned int i = 0; i < m_descriptor.programCount; ++i) {
339
        free((void *)m_descriptor.programs[i]);
340
    }
341
    free((void *)m_descriptor.programs);
342

    
343
    lock_guard<mutex> adapterMapGuard(adapterMapMutex());
344
    
345
    if (m_adapterMap) {
346
        
347
        m_adapterMap->erase(&m_descriptor);
348
        
349
        if (m_adapterMap->empty()) {
350
            delete m_adapterMap;
351
            m_adapterMap = 0;
352
        }
353
    }
354
}
355

    
356
PluginAdapterBase::Impl *
357
PluginAdapterBase::Impl::lookupAdapter(VampPluginHandle handle)
358
{
359
#ifdef DEBUG_PLUGIN_ADAPTER
360
    cerr << "PluginAdapterBase::Impl::lookupAdapter(" << handle << ")" << endl;
361
#endif
362

    
363
    lock_guard<mutex> adapterMapGuard(adapterMapMutex());
364
    
365
    if (!m_adapterMap) return 0;
366
    AdapterMap::const_iterator i = m_adapterMap->find(handle);
367
    if (i == m_adapterMap->end()) return 0;
368
    return i->second;
369
}
370

    
371
VampPluginHandle
372
PluginAdapterBase::Impl::vampInstantiate(const VampPluginDescriptor *desc,
373
                                         float inputSampleRate)
374
{
375
#ifdef DEBUG_PLUGIN_ADAPTER
376
    cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << ")" << endl;
377
#endif
378

    
379
    lock_guard<mutex> adapterMapGuard(adapterMapMutex());
380
    
381
    if (!m_adapterMap) {
382
        m_adapterMap = new AdapterMap();
383
    }
384

    
385
    if (m_adapterMap->find(desc) == m_adapterMap->end()) {
386
        cerr << "WARNING: PluginAdapterBase::Impl::vampInstantiate: Descriptor " << desc << " not in adapter map" << endl;
387
        return 0;
388
    }
389

    
390
    Impl *adapter = (*m_adapterMap)[desc];
391
    if (desc != &adapter->m_descriptor) return 0;
392

    
393
    Plugin *plugin = adapter->m_base->createPlugin(inputSampleRate);
394
    if (plugin) {
395
        (*m_adapterMap)[plugin] = adapter;
396
    }
397

    
398
#ifdef DEBUG_PLUGIN_ADAPTER
399
    cerr << "PluginAdapterBase::Impl::vampInstantiate(" << desc << "): returning handle " << plugin << endl;
400
#endif
401

    
402
    return plugin;
403
}
404

    
405
void
406
PluginAdapterBase::Impl::vampCleanup(VampPluginHandle handle)
407
{
408
#ifdef DEBUG_PLUGIN_ADAPTER
409
    cerr << "PluginAdapterBase::Impl::vampCleanup(" << handle << ")" << endl;
410
#endif
411

    
412
    Impl *adapter = lookupAdapter(handle);
413
    if (!adapter) {
414
        delete ((Plugin *)handle);
415
        return;
416
    }
417
    adapter->cleanup(((Plugin *)handle));
418
}
419

    
420
int
421
PluginAdapterBase::Impl::vampInitialise(VampPluginHandle handle,
422
                                        unsigned int channels,
423
                                        unsigned int stepSize,
424
                                        unsigned int blockSize)
425
{
426
#ifdef DEBUG_PLUGIN_ADAPTER
427
    cerr << "PluginAdapterBase::Impl::vampInitialise(" << handle << ", " << channels << ", " << stepSize << ", " << blockSize << ")" << endl;
428
#endif
429

    
430
    Impl *adapter = lookupAdapter(handle);
431
    if (!adapter) return 0;
432
    bool result = ((Plugin *)handle)->initialise(channels, stepSize, blockSize);
433
    adapter->markOutputsChanged((Plugin *)handle);
434
    return result ? 1 : 0;
435
}
436

    
437
void
438
PluginAdapterBase::Impl::vampReset(VampPluginHandle handle) 
439
{
440
#ifdef DEBUG_PLUGIN_ADAPTER
441
    cerr << "PluginAdapterBase::Impl::vampReset(" << handle << ")" << endl;
442
#endif
443

    
444
    ((Plugin *)handle)->reset();
445
}
446

    
447
float
448
PluginAdapterBase::Impl::vampGetParameter(VampPluginHandle handle,
449
                                    int param) 
450
{
451
#ifdef DEBUG_PLUGIN_ADAPTER
452
    cerr << "PluginAdapterBase::Impl::vampGetParameter(" << handle << ", " << param << ")" << endl;
453
#endif
454

    
455
    Impl *adapter = lookupAdapter(handle);
456
    if (!adapter) return 0.0;
457
    Plugin::ParameterList &list = adapter->m_parameters;
458
    return ((Plugin *)handle)->getParameter(list[param].identifier);
459
}
460

    
461
void
462
PluginAdapterBase::Impl::vampSetParameter(VampPluginHandle handle,
463
                                    int param, float value)
464
{
465
#ifdef DEBUG_PLUGIN_ADAPTER
466
    cerr << "PluginAdapterBase::Impl::vampSetParameter(" << handle << ", " << param << ", " << value << ")" << endl;
467
#endif
468

    
469
    Impl *adapter = lookupAdapter(handle);
470
    if (!adapter) return;
471
    Plugin::ParameterList &list = adapter->m_parameters;
472
    ((Plugin *)handle)->setParameter(list[param].identifier, value);
473
    adapter->markOutputsChanged((Plugin *)handle);
474
}
475

    
476
unsigned int
477
PluginAdapterBase::Impl::vampGetCurrentProgram(VampPluginHandle handle)
478
{
479
#ifdef DEBUG_PLUGIN_ADAPTER
480
    cerr << "PluginAdapterBase::Impl::vampGetCurrentProgram(" << handle << ")" << endl;
481
#endif
482

    
483
    Impl *adapter = lookupAdapter(handle);
484
    if (!adapter) return 0;
485
    Plugin::ProgramList &list = adapter->m_programs;
486
    string program = ((Plugin *)handle)->getCurrentProgram();
487
    for (unsigned int i = 0; i < list.size(); ++i) {
488
        if (list[i] == program) return i;
489
    }
490
    return 0;
491
}
492

    
493
void
494
PluginAdapterBase::Impl::vampSelectProgram(VampPluginHandle handle,
495
                                           unsigned int program)
496
{
497
#ifdef DEBUG_PLUGIN_ADAPTER
498
    cerr << "PluginAdapterBase::Impl::vampSelectProgram(" << handle << ", " << program << ")" << endl;
499
#endif
500

    
501
    Impl *adapter = lookupAdapter(handle);
502
    if (!adapter) return;
503

    
504
    Plugin::ProgramList &list = adapter->m_programs;
505
    ((Plugin *)handle)->selectProgram(list[program]);
506

    
507
    adapter->markOutputsChanged((Plugin *)handle);
508
}
509

    
510
unsigned int
511
PluginAdapterBase::Impl::vampGetPreferredStepSize(VampPluginHandle handle)
512
{
513
#ifdef DEBUG_PLUGIN_ADAPTER
514
    cerr << "PluginAdapterBase::Impl::vampGetPreferredStepSize(" << handle << ")" << endl;
515
#endif
516

    
517
    return ((Plugin *)handle)->getPreferredStepSize();
518
}
519

    
520
unsigned int
521
PluginAdapterBase::Impl::vampGetPreferredBlockSize(VampPluginHandle handle) 
522
{
523
#ifdef DEBUG_PLUGIN_ADAPTER
524
    cerr << "PluginAdapterBase::Impl::vampGetPreferredBlockSize(" << handle << ")" << endl;
525
#endif
526

    
527
    return ((Plugin *)handle)->getPreferredBlockSize();
528
}
529

    
530
unsigned int
531
PluginAdapterBase::Impl::vampGetMinChannelCount(VampPluginHandle handle)
532
{
533
#ifdef DEBUG_PLUGIN_ADAPTER
534
    cerr << "PluginAdapterBase::Impl::vampGetMinChannelCount(" << handle << ")" << endl;
535
#endif
536

    
537
    return ((Plugin *)handle)->getMinChannelCount();
538
}
539

    
540
unsigned int
541
PluginAdapterBase::Impl::vampGetMaxChannelCount(VampPluginHandle handle)
542
{
543
#ifdef DEBUG_PLUGIN_ADAPTER
544
    cerr << "PluginAdapterBase::Impl::vampGetMaxChannelCount(" << handle << ")" << endl;
545
#endif
546

    
547
    return ((Plugin *)handle)->getMaxChannelCount();
548
}
549

    
550
unsigned int
551
PluginAdapterBase::Impl::vampGetOutputCount(VampPluginHandle handle)
552
{
553
#ifdef DEBUG_PLUGIN_ADAPTER
554
    cerr << "PluginAdapterBase::Impl::vampGetOutputCount(" << handle << ")" << endl;
555
#endif
556

    
557
    Impl *adapter = lookupAdapter(handle);
558

    
559
//    cerr << "vampGetOutputCount: handle " << handle << " -> adapter "<< adapter << endl;
560

    
561
    if (!adapter) return 0;
562
    return adapter->getOutputCount((Plugin *)handle);
563
}
564

    
565
VampOutputDescriptor *
566
PluginAdapterBase::Impl::vampGetOutputDescriptor(VampPluginHandle handle,
567
                                                 unsigned int i)
568
{
569
#ifdef DEBUG_PLUGIN_ADAPTER
570
    cerr << "PluginAdapterBase::Impl::vampGetOutputDescriptor(" << handle << ", " << i << ")" << endl;
571
#endif
572

    
573
    Impl *adapter = lookupAdapter(handle);
574

    
575
//    cerr << "vampGetOutputDescriptor: handle " << handle << " -> adapter "<< adapter << endl;
576

    
577
    if (!adapter) return 0;
578
    return adapter->getOutputDescriptor((Plugin *)handle, i);
579
}
580

    
581
void
582
PluginAdapterBase::Impl::vampReleaseOutputDescriptor(VampOutputDescriptor *desc)
583
{
584
#ifdef DEBUG_PLUGIN_ADAPTER
585
    cerr << "PluginAdapterBase::Impl::vampReleaseOutputDescriptor(" << desc << ")" << endl;
586
#endif
587

    
588
    if (desc->identifier) free((void *)desc->identifier);
589
    if (desc->name) free((void *)desc->name);
590
    if (desc->description) free((void *)desc->description);
591
    if (desc->unit) free((void *)desc->unit);
592
    if (desc->hasFixedBinCount && desc->binNames) {
593
        for (unsigned int i = 0; i < desc->binCount; ++i) {
594
            if (desc->binNames[i]) {
595
                free((void *)desc->binNames[i]);
596
            }
597
        }
598
    }
599
    if (desc->binNames) free((void *)desc->binNames);
600
    free((void *)desc);
601
}
602

    
603
VampFeatureList *
604
PluginAdapterBase::Impl::vampProcess(VampPluginHandle handle,
605
                                     const float *const *inputBuffers,
606
                                     int sec,
607
                                     int nsec)
608
{
609
#ifdef DEBUG_PLUGIN_ADAPTER
610
    cerr << "PluginAdapterBase::Impl::vampProcess(" << handle << ", " << sec << ", " << nsec << ")" << endl;
611
#endif
612

    
613
    Impl *adapter = lookupAdapter(handle);
614
    if (!adapter) return 0;
615
    return adapter->process((Plugin *)handle, inputBuffers, sec, nsec);
616
}
617

    
618
VampFeatureList *
619
PluginAdapterBase::Impl::vampGetRemainingFeatures(VampPluginHandle handle)
620
{
621
#ifdef DEBUG_PLUGIN_ADAPTER
622
    cerr << "PluginAdapterBase::Impl::vampGetRemainingFeatures(" << handle << ")" << endl;
623
#endif
624

    
625
    Impl *adapter = lookupAdapter(handle);
626
    if (!adapter) return 0;
627
    return adapter->getRemainingFeatures((Plugin *)handle);
628
}
629

    
630
void
631
PluginAdapterBase::Impl::vampReleaseFeatureSet(VampFeatureList *)
632
{
633
#ifdef DEBUG_PLUGIN_ADAPTER
634
    cerr << "PluginAdapterBase::Impl::vampReleaseFeatureSet" << endl;
635
#endif
636
}
637

    
638
void 
639
PluginAdapterBase::Impl::cleanup(Plugin *plugin)
640
{
641
    // at this point no mutex is held
642
    
643
    lock_guard<mutex> adapterMapGuard(adapterMapMutex());
644
    lock_guard<mutex> guard(m_mutex);
645
    
646
    if (m_fs.find(plugin) != m_fs.end()) {
647
        size_t outputCount = 0;
648
        if (m_pluginOutputs[plugin]) {
649
            outputCount = m_pluginOutputs[plugin]->size();
650
        }
651
#ifdef DEBUG_PLUGIN_ADAPTER
652
        cerr << "PluginAdapterBase::Impl::cleanup: " << outputCount << " output(s)" << endl;
653
#endif
654
        VampFeatureList *list = m_fs[plugin];
655
        for (unsigned int i = 0; i < outputCount; ++i) {
656
            for (unsigned int j = 0; j < m_fsizes[plugin][i]; ++j) {
657
                if (list[i].features[j].v1.label) {
658
                    free(list[i].features[j].v1.label);
659
                }
660
                if (list[i].features[j].v1.values) {
661
                    free(list[i].features[j].v1.values);
662
                }
663
            }
664
            if (list[i].features) free(list[i].features);
665
        }
666
        if (list) free((void *)list);
667
        m_fs.erase(plugin);
668
        m_fsizes.erase(plugin);
669
        m_fvsizes.erase(plugin);
670
    }
671

    
672
    if (m_pluginOutputs.find(plugin) != m_pluginOutputs.end()) {
673
        delete m_pluginOutputs[plugin];
674
        m_pluginOutputs.erase(plugin);
675
    }
676

    
677
    if (m_adapterMap) {
678
        m_adapterMap->erase(plugin);
679

    
680
        if (m_adapterMap->empty()) {
681
            delete m_adapterMap;
682
            m_adapterMap = 0;
683
        }
684
    }
685

    
686
    delete ((Plugin *)plugin);
687
}
688

    
689
void 
690
PluginAdapterBase::Impl::checkOutputMap(Plugin *plugin)
691
{
692
    // must be called with m_mutex held
693
    
694
    OutputMap::iterator i = m_pluginOutputs.find(plugin);
695

    
696
    if (i == m_pluginOutputs.end() || !i->second) {
697

    
698
        m_pluginOutputs[plugin] = new Plugin::OutputList
699
            (plugin->getOutputDescriptors());
700

    
701
//        cerr << "PluginAdapterBase::Impl::checkOutputMap: Have " << m_pluginOutputs[plugin]->size() << " outputs for plugin " << plugin->getIdentifier() << endl;
702
    }
703
}
704

    
705
void
706
PluginAdapterBase::Impl::markOutputsChanged(Plugin *plugin)
707
{
708
    lock_guard<mutex> guard(m_mutex);
709

    
710
    OutputMap::iterator i = m_pluginOutputs.find(plugin);
711

    
712
//    cerr << "PluginAdapterBase::Impl::markOutputsChanged" << endl;
713

    
714
    if (i != m_pluginOutputs.end()) {
715

    
716
        Plugin::OutputList *list = i->second;
717
        m_pluginOutputs.erase(i);
718
        delete list;
719
    }
720
}
721

    
722
unsigned int 
723
PluginAdapterBase::Impl::getOutputCount(Plugin *plugin)
724
{
725
    lock_guard<mutex> guard(m_mutex);
726

    
727
    checkOutputMap(plugin);
728

    
729
    return m_pluginOutputs[plugin]->size();
730
}
731

    
732
VampOutputDescriptor *
733
PluginAdapterBase::Impl::getOutputDescriptor(Plugin *plugin,
734
                                             unsigned int i)
735
{
736
    lock_guard<mutex> guard(m_mutex);
737

    
738
    checkOutputMap(plugin);
739

    
740
    Plugin::OutputDescriptor &od =
741
        (*m_pluginOutputs[plugin])[i];
742

    
743
    VampOutputDescriptor *desc = (VampOutputDescriptor *)
744
        malloc(sizeof(VampOutputDescriptor));
745

    
746
    desc->identifier = strdup(od.identifier.c_str());
747
    desc->name = strdup(od.name.c_str());
748
    desc->description = strdup(od.description.c_str());
749
    desc->unit = strdup(od.unit.c_str());
750
    desc->hasFixedBinCount = od.hasFixedBinCount;
751
    desc->binCount = od.binCount;
752

    
753
    if (od.hasFixedBinCount && od.binCount > 0
754
        // We would like to do "&& !od.binNames.empty()" here -- but we
755
        // can't, because it will crash older versions of the host adapter
756
        // which try to copy the names across whenever the bin count is
757
        // non-zero, regardless of whether they exist or not
758
        ) {
759
        desc->binNames = (const char **)
760
            malloc(od.binCount * sizeof(const char *));
761
        
762
        for (unsigned int i = 0; i < od.binCount; ++i) {
763
            if (i < od.binNames.size()) {
764
                desc->binNames[i] = strdup(od.binNames[i].c_str());
765
            } else {
766
                desc->binNames[i] = 0;
767
            }
768
        }
769
    } else {
770
        desc->binNames = 0;
771
    }
772

    
773
    desc->hasKnownExtents = od.hasKnownExtents;
774
    desc->minValue = od.minValue;
775
    desc->maxValue = od.maxValue;
776
    desc->isQuantized = od.isQuantized;
777
    desc->quantizeStep = od.quantizeStep;
778

    
779
    switch (od.sampleType) {
780
    case Plugin::OutputDescriptor::OneSamplePerStep:
781
        desc->sampleType = vampOneSamplePerStep; break;
782
    case Plugin::OutputDescriptor::FixedSampleRate:
783
        desc->sampleType = vampFixedSampleRate; break;
784
    case Plugin::OutputDescriptor::VariableSampleRate:
785
        desc->sampleType = vampVariableSampleRate; break;
786
    }
787

    
788
    desc->sampleRate = od.sampleRate;
789
    desc->hasDuration = od.hasDuration;
790

    
791
    return desc;
792
}
793
    
794
VampFeatureList *
795
PluginAdapterBase::Impl::process(Plugin *plugin,
796
                                 const float *const *inputBuffers,
797
                                 int sec, int nsec)
798
{
799
//    cerr << "PluginAdapterBase::Impl::process" << endl;
800

    
801
    RealTime rt(sec, nsec);
802

    
803
    // We don't want to hold the mutex during the actual process call,
804
    // only while looking up the associated metadata
805
    {    
806
        lock_guard<mutex> guard(m_mutex);
807
        checkOutputMap(plugin);
808
    }
809

    
810
    return convertFeatures(plugin, plugin->process(inputBuffers, rt));
811
}
812
    
813
VampFeatureList *
814
PluginAdapterBase::Impl::getRemainingFeatures(Plugin *plugin)
815
{
816
//    cerr << "PluginAdapterBase::Impl::getRemainingFeatures" << endl;
817

    
818
    // We don't want to hold the mutex during the actual call, only
819
    // while looking up the associated metadata
820
    {    
821
        lock_guard<mutex> guard(m_mutex);
822
        checkOutputMap(plugin);
823
    }
824

    
825
    return convertFeatures(plugin, plugin->getRemainingFeatures());
826
}
827

    
828
VampFeatureList *
829
PluginAdapterBase::Impl::convertFeatures(Plugin *plugin,
830
                                         const Plugin::FeatureSet &features)
831
{
832
    lock_guard<mutex> guard(m_mutex);
833

    
834
    int lastN = -1;
835

    
836
    int outputCount = 0;
837
    if (m_pluginOutputs[plugin]) outputCount = m_pluginOutputs[plugin]->size();
838
    
839
    resizeFS(plugin, outputCount);
840
    VampFeatureList *fs = m_fs[plugin];
841

    
842
//    cerr << "PluginAdapter(v2)::convertFeatures: NOTE: sizeof(Feature) == " << sizeof(Plugin::Feature) << ", sizeof(VampFeature) == " << sizeof(VampFeature) << ", sizeof(VampFeatureList) == " << sizeof(VampFeatureList) << endl;
843

    
844
    for (Plugin::FeatureSet::const_iterator fi = features.begin();
845
         fi != features.end(); ++fi) {
846

    
847
        int n = fi->first;
848
        
849
//        cerr << "PluginAdapterBase::Impl::convertFeatures: n = " << n << endl;
850

    
851
        if (n >= int(outputCount)) {
852
            cerr << "WARNING: PluginAdapterBase::Impl::convertFeatures: Too many outputs from plugin (" << n+1 << ", only should be " << outputCount << ")" << endl;
853
            continue;
854
        }
855

    
856
        if (n > lastN + 1) {
857
            for (int i = lastN + 1; i < n; ++i) {
858
                fs[i].featureCount = 0;
859
            }
860
        }
861

    
862
        const Plugin::FeatureList &fl = fi->second;
863

    
864
        size_t sz = fl.size();
865
        if (sz > m_fsizes[plugin][n]) resizeFL(plugin, n, sz);
866
        fs[n].featureCount = sz;
867
        
868
        for (size_t j = 0; j < sz; ++j) {
869

    
870
//            cerr << "PluginAdapterBase::Impl::convertFeatures: j = " << j << endl;
871

    
872
            VampFeature *feature = &fs[n].features[j].v1;
873

    
874
            feature->hasTimestamp = fl[j].hasTimestamp;
875
            feature->sec = fl[j].timestamp.sec;
876
            feature->nsec = fl[j].timestamp.nsec;
877
            feature->valueCount = fl[j].values.size();
878

    
879
            VampFeatureV2 *v2 = &fs[n].features[j + sz].v2;
880
            
881
            v2->hasDuration = fl[j].hasDuration;
882
            v2->durationSec = fl[j].duration.sec;
883
            v2->durationNsec = fl[j].duration.nsec;
884

    
885
            if (feature->label) free(feature->label);
886

    
887
            if (fl[j].label.empty()) {
888
                feature->label = 0;
889
            } else {
890
                feature->label = strdup(fl[j].label.c_str());
891
            }
892

    
893
            if (feature->valueCount > m_fvsizes[plugin][n][j]) {
894
                resizeFV(plugin, n, j, feature->valueCount);
895
            }
896

    
897
            for (unsigned int k = 0; k < feature->valueCount; ++k) {
898
//                cerr << "PluginAdapterBase::Impl::convertFeatures: k = " << k << endl;
899
                feature->values[k] = fl[j].values[k];
900
            }
901
        }
902

    
903
        lastN = n;
904
    }
905

    
906
    if (lastN == -1) return 0;
907

    
908
    if (int(outputCount) > lastN + 1) {
909
        for (int i = lastN + 1; i < int(outputCount); ++i) {
910
            fs[i].featureCount = 0;
911
        }
912
    }
913

    
914
//    cerr << "PluginAdapter(v2)::convertFeatures: NOTE: have " << outputCount << " outputs" << endl;
915
//    for (int i = 0; i < outputCount; ++i) {
916
//        cerr << "PluginAdapter(v2)::convertFeatures: NOTE: output " << i << " has " << fs[i].featureCount << " features" << endl;
917
//    }
918

    
919

    
920
    return fs;
921
}
922

    
923
void
924
PluginAdapterBase::Impl::resizeFS(Plugin *plugin, int n)
925
{
926
    // called with m_mutex held
927
    
928
#ifdef DEBUG_PLUGIN_ADAPTER
929
    cerr << "PluginAdapterBase::Impl::resizeFS(" << plugin << ", " << n << ")" << endl;
930
#endif
931

    
932
    int i = m_fsizes[plugin].size();
933
    if (i >= n) return;
934

    
935
#ifdef DEBUG_PLUGIN_ADAPTER
936
    cerr << "resizing from " << i << endl;
937
#endif
938

    
939
    m_fs[plugin] = (VampFeatureList *)realloc
940
        (m_fs[plugin], n * sizeof(VampFeatureList));
941

    
942
    while (i < n) {
943
        m_fs[plugin][i].featureCount = 0;
944
        m_fs[plugin][i].features = 0;
945
        m_fsizes[plugin].push_back(0);
946
        m_fvsizes[plugin].push_back(vector<size_t>());
947
        i++;
948
    }
949
}
950

    
951
void
952
PluginAdapterBase::Impl::resizeFL(Plugin *plugin, int n, size_t sz)
953
{
954
    // called with m_mutex held
955
    
956
#ifdef DEBUG_PLUGIN_ADAPTER
957
    cerr << "PluginAdapterBase::Impl::resizeFL(" << plugin << ", " << n << ", "
958
              << sz << ")" << endl;
959
#endif
960
    
961
    size_t i = m_fsizes[plugin][n];
962
    if (i >= sz) return;
963

    
964
#ifdef DEBUG_PLUGIN_ADAPTER
965
    cerr << "resizing from " << i << endl;
966
#endif
967

    
968
    m_fs[plugin][n].features = (VampFeatureUnion *)realloc
969
        (m_fs[plugin][n].features, 2 * sz * sizeof(VampFeatureUnion));
970

    
971
    while (m_fsizes[plugin][n] < sz) {
972
        m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.hasTimestamp = 0;
973
        m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.valueCount = 0;
974
        m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.values = 0;
975
        m_fs[plugin][n].features[m_fsizes[plugin][n]].v1.label = 0;
976
        m_fs[plugin][n].features[m_fsizes[plugin][n] + sz].v2.hasDuration = 0;
977
        m_fvsizes[plugin][n].push_back(0);
978
        m_fsizes[plugin][n]++;
979
    }
980
}
981

    
982
void
983
PluginAdapterBase::Impl::resizeFV(Plugin *plugin, int n, int j, size_t sz)
984
{
985
    // called with m_mutex held
986
    
987
#ifdef DEBUG_PLUGIN_ADAPTER
988
    cerr << "PluginAdapterBase::Impl::resizeFV(" << plugin << ", " << n << ", "
989
              << j << ", " << sz << ")" << endl;
990
#endif
991
    
992
    size_t i = m_fvsizes[plugin][n][j];
993
    if (i >= sz) return;
994

    
995
#ifdef DEBUG_PLUGIN_ADAPTER
996
    cerr << "resizing from " << i << endl;
997
#endif
998
    
999
    m_fs[plugin][n].features[j].v1.values = (float *)realloc
1000
        (m_fs[plugin][n].features[j].v1.values, sz * sizeof(float));
1001

    
1002
    m_fvsizes[plugin][n][j] = sz;
1003
}
1004
  
1005
PluginAdapterBase::Impl::AdapterMap *
1006
PluginAdapterBase::Impl::m_adapterMap = 0;
1007

    
1008
}
1009

    
1010
_VAMP_SDK_PLUGSPACE_END(PluginAdapter.cpp)
1011