annotate vamp-sdk/PluginHostAdapter.cpp @ 98:896a97349ac5

* Add a static wrapper object to wrap the static instance pointer, so that it can be properly deleted on program exit instead of showing up in certain tools as leaked
author cannam
date Mon, 03 Dec 2007 12:57:27 +0000
parents b907557b2fb9
children 1e7ab0399852
rev   line source
cannam@1 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
cannam@1 2
cannam@1 3 /*
cannam@1 4 Vamp
cannam@1 5
cannam@1 6 An API for audio analysis and feature extraction plugins.
cannam@1 7
cannam@1 8 Centre for Digital Music, Queen Mary, University of London.
cannam@1 9 Copyright 2006 Chris Cannam.
cannam@1 10
cannam@1 11 Permission is hereby granted, free of charge, to any person
cannam@1 12 obtaining a copy of this software and associated documentation
cannam@1 13 files (the "Software"), to deal in the Software without
cannam@1 14 restriction, including without limitation the rights to use, copy,
cannam@1 15 modify, merge, publish, distribute, sublicense, and/or sell copies
cannam@1 16 of the Software, and to permit persons to whom the Software is
cannam@1 17 furnished to do so, subject to the following conditions:
cannam@1 18
cannam@1 19 The above copyright notice and this permission notice shall be
cannam@1 20 included in all copies or substantial portions of the Software.
cannam@1 21
cannam@1 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@1 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@1 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
cannam@6 25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
cannam@1 26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@1 27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@1 28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@1 29
cannam@1 30 Except as contained in this notice, the names of the Centre for
cannam@1 31 Digital Music; Queen Mary, University of London; and Chris Cannam
cannam@1 32 shall not be used in advertising or otherwise to promote the sale,
cannam@1 33 use or other dealings in this Software without prior written
cannam@1 34 authorization.
cannam@1 35 */
cannam@1 36
cannam@1 37 #include "PluginHostAdapter.h"
cannam@1 38
cannam@1 39 namespace Vamp
cannam@1 40 {
cannam@1 41
cannam@1 42 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
cannam@1 43 float inputSampleRate) :
cannam@1 44 Plugin(inputSampleRate),
cannam@1 45 m_descriptor(descriptor)
cannam@1 46 {
cannam@15 47 // std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
cannam@1 48 m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
cannam@15 49 if (!m_handle) {
cannam@15 50 // std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
cannam@15 51 }
cannam@1 52 }
cannam@1 53
cannam@1 54 PluginHostAdapter::~PluginHostAdapter()
cannam@1 55 {
cannam@15 56 // std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
cannam@1 57 if (m_handle) m_descriptor->cleanup(m_handle);
cannam@1 58 }
cannam@1 59
cannam@32 60 std::vector<std::string>
cannam@32 61 PluginHostAdapter::getPluginPath()
cannam@32 62 {
cannam@32 63 std::vector<std::string> path;
cannam@32 64 std::string envPath;
cannam@32 65
cannam@32 66 char *cpath = getenv("VAMP_PATH");
cannam@32 67 if (cpath) envPath = cpath;
cannam@32 68
cannam@32 69 #ifdef _WIN32
cannam@32 70 #define PATH_SEPARATOR ';'
cannam@32 71 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
cannam@32 72 #else
cannam@32 73 #define PATH_SEPARATOR ':'
cannam@32 74 #ifdef __APPLE__
cannam@35 75 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
cannam@32 76 #else
cannam@35 77 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
cannam@32 78 #endif
cannam@32 79 #endif
cannam@32 80
cannam@32 81 if (envPath == "") {
cannam@32 82 envPath = DEFAULT_VAMP_PATH;
cannam@32 83 char *chome = getenv("HOME");
cannam@32 84 if (chome) {
cannam@32 85 std::string home(chome);
cannam@32 86 std::string::size_type f;
cannam@32 87 while ((f = envPath.find("$HOME")) != std::string::npos &&
cannam@32 88 f < envPath.length()) {
cannam@32 89 envPath.replace(f, 5, home);
cannam@32 90 }
cannam@32 91 }
cannam@32 92 #ifdef _WIN32
cannam@32 93 char *cpfiles = getenv("ProgramFiles");
cannam@32 94 if (!cpfiles) cpfiles = "C:\\Program Files";
cannam@32 95 std::string pfiles(cpfiles);
cannam@32 96 std::string::size_type f;
cannam@32 97 while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
cannam@32 98 f < envPath.length()) {
cannam@32 99 envPath.replace(f, 14, pfiles);
cannam@32 100 }
cannam@32 101 #endif
cannam@32 102 }
cannam@32 103
cannam@32 104 std::string::size_type index = 0, newindex = 0;
cannam@32 105
cannam@32 106 while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
cannam@32 107 path.push_back(envPath.substr(index, newindex - index));
cannam@32 108 index = newindex + 1;
cannam@32 109 }
cannam@32 110
cannam@32 111 path.push_back(envPath.substr(index));
cannam@32 112
cannam@32 113 return path;
cannam@32 114 }
cannam@32 115
cannam@1 116 bool
cannam@1 117 PluginHostAdapter::initialise(size_t channels,
cannam@1 118 size_t stepSize,
cannam@1 119 size_t blockSize)
cannam@1 120 {
cannam@1 121 if (!m_handle) return false;
cannam@1 122 return m_descriptor->initialise(m_handle, channels, stepSize, blockSize) ?
cannam@1 123 true : false;
cannam@1 124 }
cannam@1 125
cannam@1 126 void
cannam@1 127 PluginHostAdapter::reset()
cannam@1 128 {
cannam@1 129 if (!m_handle) return;
cannam@1 130 m_descriptor->reset(m_handle);
cannam@1 131 }
cannam@1 132
cannam@1 133 PluginHostAdapter::InputDomain
cannam@1 134 PluginHostAdapter::getInputDomain() const
cannam@1 135 {
cannam@1 136 if (m_descriptor->inputDomain == vampFrequencyDomain) {
cannam@1 137 return FrequencyDomain;
cannam@1 138 } else {
cannam@1 139 return TimeDomain;
cannam@1 140 }
cannam@1 141 }
cannam@1 142
cannam@50 143 unsigned int
cannam@50 144 PluginHostAdapter::getVampApiVersion() const
cannam@50 145 {
cannam@50 146 return m_descriptor->vampApiVersion;
cannam@50 147 }
cannam@50 148
cannam@1 149 std::string
cannam@49 150 PluginHostAdapter::getIdentifier() const
cannam@49 151 {
cannam@49 152 return m_descriptor->identifier;
cannam@49 153 }
cannam@49 154
cannam@49 155 std::string
cannam@1 156 PluginHostAdapter::getName() const
cannam@1 157 {
cannam@1 158 return m_descriptor->name;
cannam@1 159 }
cannam@1 160
cannam@1 161 std::string
cannam@1 162 PluginHostAdapter::getDescription() const
cannam@1 163 {
cannam@1 164 return m_descriptor->description;
cannam@1 165 }
cannam@1 166
cannam@1 167 std::string
cannam@1 168 PluginHostAdapter::getMaker() const
cannam@1 169 {
cannam@1 170 return m_descriptor->maker;
cannam@1 171 }
cannam@1 172
cannam@1 173 int
cannam@1 174 PluginHostAdapter::getPluginVersion() const
cannam@1 175 {
cannam@1 176 return m_descriptor->pluginVersion;
cannam@1 177 }
cannam@1 178
cannam@1 179 std::string
cannam@1 180 PluginHostAdapter::getCopyright() const
cannam@1 181 {
cannam@1 182 return m_descriptor->copyright;
cannam@1 183 }
cannam@1 184
cannam@1 185 PluginHostAdapter::ParameterList
cannam@1 186 PluginHostAdapter::getParameterDescriptors() const
cannam@1 187 {
cannam@1 188 ParameterList list;
cannam@1 189 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@1 190 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
cannam@1 191 ParameterDescriptor pd;
cannam@49 192 pd.identifier = spd->identifier;
cannam@1 193 pd.name = spd->name;
cannam@1 194 pd.description = spd->description;
cannam@1 195 pd.unit = spd->unit;
cannam@1 196 pd.minValue = spd->minValue;
cannam@1 197 pd.maxValue = spd->maxValue;
cannam@1 198 pd.defaultValue = spd->defaultValue;
cannam@1 199 pd.isQuantized = spd->isQuantized;
cannam@1 200 pd.quantizeStep = spd->quantizeStep;
cannam@9 201 if (pd.isQuantized && spd->valueNames) {
cannam@9 202 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
cannam@9 203 pd.valueNames.push_back(spd->valueNames[j]);
cannam@9 204 }
cannam@9 205 }
cannam@1 206 list.push_back(pd);
cannam@1 207 }
cannam@1 208 return list;
cannam@1 209 }
cannam@1 210
cannam@1 211 float
cannam@1 212 PluginHostAdapter::getParameter(std::string param) const
cannam@1 213 {
cannam@1 214 if (!m_handle) return 0.0;
cannam@1 215
cannam@1 216 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 217 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 218 return m_descriptor->getParameter(m_handle, i);
cannam@1 219 }
cannam@1 220 }
cannam@1 221
cannam@1 222 return 0.0;
cannam@1 223 }
cannam@1 224
cannam@1 225 void
cannam@1 226 PluginHostAdapter::setParameter(std::string param,
cannam@1 227 float value)
cannam@1 228 {
cannam@1 229 if (!m_handle) return;
cannam@1 230
cannam@1 231 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 232 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 233 m_descriptor->setParameter(m_handle, i, value);
cannam@1 234 return;
cannam@1 235 }
cannam@1 236 }
cannam@1 237 }
cannam@1 238
cannam@1 239 PluginHostAdapter::ProgramList
cannam@1 240 PluginHostAdapter::getPrograms() const
cannam@1 241 {
cannam@1 242 ProgramList list;
cannam@1 243
cannam@1 244 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 245 list.push_back(m_descriptor->programs[i]);
cannam@1 246 }
cannam@1 247
cannam@1 248 return list;
cannam@1 249 }
cannam@1 250
cannam@1 251 std::string
cannam@1 252 PluginHostAdapter::getCurrentProgram() const
cannam@1 253 {
cannam@1 254 if (!m_handle) return "";
cannam@1 255
cannam@1 256 int pn = m_descriptor->getCurrentProgram(m_handle);
cannam@1 257 return m_descriptor->programs[pn];
cannam@1 258 }
cannam@1 259
cannam@1 260 void
cannam@1 261 PluginHostAdapter::selectProgram(std::string program)
cannam@1 262 {
cannam@1 263 if (!m_handle) return;
cannam@1 264
cannam@1 265 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 266 if (program == m_descriptor->programs[i]) {
cannam@1 267 m_descriptor->selectProgram(m_handle, i);
cannam@1 268 return;
cannam@1 269 }
cannam@1 270 }
cannam@1 271 }
cannam@1 272
cannam@1 273 size_t
cannam@1 274 PluginHostAdapter::getPreferredStepSize() const
cannam@1 275 {
cannam@1 276 if (!m_handle) return 0;
cannam@1 277 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 278 }
cannam@1 279
cannam@1 280 size_t
cannam@1 281 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 282 {
cannam@1 283 if (!m_handle) return 0;
cannam@1 284 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 285 }
cannam@1 286
cannam@26 287 size_t
cannam@26 288 PluginHostAdapter::getMinChannelCount() const
cannam@26 289 {
cannam@26 290 if (!m_handle) return 0;
cannam@26 291 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 292 }
cannam@26 293
cannam@26 294 size_t
cannam@26 295 PluginHostAdapter::getMaxChannelCount() const
cannam@26 296 {
cannam@26 297 if (!m_handle) return 0;
cannam@26 298 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 299 }
cannam@26 300
cannam@1 301 PluginHostAdapter::OutputList
cannam@1 302 PluginHostAdapter::getOutputDescriptors() const
cannam@1 303 {
cannam@1 304 OutputList list;
cannam@15 305 if (!m_handle) {
cannam@15 306 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 307 return list;
cannam@15 308 }
cannam@1 309
cannam@1 310 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 311
cannam@1 312 for (unsigned int i = 0; i < count; ++i) {
cannam@1 313 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 314 OutputDescriptor d;
cannam@49 315 d.identifier = sd->identifier;
cannam@1 316 d.name = sd->name;
cannam@1 317 d.description = sd->description;
cannam@1 318 d.unit = sd->unit;
cannam@9 319 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 320 d.binCount = sd->binCount;
cannam@9 321 if (d.hasFixedBinCount) {
cannam@9 322 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 323 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 324 }
cannam@1 325 }
cannam@1 326 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 327 d.minValue = sd->minValue;
cannam@1 328 d.maxValue = sd->maxValue;
cannam@1 329 d.isQuantized = sd->isQuantized;
cannam@1 330 d.quantizeStep = sd->quantizeStep;
cannam@1 331
cannam@1 332 switch (sd->sampleType) {
cannam@1 333 case vampOneSamplePerStep:
cannam@1 334 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 335 case vampFixedSampleRate:
cannam@1 336 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 337 case vampVariableSampleRate:
cannam@1 338 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 339 }
cannam@1 340
cannam@1 341 d.sampleRate = sd->sampleRate;
cannam@1 342
cannam@1 343 list.push_back(d);
cannam@1 344
cannam@1 345 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 346 }
cannam@1 347
cannam@1 348 return list;
cannam@1 349 }
cannam@1 350
cannam@1 351 PluginHostAdapter::FeatureSet
cannam@47 352 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 353 RealTime timestamp)
cannam@1 354 {
cannam@1 355 FeatureSet fs;
cannam@1 356 if (!m_handle) return fs;
cannam@1 357
cannam@1 358 int sec = timestamp.sec;
cannam@1 359 int nsec = timestamp.nsec;
cannam@1 360
cannam@12 361 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 362 inputBuffers,
cannam@1 363 sec, nsec);
cannam@1 364
cannam@1 365 convertFeatures(features, fs);
cannam@1 366 m_descriptor->releaseFeatureSet(features);
cannam@1 367 return fs;
cannam@1 368 }
cannam@1 369
cannam@1 370 PluginHostAdapter::FeatureSet
cannam@1 371 PluginHostAdapter::getRemainingFeatures()
cannam@1 372 {
cannam@1 373 FeatureSet fs;
cannam@1 374 if (!m_handle) return fs;
cannam@1 375
cannam@12 376 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 377
cannam@1 378 convertFeatures(features, fs);
cannam@1 379 m_descriptor->releaseFeatureSet(features);
cannam@1 380 return fs;
cannam@1 381 }
cannam@1 382
cannam@1 383 void
cannam@12 384 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 385 FeatureSet &fs)
cannam@1 386 {
cannam@7 387 if (!features) return;
cannam@7 388
cannam@12 389 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 390
cannam@12 391 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 392
cannam@12 393 VampFeatureList &list = features[i];
cannam@1 394
cannam@1 395 if (list.featureCount > 0) {
cannam@1 396
cannam@1 397 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@1 398
cannam@1 399 Feature feature;
cannam@1 400 feature.hasTimestamp = list.features[j].hasTimestamp;
cannam@1 401 feature.timestamp = RealTime(list.features[j].sec,
cannam@1 402 list.features[j].nsec);
cannam@1 403
cannam@1 404 for (unsigned int k = 0; k < list.features[j].valueCount; ++k) {
cannam@1 405 feature.values.push_back(list.features[j].values[k]);
cannam@1 406 }
cannam@7 407
cannam@7 408 if (list.features[j].label) {
cannam@7 409 feature.label = list.features[j].label;
cannam@7 410 }
cannam@1 411
cannam@1 412 fs[i].push_back(feature);
cannam@1 413 }
cannam@1 414 }
cannam@1 415 }
cannam@1 416 }
cannam@1 417
cannam@1 418 }