annotate src/vamp-hostsdk/PluginHostAdapter.cpp @ 538:8ffb8985ae8f

Add ability to disown a wrapped plugin - making it possible to use the adapters in some situations involving managed pointers that didn't work previously
author Chris Cannam
date Thu, 23 Apr 2020 11:39:34 +0100
parents db2cd87cef6f
children 15a89a89aa9b
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@230 37 #include <vamp-hostsdk/PluginHostAdapter.h>
cannam@130 38 #include <cstdlib>
cannam@1 39
Chris@512 40 #include "Files.h"
Chris@512 41
Chris@528 42 #if ( VAMP_SDK_MAJOR_VERSION != 2 || VAMP_SDK_MINOR_VERSION != 9 )
cannam@308 43 #error Unexpected version of Vamp SDK header included
cannam@234 44 #endif
cannam@234 45
cannam@263 46 _VAMP_SDK_HOSTSPACE_BEGIN(PluginHostAdapter.cpp)
cannam@263 47
cannam@1 48 namespace Vamp
cannam@1 49 {
cannam@1 50
cannam@1 51 PluginHostAdapter::PluginHostAdapter(const VampPluginDescriptor *descriptor,
cannam@1 52 float inputSampleRate) :
cannam@1 53 Plugin(inputSampleRate),
cannam@1 54 m_descriptor(descriptor)
cannam@1 55 {
cannam@15 56 // std::cerr << "PluginHostAdapter::PluginHostAdapter (plugin = " << descriptor->name << ")" << std::endl;
cannam@1 57 m_handle = m_descriptor->instantiate(m_descriptor, inputSampleRate);
cannam@15 58 if (!m_handle) {
cannam@15 59 // std::cerr << "WARNING: PluginHostAdapter: Plugin instantiation failed for plugin " << m_descriptor->name << std::endl;
cannam@15 60 }
cannam@1 61 }
cannam@1 62
cannam@1 63 PluginHostAdapter::~PluginHostAdapter()
cannam@1 64 {
cannam@15 65 // std::cerr << "PluginHostAdapter::~PluginHostAdapter (plugin = " << m_descriptor->name << ")" << std::endl;
cannam@1 66 if (m_handle) m_descriptor->cleanup(m_handle);
cannam@1 67 }
cannam@1 68
cannam@32 69 std::vector<std::string>
cannam@32 70 PluginHostAdapter::getPluginPath()
cannam@32 71 {
cannam@32 72 std::vector<std::string> path;
cannam@32 73 std::string envPath;
cannam@32 74
Chris@513 75 if (Files::isNonNative32Bit()) {
Chris@513 76 (void)Files::getEnvUtf8("VAMP_PATH_32", envPath);
Chris@513 77 } else {
Chris@513 78 (void)Files::getEnvUtf8("VAMP_PATH", envPath);
Chris@513 79 }
cannam@32 80
cannam@32 81 #ifdef _WIN32
cannam@32 82 #define PATH_SEPARATOR ';'
cannam@32 83 #define DEFAULT_VAMP_PATH "%ProgramFiles%\\Vamp Plugins"
cannam@32 84 #else
cannam@32 85 #define PATH_SEPARATOR ':'
cannam@32 86 #ifdef __APPLE__
cannam@35 87 #define DEFAULT_VAMP_PATH "$HOME/Library/Audio/Plug-Ins/Vamp:/Library/Audio/Plug-Ins/Vamp"
cannam@32 88 #else
cannam@35 89 #define DEFAULT_VAMP_PATH "$HOME/vamp:$HOME/.vamp:/usr/local/lib/vamp:/usr/lib/vamp"
cannam@32 90 #endif
cannam@32 91 #endif
cannam@32 92
cannam@32 93 if (envPath == "") {
cannam@32 94 envPath = DEFAULT_VAMP_PATH;
Chris@512 95 std::string home;
Chris@512 96 if (Files::getEnvUtf8("HOME", home)) {
cannam@32 97 std::string::size_type f;
cannam@32 98 while ((f = envPath.find("$HOME")) != std::string::npos &&
cannam@32 99 f < envPath.length()) {
cannam@32 100 envPath.replace(f, 5, home);
cannam@32 101 }
cannam@32 102 }
cannam@32 103 #ifdef _WIN32
Chris@512 104 std::string pfiles;
Chris@512 105 if (!Files::getEnvUtf8("ProgramFiles", pfiles)) {
Chris@512 106 pfiles = "C:\\Program Files";
Chris@512 107 }
cannam@32 108 std::string::size_type f;
cannam@32 109 while ((f = envPath.find("%ProgramFiles%")) != std::string::npos &&
cannam@32 110 f < envPath.length()) {
cannam@32 111 envPath.replace(f, 14, pfiles);
cannam@32 112 }
cannam@32 113 #endif
cannam@32 114 }
cannam@32 115
cannam@32 116 std::string::size_type index = 0, newindex = 0;
cannam@32 117
cannam@32 118 while ((newindex = envPath.find(PATH_SEPARATOR, index)) < envPath.size()) {
cannam@32 119 path.push_back(envPath.substr(index, newindex - index));
cannam@32 120 index = newindex + 1;
cannam@32 121 }
cannam@32 122
cannam@32 123 path.push_back(envPath.substr(index));
cannam@32 124
cannam@32 125 return path;
cannam@32 126 }
cannam@32 127
cannam@1 128 bool
cannam@1 129 PluginHostAdapter::initialise(size_t channels,
cannam@1 130 size_t stepSize,
cannam@1 131 size_t blockSize)
cannam@1 132 {
cannam@1 133 if (!m_handle) return false;
Chris@421 134 return m_descriptor->initialise
Chris@421 135 (m_handle,
Chris@421 136 (unsigned int)channels,
Chris@421 137 (unsigned int)stepSize,
Chris@421 138 (unsigned int)blockSize) ?
cannam@1 139 true : false;
cannam@1 140 }
cannam@1 141
cannam@1 142 void
cannam@1 143 PluginHostAdapter::reset()
cannam@1 144 {
cannam@197 145 if (!m_handle) {
cannam@197 146 // std::cerr << "PluginHostAdapter::reset: no handle" << std::endl;
cannam@197 147 return;
cannam@197 148 }
cannam@197 149 // std::cerr << "PluginHostAdapter::reset(" << m_handle << ")" << std::endl;
cannam@1 150 m_descriptor->reset(m_handle);
cannam@1 151 }
cannam@1 152
cannam@1 153 PluginHostAdapter::InputDomain
cannam@1 154 PluginHostAdapter::getInputDomain() const
cannam@1 155 {
cannam@1 156 if (m_descriptor->inputDomain == vampFrequencyDomain) {
cannam@1 157 return FrequencyDomain;
cannam@1 158 } else {
cannam@1 159 return TimeDomain;
cannam@1 160 }
cannam@1 161 }
cannam@1 162
cannam@50 163 unsigned int
cannam@50 164 PluginHostAdapter::getVampApiVersion() const
cannam@50 165 {
cannam@50 166 return m_descriptor->vampApiVersion;
cannam@50 167 }
cannam@50 168
cannam@1 169 std::string
cannam@49 170 PluginHostAdapter::getIdentifier() const
cannam@49 171 {
cannam@49 172 return m_descriptor->identifier;
cannam@49 173 }
cannam@49 174
cannam@49 175 std::string
cannam@1 176 PluginHostAdapter::getName() const
cannam@1 177 {
cannam@1 178 return m_descriptor->name;
cannam@1 179 }
cannam@1 180
cannam@1 181 std::string
cannam@1 182 PluginHostAdapter::getDescription() const
cannam@1 183 {
cannam@1 184 return m_descriptor->description;
cannam@1 185 }
cannam@1 186
cannam@1 187 std::string
cannam@1 188 PluginHostAdapter::getMaker() const
cannam@1 189 {
cannam@1 190 return m_descriptor->maker;
cannam@1 191 }
cannam@1 192
cannam@1 193 int
cannam@1 194 PluginHostAdapter::getPluginVersion() const
cannam@1 195 {
cannam@1 196 return m_descriptor->pluginVersion;
cannam@1 197 }
cannam@1 198
cannam@1 199 std::string
cannam@1 200 PluginHostAdapter::getCopyright() const
cannam@1 201 {
cannam@1 202 return m_descriptor->copyright;
cannam@1 203 }
cannam@1 204
cannam@1 205 PluginHostAdapter::ParameterList
cannam@1 206 PluginHostAdapter::getParameterDescriptors() const
cannam@1 207 {
cannam@1 208 ParameterList list;
cannam@1 209 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@1 210 const VampParameterDescriptor *spd = m_descriptor->parameters[i];
cannam@1 211 ParameterDescriptor pd;
cannam@49 212 pd.identifier = spd->identifier;
cannam@1 213 pd.name = spd->name;
cannam@1 214 pd.description = spd->description;
cannam@1 215 pd.unit = spd->unit;
cannam@1 216 pd.minValue = spd->minValue;
cannam@1 217 pd.maxValue = spd->maxValue;
cannam@1 218 pd.defaultValue = spd->defaultValue;
cannam@1 219 pd.isQuantized = spd->isQuantized;
cannam@1 220 pd.quantizeStep = spd->quantizeStep;
cannam@9 221 if (pd.isQuantized && spd->valueNames) {
cannam@9 222 for (unsigned int j = 0; spd->valueNames[j]; ++j) {
cannam@9 223 pd.valueNames.push_back(spd->valueNames[j]);
cannam@9 224 }
cannam@9 225 }
cannam@1 226 list.push_back(pd);
cannam@1 227 }
cannam@1 228 return list;
cannam@1 229 }
cannam@1 230
cannam@1 231 float
cannam@1 232 PluginHostAdapter::getParameter(std::string param) const
cannam@1 233 {
cannam@1 234 if (!m_handle) return 0.0;
cannam@1 235
cannam@1 236 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 237 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 238 return m_descriptor->getParameter(m_handle, i);
cannam@1 239 }
cannam@1 240 }
cannam@1 241
cannam@1 242 return 0.0;
cannam@1 243 }
cannam@1 244
cannam@1 245 void
cannam@1 246 PluginHostAdapter::setParameter(std::string param,
cannam@1 247 float value)
cannam@1 248 {
cannam@1 249 if (!m_handle) return;
cannam@1 250
cannam@1 251 for (unsigned int i = 0; i < m_descriptor->parameterCount; ++i) {
cannam@49 252 if (param == m_descriptor->parameters[i]->identifier) {
cannam@1 253 m_descriptor->setParameter(m_handle, i, value);
cannam@1 254 return;
cannam@1 255 }
cannam@1 256 }
cannam@1 257 }
cannam@1 258
cannam@1 259 PluginHostAdapter::ProgramList
cannam@1 260 PluginHostAdapter::getPrograms() const
cannam@1 261 {
cannam@1 262 ProgramList list;
cannam@1 263
cannam@1 264 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 265 list.push_back(m_descriptor->programs[i]);
cannam@1 266 }
cannam@1 267
cannam@1 268 return list;
cannam@1 269 }
cannam@1 270
cannam@1 271 std::string
cannam@1 272 PluginHostAdapter::getCurrentProgram() const
cannam@1 273 {
cannam@1 274 if (!m_handle) return "";
cannam@1 275
cannam@1 276 int pn = m_descriptor->getCurrentProgram(m_handle);
Chris@345 277 if (pn < (int)m_descriptor->programCount) {
Chris@345 278 return m_descriptor->programs[pn];
Chris@345 279 } else {
Chris@345 280 return "";
Chris@345 281 }
cannam@1 282 }
cannam@1 283
cannam@1 284 void
cannam@1 285 PluginHostAdapter::selectProgram(std::string program)
cannam@1 286 {
cannam@1 287 if (!m_handle) return;
cannam@1 288
cannam@1 289 for (unsigned int i = 0; i < m_descriptor->programCount; ++i) {
cannam@1 290 if (program == m_descriptor->programs[i]) {
cannam@1 291 m_descriptor->selectProgram(m_handle, i);
cannam@1 292 return;
cannam@1 293 }
cannam@1 294 }
cannam@1 295 }
cannam@1 296
cannam@1 297 size_t
cannam@1 298 PluginHostAdapter::getPreferredStepSize() const
cannam@1 299 {
cannam@1 300 if (!m_handle) return 0;
cannam@1 301 return m_descriptor->getPreferredStepSize(m_handle);
cannam@1 302 }
cannam@1 303
cannam@1 304 size_t
cannam@1 305 PluginHostAdapter::getPreferredBlockSize() const
cannam@1 306 {
cannam@1 307 if (!m_handle) return 0;
cannam@1 308 return m_descriptor->getPreferredBlockSize(m_handle);
cannam@1 309 }
cannam@1 310
cannam@26 311 size_t
cannam@26 312 PluginHostAdapter::getMinChannelCount() const
cannam@26 313 {
cannam@26 314 if (!m_handle) return 0;
cannam@26 315 return m_descriptor->getMinChannelCount(m_handle);
cannam@26 316 }
cannam@26 317
cannam@26 318 size_t
cannam@26 319 PluginHostAdapter::getMaxChannelCount() const
cannam@26 320 {
cannam@26 321 if (!m_handle) return 0;
cannam@26 322 return m_descriptor->getMaxChannelCount(m_handle);
cannam@26 323 }
cannam@26 324
cannam@1 325 PluginHostAdapter::OutputList
cannam@1 326 PluginHostAdapter::getOutputDescriptors() const
cannam@1 327 {
cannam@1 328 OutputList list;
cannam@15 329 if (!m_handle) {
cannam@15 330 // std::cerr << "PluginHostAdapter::getOutputDescriptors: no handle " << std::endl;
cannam@15 331 return list;
cannam@15 332 }
cannam@1 333
cannam@1 334 unsigned int count = m_descriptor->getOutputCount(m_handle);
cannam@1 335
cannam@1 336 for (unsigned int i = 0; i < count; ++i) {
cannam@1 337 VampOutputDescriptor *sd = m_descriptor->getOutputDescriptor(m_handle, i);
cannam@1 338 OutputDescriptor d;
cannam@49 339 d.identifier = sd->identifier;
cannam@1 340 d.name = sd->name;
cannam@1 341 d.description = sd->description;
cannam@1 342 d.unit = sd->unit;
cannam@9 343 d.hasFixedBinCount = sd->hasFixedBinCount;
cannam@9 344 d.binCount = sd->binCount;
cannam@240 345 if (d.hasFixedBinCount && sd->binNames) {
cannam@9 346 for (unsigned int j = 0; j < sd->binCount; ++j) {
cannam@9 347 d.binNames.push_back(sd->binNames[j] ? sd->binNames[j] : "");
cannam@9 348 }
cannam@1 349 }
cannam@1 350 d.hasKnownExtents = sd->hasKnownExtents;
cannam@1 351 d.minValue = sd->minValue;
cannam@1 352 d.maxValue = sd->maxValue;
cannam@1 353 d.isQuantized = sd->isQuantized;
cannam@1 354 d.quantizeStep = sd->quantizeStep;
cannam@1 355
cannam@1 356 switch (sd->sampleType) {
cannam@1 357 case vampOneSamplePerStep:
cannam@1 358 d.sampleType = OutputDescriptor::OneSamplePerStep; break;
cannam@1 359 case vampFixedSampleRate:
cannam@1 360 d.sampleType = OutputDescriptor::FixedSampleRate; break;
cannam@1 361 case vampVariableSampleRate:
cannam@1 362 d.sampleType = OutputDescriptor::VariableSampleRate; break;
cannam@1 363 }
cannam@1 364
cannam@1 365 d.sampleRate = sd->sampleRate;
cannam@1 366
cannam@192 367 if (m_descriptor->vampApiVersion >= 2) {
cannam@192 368 d.hasDuration = sd->hasDuration;
cannam@192 369 } else {
cannam@192 370 d.hasDuration = false;
cannam@192 371 }
cannam@192 372
cannam@1 373 list.push_back(d);
cannam@1 374
cannam@1 375 m_descriptor->releaseOutputDescriptor(sd);
cannam@1 376 }
cannam@1 377
cannam@1 378 return list;
cannam@1 379 }
cannam@1 380
cannam@1 381 PluginHostAdapter::FeatureSet
cannam@47 382 PluginHostAdapter::process(const float *const *inputBuffers,
cannam@47 383 RealTime timestamp)
cannam@1 384 {
cannam@1 385 FeatureSet fs;
cannam@1 386 if (!m_handle) return fs;
cannam@1 387
cannam@1 388 int sec = timestamp.sec;
cannam@1 389 int nsec = timestamp.nsec;
cannam@1 390
cannam@12 391 VampFeatureList *features = m_descriptor->process(m_handle,
cannam@1 392 inputBuffers,
cannam@1 393 sec, nsec);
cannam@1 394
cannam@1 395 convertFeatures(features, fs);
cannam@1 396 m_descriptor->releaseFeatureSet(features);
cannam@1 397 return fs;
cannam@1 398 }
cannam@1 399
cannam@1 400 PluginHostAdapter::FeatureSet
cannam@1 401 PluginHostAdapter::getRemainingFeatures()
cannam@1 402 {
cannam@1 403 FeatureSet fs;
cannam@1 404 if (!m_handle) return fs;
cannam@1 405
cannam@12 406 VampFeatureList *features = m_descriptor->getRemainingFeatures(m_handle);
cannam@1 407
cannam@1 408 convertFeatures(features, fs);
cannam@1 409 m_descriptor->releaseFeatureSet(features);
cannam@1 410 return fs;
cannam@1 411 }
cannam@1 412
cannam@1 413 void
cannam@12 414 PluginHostAdapter::convertFeatures(VampFeatureList *features,
cannam@1 415 FeatureSet &fs)
cannam@1 416 {
cannam@7 417 if (!features) return;
cannam@7 418
cannam@12 419 unsigned int outputs = m_descriptor->getOutputCount(m_handle);
cannam@12 420
cannam@12 421 for (unsigned int i = 0; i < outputs; ++i) {
cannam@1 422
cannam@12 423 VampFeatureList &list = features[i];
cannam@1 424
cannam@1 425 if (list.featureCount > 0) {
cannam@1 426
cannam@108 427 Feature feature;
cannam@168 428 feature.values.reserve(list.features[0].v1.valueCount);
cannam@108 429
cannam@1 430 for (unsigned int j = 0; j < list.featureCount; ++j) {
cannam@108 431
cannam@168 432 feature.hasTimestamp = list.features[j].v1.hasTimestamp;
cannam@168 433 feature.timestamp = RealTime(list.features[j].v1.sec,
cannam@168 434 list.features[j].v1.nsec);
cannam@168 435 feature.hasDuration = false;
cannam@1 436
cannam@167 437 if (m_descriptor->vampApiVersion >= 2) {
cannam@168 438 unsigned int j2 = j + list.featureCount;
cannam@168 439 feature.hasDuration = list.features[j2].v2.hasDuration;
cannam@168 440 feature.duration = RealTime(list.features[j2].v2.durationSec,
cannam@168 441 list.features[j2].v2.durationNsec);
cannam@167 442 }
cannam@167 443
cannam@168 444 for (unsigned int k = 0; k < list.features[j].v1.valueCount; ++k) {
cannam@168 445 feature.values.push_back(list.features[j].v1.values[k]);
cannam@1 446 }
cannam@7 447
cannam@168 448 if (list.features[j].v1.label) {
cannam@168 449 feature.label = list.features[j].v1.label;
cannam@7 450 }
cannam@1 451
cannam@1 452 fs[i].push_back(feature);
cannam@108 453
cannam@168 454 if (list.features[j].v1.valueCount > 0) {
cannam@108 455 feature.values.clear();
cannam@108 456 }
cannam@108 457
cannam@168 458 if (list.features[j].v1.label) {
cannam@108 459 feature.label = "";
cannam@108 460 }
cannam@1 461 }
cannam@1 462 }
cannam@1 463 }
cannam@1 464 }
cannam@1 465
cannam@1 466 }
cannam@263 467
cannam@263 468 _VAMP_SDK_HOSTSPACE_END(PluginHostAdapter.cpp)
cannam@263 469