annotate plugin/DSSIPluginFactory.cpp @ 1196:c7b9c902642f spectrogram-minor-refactor

Fix threshold in spectrogram -- it wasn't working in the last release. There is a new protocol for this. Formerly the threshold parameter had a range from -50dB to 0 with the default at -50, and -50 treated internally as "no threshold". However, there was a hardcoded, hidden internal threshold for spectrogram colour mapping at -80dB with anything below this being rounded to zero. Now the threshold parameter has range -81 to -1 with the default at -80, -81 is treated internally as "no threshold", and there is no hidden internal threshold. So the default behaviour is the same as before, an effective -80dB threshold, but it is now possible to change this in both directions. Sessions reloaded from prior versions may look slightly different because, if the session says there should be no threshold, there will now actually be no threshold instead of having the hidden internal one. Still need to do something in the UI to make it apparent that the -81dB setting removes the threshold entirely. This is at least no worse than the previous, also obscured, magic -50dB setting.
author Chris Cannam
date Mon, 01 Aug 2016 16:21:01 +0100
parents a1cd5abcb38b
children 6b847a59d908
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@0 42
Chris@0 43 DSSIPluginFactory::DSSIPluginFactory() :
Chris@0 44 LADSPAPluginFactory()
Chris@0 45 {
Chris@0 46 m_hostDescriptor.DSSI_API_Version = 2;
Chris@0 47 m_hostDescriptor.request_transport_information = NULL;
Chris@0 48 m_hostDescriptor.request_midi_send = DSSIPluginInstance::requestMidiSend;
Chris@0 49 m_hostDescriptor.request_non_rt_thread = DSSIPluginInstance::requestNonRTThread;
Chris@0 50 m_hostDescriptor.midi_send = DSSIPluginInstance::midiSend;
Chris@0 51 }
Chris@0 52
Chris@0 53 DSSIPluginFactory::~DSSIPluginFactory()
Chris@0 54 {
Chris@0 55 // nothing else to do here either
Chris@0 56 }
Chris@0 57
Chris@0 58 void
Chris@0 59 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list)
Chris@0 60 {
Chris@408 61 Profiler profiler("DSSIPluginFactory::enumeratePlugins");
Chris@408 62
Chris@0 63 for (std::vector<QString>::iterator i = m_identifiers.begin();
Chris@0 64 i != m_identifiers.end(); ++i) {
Chris@0 65
Chris@0 66 const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i);
Chris@0 67 if (!ddesc) continue;
Chris@0 68
Chris@0 69 const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin;
Chris@0 70 if (!descriptor) continue;
Chris@0 71
Chris@690 72 // SVDEBUG << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << endl;
Chris@0 73
Chris@0 74 list.push_back(*i);
Chris@0 75 list.push_back(descriptor->Name);
Chris@0 76 list.push_back(QString("%1").arg(descriptor->UniqueID));
Chris@0 77 list.push_back(descriptor->Label);
Chris@0 78 list.push_back(descriptor->Maker);
Chris@0 79 list.push_back(descriptor->Copyright);
Chris@0 80 list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false");
Chris@0 81 list.push_back(ddesc->run_multiple_synths ? "true" : "false");
Chris@165 82 list.push_back(m_taxonomy[*i]);
Chris@0 83 list.push_back(QString("%1").arg(descriptor->PortCount));
Chris@0 84
Chris@1038 85 for (int p = 0; p < (int)descriptor->PortCount; ++p) {
Chris@0 86
Chris@0 87 int type = 0;
Chris@0 88 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
Chris@0 89 type |= PortType::Control;
Chris@0 90 } else {
Chris@0 91 type |= PortType::Audio;
Chris@0 92 }
Chris@0 93 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
Chris@0 94 type |= PortType::Input;
Chris@0 95 } else {
Chris@0 96 type |= PortType::Output;
Chris@0 97 }
Chris@0 98
Chris@0 99 list.push_back(QString("%1").arg(p));
Chris@0 100 list.push_back(descriptor->PortNames[p]);
Chris@0 101 list.push_back(QString("%1").arg(type));
Chris@0 102 list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
Chris@0 103 list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
Chris@0 104 list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
Chris@0 105 list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
Chris@0 106 }
Chris@0 107 }
Chris@0 108
Chris@0 109 unloadUnusedLibraries();
Chris@0 110 }
Chris@0 111
Chris@0 112 RealTimePluginInstance *
Chris@0 113 DSSIPluginFactory::instantiatePlugin(QString identifier,
Chris@0 114 int instrument,
Chris@0 115 int position,
Chris@1040 116 sv_samplerate_t sampleRate,
Chris@1040 117 int blockSize,
Chris@1040 118 int channels)
Chris@0 119 {
Chris@408 120 Profiler profiler("DSSIPluginFactory::instantiatePlugin");
Chris@408 121
Chris@0 122 const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier);
Chris@0 123
Chris@0 124 if (descriptor) {
Chris@0 125
Chris@0 126 DSSIPluginInstance *instance =
Chris@0 127 new DSSIPluginInstance
Chris@0 128 (this, instrument, identifier, position, sampleRate, blockSize, channels,
Chris@0 129 descriptor);
Chris@0 130
Chris@0 131 m_instances.insert(instance);
Chris@0 132
Chris@0 133 return instance;
Chris@0 134 }
Chris@0 135
Chris@0 136 return 0;
Chris@0 137 }
Chris@0 138
Chris@0 139 const DSSI_Descriptor *
Chris@0 140 DSSIPluginFactory::getDSSIDescriptor(QString identifier)
Chris@0 141 {
Chris@0 142 QString type, soname, label;
Chris@0 143 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@0 144
Chris@0 145 if (soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
Chris@0 146 if (label == "sample_player") {
Chris@0 147 const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0);
Chris@0 148 if (descriptor) {
Chris@0 149 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@0 150 }
Chris@0 151 return descriptor;
Chris@0 152 } else {
Chris@0 153 return 0;
Chris@0 154 }
Chris@0 155 }
Chris@0 156
Chris@0 157 bool firstInLibrary = false;
Chris@0 158
Chris@0 159 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@0 160 loadLibrary(soname);
Chris@0 161 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@843 162 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname << endl;
Chris@0 163 return 0;
Chris@0 164 }
Chris@0 165 firstInLibrary = true;
Chris@0 166 }
Chris@0 167
Chris@0 168 void *libraryHandle = m_libraryHandles[soname];
Chris@0 169
Chris@0 170 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@0 171 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 172
Chris@0 173 if (!fn) {
Chris@843 174 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname << endl;
Chris@0 175 return 0;
Chris@0 176 }
Chris@0 177
Chris@0 178 const DSSI_Descriptor *descriptor = 0;
Chris@0 179
Chris@0 180 int index = 0;
Chris@0 181 while ((descriptor = fn(index))) {
Chris@0 182 if (descriptor->LADSPA_Plugin->Label == label) {
Chris@0 183 if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) {
Chris@0 184 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@0 185 }
Chris@0 186 return descriptor;
Chris@0 187 }
Chris@0 188 ++index;
Chris@0 189 }
Chris@0 190
Chris@843 191 cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label << " in library " << soname << endl;
Chris@0 192
Chris@0 193 return 0;
Chris@0 194 }
Chris@0 195
Chris@0 196 const LADSPA_Descriptor *
Chris@0 197 DSSIPluginFactory::getLADSPADescriptor(QString identifier)
Chris@0 198 {
Chris@0 199 const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier);
Chris@0 200 if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin;
Chris@0 201 else return 0;
Chris@0 202 }
Chris@0 203
Chris@0 204
Chris@0 205 std::vector<QString>
Chris@0 206 DSSIPluginFactory::getPluginPath()
Chris@0 207 {
Chris@0 208 std::vector<QString> pathList;
Chris@0 209 std::string path;
Chris@0 210
Chris@0 211 char *cpath = getenv("DSSI_PATH");
Chris@0 212 if (cpath) path = cpath;
Chris@0 213
Chris@0 214 if (path == "") {
Chris@186 215
Chris@186 216 path = DEFAULT_DSSI_PATH;
Chris@186 217
Chris@0 218 char *home = getenv("HOME");
Chris@66 219 if (home) {
Chris@186 220 std::string::size_type f;
Chris@186 221 while ((f = path.find("$HOME")) != std::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@220 228 char *pfiles = getenv("ProgramFiles");
Chris@220 229 if (!pfiles) pfiles = "C:\\Program Files";
Chris@220 230 {
Chris@186 231 std::string::size_type f;
Chris@186 232 while ((f = path.find("%ProgramFiles%")) != std::string::npos &&
Chris@186 233 f < path.length()) {
Chris@186 234 path.replace(f, 14, pfiles);
Chris@186 235 }
Chris@220 236 }
Chris@186 237 #endif
Chris@0 238 }
Chris@0 239
Chris@0 240 std::string::size_type index = 0, newindex = 0;
Chris@0 241
Chris@223 242 while ((newindex = path.find(PATH_SEPARATOR, index)) < path.size()) {
Chris@0 243 pathList.push_back(path.substr(index, newindex - index).c_str());
Chris@0 244 index = newindex + 1;
Chris@0 245 }
Chris@0 246
Chris@0 247 pathList.push_back(path.substr(index).c_str());
Chris@0 248
Chris@0 249 return pathList;
Chris@0 250 }
Chris@0 251
Chris@0 252
Chris@0 253 std::vector<QString>
Chris@0 254 DSSIPluginFactory::getLRDFPath(QString &baseUri)
Chris@0 255 {
Chris@150 256 std::vector<QString> lrdfPaths;
Chris@150 257
Chris@150 258 #ifdef HAVE_LRDF
Chris@0 259 std::vector<QString> pathList = getPluginPath();
Chris@0 260
Chris@0 261 lrdfPaths.push_back("/usr/local/share/dssi/rdf");
Chris@0 262 lrdfPaths.push_back("/usr/share/dssi/rdf");
Chris@0 263
Chris@0 264 lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
Chris@0 265 lrdfPaths.push_back("/usr/share/ladspa/rdf");
Chris@0 266
Chris@0 267 for (std::vector<QString>::iterator i = pathList.begin();
Chris@0 268 i != pathList.end(); ++i) {
Chris@0 269 lrdfPaths.push_back(*i + "/rdf");
Chris@0 270 }
Chris@0 271
Chris@0 272 #ifdef DSSI_BASE
Chris@0 273 baseUri = DSSI_BASE;
Chris@0 274 #else
Chris@0 275 baseUri = "http://dssi.sourceforge.net/ontology#";
Chris@0 276 #endif
Chris@953 277 #else
Chris@953 278 // avoid unused parameter
Chris@953 279 baseUri = "";
Chris@150 280 #endif
Chris@0 281
Chris@0 282 return lrdfPaths;
Chris@0 283 }
Chris@0 284
Chris@0 285
Chris@0 286 void
Chris@929 287 DSSIPluginFactory::discoverPluginsFrom(QString soname)
Chris@0 288 {
Chris@408 289 Profiler profiler("DSSIPluginFactory::discoverPlugins");
Chris@408 290
Chris@0 291 // Note that soname is expected to be a full path at this point,
Chris@0 292 // of a file that is known to exist
Chris@0 293
Chris@0 294 void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
Chris@0 295
Chris@0 296 if (!libraryHandle) {
Chris@843 297 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
Chris@843 298 << soname << " - " << DLERROR() << endl;
Chris@0 299 return;
Chris@0 300 }
Chris@0 301
Chris@0 302 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@0 303 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 304
Chris@0 305 if (!fn) {
Chris@843 306 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname << endl;
Chris@0 307 return;
Chris@0 308 }
Chris@0 309
Chris@0 310 const DSSI_Descriptor *descriptor = 0;
Chris@0 311
Chris@0 312 int index = 0;
Chris@0 313 while ((descriptor = fn(index))) {
Chris@0 314
Chris@0 315 const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
Chris@0 316 if (!ladspaDescriptor) {
Chris@843 317 cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname << endl;
Chris@0 318 ++index;
Chris@0 319 continue;
Chris@0 320 }
Chris@0 321
Chris@60 322 RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor;
Chris@60 323 rtd->name = ladspaDescriptor->Name;
Chris@60 324 rtd->label = ladspaDescriptor->Label;
Chris@60 325 rtd->maker = ladspaDescriptor->Maker;
Chris@60 326 rtd->copyright = ladspaDescriptor->Copyright;
Chris@60 327 rtd->category = "";
Chris@60 328 rtd->isSynth = (descriptor->run_synth ||
Chris@60 329 descriptor->run_multiple_synths);
Chris@60 330 rtd->parameterCount = 0;
Chris@60 331 rtd->audioInputPortCount = 0;
Chris@166 332 rtd->audioOutputPortCount = 0;
Chris@60 333 rtd->controlOutputPortCount = 0;
Chris@60 334
Chris@165 335 QString identifier = PluginIdentifier::createIdentifier
Chris@165 336 ("dssi", soname, ladspaDescriptor->Label);
Chris@165 337
Chris@35 338 #ifdef HAVE_LRDF
Chris@0 339 char *def_uri = 0;
Chris@0 340 lrdf_defaults *defs = 0;
Chris@0 341
Chris@165 342 QString category = m_taxonomy[identifier];
Chris@165 343
Chris@166 344 if (category == "" && m_lrdfTaxonomy[ladspaDescriptor->UniqueID] != "") {
Chris@166 345 m_taxonomy[identifier] = m_lrdfTaxonomy[ladspaDescriptor->UniqueID];
Chris@165 346 category = m_taxonomy[identifier];
Chris@165 347 }
Chris@0 348
Chris@973 349 if (category == "") {
Chris@973 350 std::string name = rtd->name;
Chris@0 351 if (name.length() > 4 &&
Chris@0 352 name.substr(name.length() - 4) == " VST") {
Chris@0 353 if (descriptor->run_synth || descriptor->run_multiple_synths) {
Chris@0 354 category = "VST instruments";
Chris@0 355 } else {
Chris@0 356 category = "VST effects";
Chris@0 357 }
Chris@165 358 m_taxonomy[identifier] = category;
Chris@0 359 }
Chris@0 360 }
Chris@60 361
Chris@60 362 rtd->category = category.toStdString();
Chris@0 363
Chris@843 364 // cerr << "Plugin id is " << ladspaDescriptor->UniqueID
Chris@844 365 // << ", identifier is \"" << identifier
Chris@844 366 // << "\", category is \"" << category
Chris@167 367 // << "\", name is " << ladspaDescriptor->Name
Chris@167 368 // << ", label is " << ladspaDescriptor->Label
Chris@843 369 // << endl;
Chris@0 370
Chris@0 371 def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
Chris@0 372 if (def_uri) {
Chris@0 373 defs = lrdf_get_setting_values(def_uri);
Chris@0 374 }
Chris@0 375
Chris@259 376 unsigned int controlPortNumber = 1;
Chris@0 377
Chris@1038 378 for (int i = 0; i < (int)ladspaDescriptor->PortCount; i++) {
Chris@0 379
Chris@0 380 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@0 381
Chris@0 382 if (def_uri && defs) {
Chris@0 383
Chris@1038 384 for (int j = 0; j < (int)defs->count; j++) {
Chris@0 385 if (defs->items[j].pid == controlPortNumber) {
Chris@843 386 // 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@0 387 m_portDefaults[ladspaDescriptor->UniqueID][i] =
Chris@0 388 defs->items[j].value;
Chris@0 389 }
Chris@0 390 }
Chris@0 391 }
Chris@0 392
Chris@0 393 ++controlPortNumber;
Chris@0 394 }
Chris@0 395 }
Chris@35 396 #endif // HAVE_LRDF
Chris@0 397
Chris@60 398 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@60 399 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 400 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 401 ++rtd->parameterCount;
Chris@60 402 } else {
Chris@60 403 if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
Chris@60 404 strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
Chris@60 405 ++rtd->controlOutputPortCount;
Chris@60 406 rtd->controlOutputPortNames.push_back
Chris@60 407 (ladspaDescriptor->PortNames[i]);
Chris@60 408 }
Chris@60 409 }
Chris@60 410 } else {
Chris@60 411 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 412 ++rtd->audioInputPortCount;
Chris@166 413 } else if (LADSPA_IS_PORT_OUTPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@166 414 ++rtd->audioOutputPortCount;
Chris@60 415 }
Chris@60 416 }
Chris@60 417 }
Chris@60 418
Chris@0 419 m_identifiers.push_back(identifier);
Chris@0 420
Chris@60 421 m_rtDescriptors[identifier] = rtd;
Chris@60 422
Chris@0 423 ++index;
Chris@0 424 }
Chris@0 425
Chris@0 426 if (DLCLOSE(libraryHandle) != 0) {
Chris@843 427 cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << endl;
Chris@0 428 return;
Chris@0 429 }
Chris@0 430 }
Chris@0 431
Chris@0 432
Chris@0 433