annotate plugin/DSSIPluginFactory.cpp @ 1520:954d0cf29ca7 import-audio-data

Switch the normalisation option in WritableWaveFileModel from normalising on read to normalising on write, so that the saved file is already normalised and therefore can be read again without having to remember to normalise it
author Chris Cannam
date Wed, 12 Sep 2018 13:56:56 +0100
parents 5ac102155409
children 70e172e6cc59
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@52 8 This program is free software; you can redistribute it and/or
Chris@52 9 modify it under the terms of the GNU General Public License as
Chris@52 10 published by the Free Software Foundation; either version 2 of the
Chris@52 11 License, or (at your option) any later version. See the file
Chris@52 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /*
Chris@0 16 This is a modified version of a source file from the
Chris@0 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 18 This file copyright 2000-2006 Chris Cannam.
Chris@0 19 */
Chris@0 20
Chris@0 21 #include "DSSIPluginFactory.h"
Chris@0 22 #include <iostream>
Chris@0 23
Chris@0 24 #include <QString>
Chris@0 25
Chris@0 26 #include "DSSIPluginInstance.h"
Chris@0 27 #include "PluginIdentifier.h"
Chris@0 28
Chris@405 29 #include <cstdlib>
Chris@405 30
Chris@408 31 #include "base/Profiler.h"
Chris@408 32
Chris@0 33 //!!!
Chris@150 34 #include "plugin/plugins/SamplePlayer.h"
Chris@0 35
Chris@150 36 #include "system/System.h"
Chris@0 37
Chris@35 38 #ifdef HAVE_LRDF
Chris@0 39 #include "lrdf.h"
Chris@35 40 #endif // HAVE_LRDF
Chris@0 41
Chris@1480 42 using std::string;
Chris@0 43
Chris@0 44 DSSIPluginFactory::DSSIPluginFactory() :
Chris@0 45 LADSPAPluginFactory()
Chris@0 46 {
Chris@0 47 m_hostDescriptor.DSSI_API_Version = 2;
Chris@0 48 m_hostDescriptor.request_transport_information = NULL;
Chris@0 49 m_hostDescriptor.request_midi_send = DSSIPluginInstance::requestMidiSend;
Chris@0 50 m_hostDescriptor.request_non_rt_thread = DSSIPluginInstance::requestNonRTThread;
Chris@0 51 m_hostDescriptor.midi_send = DSSIPluginInstance::midiSend;
Chris@0 52 }
Chris@0 53
Chris@0 54 DSSIPluginFactory::~DSSIPluginFactory()
Chris@0 55 {
Chris@0 56 // nothing else to do here either
Chris@0 57 }
Chris@0 58
Chris@0 59 void
Chris@0 60 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list)
Chris@0 61 {
Chris@408 62 Profiler profiler("DSSIPluginFactory::enumeratePlugins");
Chris@408 63
Chris@0 64 for (std::vector<QString>::iterator i = m_identifiers.begin();
Chris@1429 65 i != m_identifiers.end(); ++i) {
Chris@0 66
Chris@1429 67 const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i);
Chris@1429 68 if (!ddesc) continue;
Chris@0 69
Chris@1429 70 const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin;
Chris@1429 71 if (!descriptor) continue;
Chris@1429 72
Chris@1429 73 // SVDEBUG << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << endl;
Chris@0 74
Chris@1429 75 list.push_back(*i);
Chris@1429 76 list.push_back(descriptor->Name);
Chris@1429 77 list.push_back(QString("%1").arg(descriptor->UniqueID));
Chris@1429 78 list.push_back(descriptor->Label);
Chris@1429 79 list.push_back(descriptor->Maker);
Chris@1429 80 list.push_back(descriptor->Copyright);
Chris@1429 81 list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false");
Chris@1429 82 list.push_back(ddesc->run_multiple_synths ? "true" : "false");
Chris@1429 83 list.push_back(m_taxonomy[*i]);
Chris@1429 84 list.push_back(QString("%1").arg(descriptor->PortCount));
Chris@0 85
Chris@1429 86 for (int p = 0; p < (int)descriptor->PortCount; ++p) {
Chris@0 87
Chris@1429 88 int type = 0;
Chris@1429 89 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
Chris@1429 90 type |= PortType::Control;
Chris@1429 91 } else {
Chris@1429 92 type |= PortType::Audio;
Chris@1429 93 }
Chris@1429 94 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
Chris@1429 95 type |= PortType::Input;
Chris@1429 96 } else {
Chris@1429 97 type |= PortType::Output;
Chris@1429 98 }
Chris@0 99
Chris@1429 100 list.push_back(QString("%1").arg(p));
Chris@1429 101 list.push_back(descriptor->PortNames[p]);
Chris@1429 102 list.push_back(QString("%1").arg(type));
Chris@1429 103 list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
Chris@1429 104 list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
Chris@1429 105 list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
Chris@1429 106 list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
Chris@1429 107 }
Chris@0 108 }
Chris@0 109
Chris@0 110 unloadUnusedLibraries();
Chris@0 111 }
Chris@1429 112
Chris@0 113 RealTimePluginInstance *
Chris@0 114 DSSIPluginFactory::instantiatePlugin(QString identifier,
Chris@1429 115 int instrument,
Chris@1429 116 int position,
Chris@1429 117 sv_samplerate_t sampleRate,
Chris@1429 118 int blockSize,
Chris@1429 119 int channels)
Chris@0 120 {
Chris@408 121 Profiler profiler("DSSIPluginFactory::instantiatePlugin");
Chris@408 122
Chris@0 123 const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier);
Chris@0 124
Chris@0 125 if (descriptor) {
Chris@0 126
Chris@1429 127 DSSIPluginInstance *instance =
Chris@1429 128 new DSSIPluginInstance
Chris@1429 129 (this, instrument, identifier, position, sampleRate, blockSize, channels,
Chris@1429 130 descriptor);
Chris@0 131
Chris@1429 132 m_instances.insert(instance);
Chris@0 133
Chris@1429 134 return instance;
Chris@0 135 }
Chris@0 136
Chris@0 137 return 0;
Chris@0 138 }
Chris@0 139
Chris@0 140 const DSSI_Descriptor *
Chris@0 141 DSSIPluginFactory::getDSSIDescriptor(QString identifier)
Chris@0 142 {
Chris@0 143 QString type, soname, label;
Chris@0 144 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@0 145
Chris@0 146 if (soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
Chris@1429 147 if (label == "sample_player") {
Chris@1429 148 const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0);
Chris@1429 149 if (descriptor) {
Chris@1429 150 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@1429 151 }
Chris@1429 152 return descriptor;
Chris@1429 153 } else {
Chris@1429 154 return 0;
Chris@1429 155 }
Chris@0 156 }
Chris@0 157
Chris@0 158 bool firstInLibrary = false;
Chris@0 159
Chris@0 160 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@1429 161 loadLibrary(soname);
Chris@1429 162 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@1429 163 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname << endl;
Chris@1429 164 return 0;
Chris@1429 165 }
Chris@1429 166 firstInLibrary = true;
Chris@0 167 }
Chris@0 168
Chris@0 169 void *libraryHandle = m_libraryHandles[soname];
Chris@0 170
Chris@0 171 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@1429 172 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 173
Chris@0 174 if (!fn) {
Chris@1429 175 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname << endl;
Chris@1429 176 return 0;
Chris@0 177 }
Chris@0 178
Chris@0 179 const DSSI_Descriptor *descriptor = 0;
Chris@0 180
Chris@0 181 int index = 0;
Chris@0 182 while ((descriptor = fn(index))) {
Chris@1429 183 if (descriptor->LADSPA_Plugin->Label == label) {
Chris@1429 184 if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) {
Chris@1429 185 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@1429 186 }
Chris@1429 187 return descriptor;
Chris@1429 188 }
Chris@1429 189 ++index;
Chris@0 190 }
Chris@0 191
Chris@843 192 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label << " in library " << soname << endl;
Chris@0 193
Chris@0 194 return 0;
Chris@0 195 }
Chris@0 196
Chris@0 197 const LADSPA_Descriptor *
Chris@0 198 DSSIPluginFactory::getLADSPADescriptor(QString identifier)
Chris@0 199 {
Chris@0 200 const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier);
Chris@0 201 if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin;
Chris@0 202 else return 0;
Chris@0 203 }
Chris@0 204
Chris@0 205
Chris@0 206 std::vector<QString>
Chris@0 207 DSSIPluginFactory::getPluginPath()
Chris@0 208 {
Chris@0 209 std::vector<QString> pathList;
Chris@1480 210 string path;
Chris@0 211
Chris@1480 212 (void)getEnvUtf8("DSSI_PATH", path);
Chris@0 213
Chris@0 214 if (path == "") {
Chris@186 215
Chris@186 216 path = DEFAULT_DSSI_PATH;
Chris@186 217
Chris@1480 218 string home;
Chris@1480 219 if (getEnvUtf8("HOME", home)) {
Chris@1480 220 string::size_type f;
Chris@1480 221 while ((f = path.find("$HOME")) != string::npos &&
Chris@186 222 f < path.length()) {
Chris@186 223 path.replace(f, 5, home);
Chris@186 224 }
Chris@66 225 }
Chris@186 226
Chris@186 227 #ifdef _WIN32
Chris@1480 228 string pfiles;
Chris@1480 229 if (!getEnvUtf8("ProgramFiles", pfiles)) {
Chris@1480 230 pfiles = "C:\\Program Files";
Chris@1480 231 }
Chris@1480 232
Chris@1480 233 string::size_type f;
Chris@1480 234 while ((f = path.find("%ProgramFiles%")) != string::npos &&
Chris@186 235 f < path.length()) {
Chris@186 236 path.replace(f, 14, pfiles);
Chris@186 237 }
Chris@186 238 #endif
Chris@0 239 }
Chris@0 240
Chris@1480 241 string::size_type index = 0, newindex = 0;
Chris@0 242
Chris@223 243 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
Chris@1429 244 pathList.push_back(path.substr(index, newindex - index).c_str());
Chris@1429 245 index = newindex + 1;
Chris@0 246 }
Chris@0 247
Chris@0 248 pathList.push_back(path.substr(index).c_str());
Chris@0 249
Chris@0 250 return pathList;
Chris@0 251 }
Chris@0 252
Chris@0 253
Chris@0 254 std::vector<QString>
Chris@0 255 DSSIPluginFactory::getLRDFPath(QString &baseUri)
Chris@0 256 {
Chris@150 257 std::vector<QString> lrdfPaths;
Chris@150 258
Chris@150 259 #ifdef HAVE_LRDF
Chris@0 260 std::vector<QString> pathList = getPluginPath();
Chris@0 261
Chris@0 262 lrdfPaths.push_back("/usr/local/share/dssi/rdf");
Chris@0 263 lrdfPaths.push_back("/usr/share/dssi/rdf");
Chris@0 264
Chris@0 265 lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
Chris@0 266 lrdfPaths.push_back("/usr/share/ladspa/rdf");
Chris@0 267
Chris@0 268 for (std::vector<QString>::iterator i = pathList.begin();
Chris@1429 269 i != pathList.end(); ++i) {
Chris@1429 270 lrdfPaths.push_back(*i + "/rdf");
Chris@0 271 }
Chris@0 272
Chris@0 273 #ifdef DSSI_BASE
Chris@0 274 baseUri = DSSI_BASE;
Chris@0 275 #else
Chris@0 276 baseUri = "http://dssi.sourceforge.net/ontology#";
Chris@0 277 #endif
Chris@953 278 #else
Chris@953 279 // avoid unused parameter
Chris@953 280 baseUri = "";
Chris@150 281 #endif
Chris@0 282
Chris@0 283 return lrdfPaths;
Chris@0 284 }
Chris@0 285
Chris@0 286
Chris@0 287 void
Chris@929 288 DSSIPluginFactory::discoverPluginsFrom(QString soname)
Chris@0 289 {
Chris@408 290 Profiler profiler("DSSIPluginFactory::discoverPlugins");
Chris@408 291
Chris@0 292 // Note that soname is expected to be a full path at this point,
Chris@0 293 // of a file that is known to exist
Chris@0 294
Chris@0 295 void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
Chris@0 296
Chris@0 297 if (!libraryHandle) {
Chris@843 298 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
Chris@843 299 << soname << " - " << DLERROR() << endl;
Chris@0 300 return;
Chris@0 301 }
Chris@0 302
Chris@0 303 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@1429 304 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 305
Chris@0 306 if (!fn) {
Chris@1429 307 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname << endl;
Chris@1429 308 return;
Chris@0 309 }
Chris@0 310
Chris@0 311 const DSSI_Descriptor *descriptor = 0;
Chris@0 312
Chris@0 313 int index = 0;
Chris@0 314 while ((descriptor = fn(index))) {
Chris@0 315
Chris@1429 316 const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
Chris@1429 317 if (!ladspaDescriptor) {
Chris@1429 318 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname << endl;
Chris@1429 319 ++index;
Chris@1429 320 continue;
Chris@1429 321 }
Chris@0 322
Chris@60 323 RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor;
Chris@60 324 rtd->name = ladspaDescriptor->Name;
Chris@60 325 rtd->label = ladspaDescriptor->Label;
Chris@60 326 rtd->maker = ladspaDescriptor->Maker;
Chris@60 327 rtd->copyright = ladspaDescriptor->Copyright;
Chris@60 328 rtd->category = "";
Chris@60 329 rtd->isSynth = (descriptor->run_synth ||
Chris@60 330 descriptor->run_multiple_synths);
Chris@60 331 rtd->parameterCount = 0;
Chris@60 332 rtd->audioInputPortCount = 0;
Chris@166 333 rtd->audioOutputPortCount = 0;
Chris@60 334 rtd->controlOutputPortCount = 0;
Chris@60 335
Chris@1429 336 QString identifier = PluginIdentifier::createIdentifier
Chris@1429 337 ("dssi", soname, ladspaDescriptor->Label);
Chris@165 338
Chris@35 339 #ifdef HAVE_LRDF
Chris@1429 340 char *def_uri = 0;
Chris@1429 341 lrdf_defaults *defs = 0;
Chris@1429 342
Chris@1429 343 QString category = m_taxonomy[identifier];
Chris@165 344
Chris@166 345 if (category == "" && m_lrdfTaxonomy[ladspaDescriptor->UniqueID] != "") {
Chris@166 346 m_taxonomy[identifier] = m_lrdfTaxonomy[ladspaDescriptor->UniqueID];
Chris@165 347 category = m_taxonomy[identifier];
Chris@165 348 }
Chris@0 349
Chris@1429 350 if (category == "") {
Chris@1480 351 string name = rtd->name;
Chris@1429 352 if (name.length() > 4 &&
Chris@1429 353 name.substr(name.length() - 4) == " VST") {
Chris@1429 354 if (descriptor->run_synth || descriptor->run_multiple_synths) {
Chris@1429 355 category = "VST instruments";
Chris@1429 356 } else {
Chris@1429 357 category = "VST effects";
Chris@1429 358 }
Chris@1429 359 m_taxonomy[identifier] = category;
Chris@1429 360 }
Chris@1429 361 }
Chris@60 362
Chris@60 363 rtd->category = category.toStdString();
Chris@1429 364
Chris@1429 365 // cerr << "Plugin id is " << ladspaDescriptor->UniqueID
Chris@844 366 // << ", identifier is \"" << identifier
Chris@1429 367 // << "\", category is \"" << category
Chris@1429 368 // << "\", name is " << ladspaDescriptor->Name
Chris@1429 369 // << ", label is " << ladspaDescriptor->Label
Chris@1429 370 // << endl;
Chris@1429 371
Chris@1429 372 def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
Chris@1429 373 if (def_uri) {
Chris@1429 374 defs = lrdf_get_setting_values(def_uri);
Chris@1429 375 }
Chris@1429 376
Chris@1429 377 unsigned int controlPortNumber = 1;
Chris@1429 378
Chris@1429 379 for (int i = 0; i < (int)ladspaDescriptor->PortCount; i++) {
Chris@1429 380
Chris@1429 381 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@1429 382
Chris@1429 383 if (def_uri && defs) {
Chris@1429 384
Chris@1429 385 for (int j = 0; j < (int)defs->count; j++) {
Chris@1429 386 if (defs->items[j].pid == controlPortNumber) {
Chris@1429 387 // cerr << "Default for this port (" << defs->items[j].pid << ", " << defs->items[j].label << ") is " << defs->items[j].value << "; applying this to port number " << i << " with name " << ladspaDescriptor->PortNames[i] << endl;
Chris@1429 388 m_portDefaults[ladspaDescriptor->UniqueID][i] =
Chris@1429 389 defs->items[j].value;
Chris@1429 390 }
Chris@1429 391 }
Chris@1429 392 }
Chris@1429 393
Chris@1429 394 ++controlPortNumber;
Chris@1429 395 }
Chris@1429 396 }
Chris@35 397 #endif // HAVE_LRDF
Chris@0 398
Chris@1429 399 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@1429 400 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 401 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 402 ++rtd->parameterCount;
Chris@60 403 } else {
Chris@60 404 if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
Chris@60 405 strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
Chris@60 406 ++rtd->controlOutputPortCount;
Chris@60 407 rtd->controlOutputPortNames.push_back
Chris@60 408 (ladspaDescriptor->PortNames[i]);
Chris@60 409 }
Chris@60 410 }
Chris@60 411 } else {
Chris@60 412 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 413 ++rtd->audioInputPortCount;
Chris@166 414 } else if (LADSPA_IS_PORT_OUTPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@166 415 ++rtd->audioOutputPortCount;
Chris@60 416 }
Chris@60 417 }
Chris@60 418 }
Chris@60 419
Chris@1429 420 m_identifiers.push_back(identifier);
Chris@0 421
Chris@1464 422 m_libraries[identifier] = soname;
Chris@1464 423
Chris@60 424 m_rtDescriptors[identifier] = rtd;
Chris@60 425
Chris@1429 426 ++index;
Chris@0 427 }
Chris@0 428
Chris@0 429 if (DLCLOSE(libraryHandle) != 0) {
Chris@843 430 cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << endl;
Chris@0 431 return;
Chris@0 432 }
Chris@0 433 }
Chris@0 434
Chris@0 435
Chris@0 436