annotate plugin/DSSIPluginFactory.cpp @ 167:665342c6ec57

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +0000
parents 702fc936e6a6
children 06ad01f3e553
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@0 29 //!!!
Chris@150 30 #include "plugin/plugins/SamplePlayer.h"
Chris@0 31
Chris@150 32 #include "system/System.h"
Chris@0 33
Chris@35 34 #ifdef HAVE_LRDF
Chris@0 35 #include "lrdf.h"
Chris@35 36 #endif // HAVE_LRDF
Chris@0 37
Chris@0 38
Chris@0 39 DSSIPluginFactory::DSSIPluginFactory() :
Chris@0 40 LADSPAPluginFactory()
Chris@0 41 {
Chris@0 42 m_hostDescriptor.DSSI_API_Version = 2;
Chris@0 43 m_hostDescriptor.request_transport_information = NULL;
Chris@0 44 m_hostDescriptor.request_midi_send = DSSIPluginInstance::requestMidiSend;
Chris@0 45 m_hostDescriptor.request_non_rt_thread = DSSIPluginInstance::requestNonRTThread;
Chris@0 46 m_hostDescriptor.midi_send = DSSIPluginInstance::midiSend;
Chris@0 47 }
Chris@0 48
Chris@0 49 DSSIPluginFactory::~DSSIPluginFactory()
Chris@0 50 {
Chris@0 51 // nothing else to do here either
Chris@0 52 }
Chris@0 53
Chris@0 54 void
Chris@0 55 DSSIPluginFactory::enumeratePlugins(std::vector<QString> &list)
Chris@0 56 {
Chris@0 57 for (std::vector<QString>::iterator i = m_identifiers.begin();
Chris@0 58 i != m_identifiers.end(); ++i) {
Chris@0 59
Chris@0 60 const DSSI_Descriptor *ddesc = getDSSIDescriptor(*i);
Chris@0 61 if (!ddesc) continue;
Chris@0 62
Chris@0 63 const LADSPA_Descriptor *descriptor = ddesc->LADSPA_Plugin;
Chris@0 64 if (!descriptor) continue;
Chris@0 65
Chris@0 66 // std::cerr << "DSSIPluginFactory::enumeratePlugins: Name " << (descriptor->Name ? descriptor->Name : "NONE" ) << std::endl;
Chris@0 67
Chris@0 68 list.push_back(*i);
Chris@0 69 list.push_back(descriptor->Name);
Chris@0 70 list.push_back(QString("%1").arg(descriptor->UniqueID));
Chris@0 71 list.push_back(descriptor->Label);
Chris@0 72 list.push_back(descriptor->Maker);
Chris@0 73 list.push_back(descriptor->Copyright);
Chris@0 74 list.push_back((ddesc->run_synth || ddesc->run_multiple_synths) ? "true" : "false");
Chris@0 75 list.push_back(ddesc->run_multiple_synths ? "true" : "false");
Chris@165 76 list.push_back(m_taxonomy[*i]);
Chris@0 77 list.push_back(QString("%1").arg(descriptor->PortCount));
Chris@0 78
Chris@0 79 for (unsigned long p = 0; p < descriptor->PortCount; ++p) {
Chris@0 80
Chris@0 81 int type = 0;
Chris@0 82 if (LADSPA_IS_PORT_CONTROL(descriptor->PortDescriptors[p])) {
Chris@0 83 type |= PortType::Control;
Chris@0 84 } else {
Chris@0 85 type |= PortType::Audio;
Chris@0 86 }
Chris@0 87 if (LADSPA_IS_PORT_INPUT(descriptor->PortDescriptors[p])) {
Chris@0 88 type |= PortType::Input;
Chris@0 89 } else {
Chris@0 90 type |= PortType::Output;
Chris@0 91 }
Chris@0 92
Chris@0 93 list.push_back(QString("%1").arg(p));
Chris@0 94 list.push_back(descriptor->PortNames[p]);
Chris@0 95 list.push_back(QString("%1").arg(type));
Chris@0 96 list.push_back(QString("%1").arg(getPortDisplayHint(descriptor, p)));
Chris@0 97 list.push_back(QString("%1").arg(getPortMinimum(descriptor, p)));
Chris@0 98 list.push_back(QString("%1").arg(getPortMaximum(descriptor, p)));
Chris@0 99 list.push_back(QString("%1").arg(getPortDefault(descriptor, p)));
Chris@0 100 }
Chris@0 101 }
Chris@0 102
Chris@0 103 unloadUnusedLibraries();
Chris@0 104 }
Chris@0 105
Chris@0 106 RealTimePluginInstance *
Chris@0 107 DSSIPluginFactory::instantiatePlugin(QString identifier,
Chris@0 108 int instrument,
Chris@0 109 int position,
Chris@0 110 unsigned int sampleRate,
Chris@0 111 unsigned int blockSize,
Chris@0 112 unsigned int channels)
Chris@0 113 {
Chris@0 114 const DSSI_Descriptor *descriptor = getDSSIDescriptor(identifier);
Chris@0 115
Chris@0 116 if (descriptor) {
Chris@0 117
Chris@0 118 DSSIPluginInstance *instance =
Chris@0 119 new DSSIPluginInstance
Chris@0 120 (this, instrument, identifier, position, sampleRate, blockSize, channels,
Chris@0 121 descriptor);
Chris@0 122
Chris@0 123 m_instances.insert(instance);
Chris@0 124
Chris@0 125 return instance;
Chris@0 126 }
Chris@0 127
Chris@0 128 return 0;
Chris@0 129 }
Chris@0 130
Chris@0 131 const DSSI_Descriptor *
Chris@0 132 DSSIPluginFactory::getDSSIDescriptor(QString identifier)
Chris@0 133 {
Chris@0 134 QString type, soname, label;
Chris@0 135 PluginIdentifier::parseIdentifier(identifier, type, soname, label);
Chris@0 136
Chris@0 137 if (soname == PluginIdentifier::BUILTIN_PLUGIN_SONAME) {
Chris@0 138 if (label == "sample_player") {
Chris@0 139 const DSSI_Descriptor *descriptor = SamplePlayer::getDescriptor(0);
Chris@0 140 if (descriptor) {
Chris@0 141 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@0 142 }
Chris@0 143 return descriptor;
Chris@0 144 } else {
Chris@0 145 return 0;
Chris@0 146 }
Chris@0 147 }
Chris@0 148
Chris@0 149 bool firstInLibrary = false;
Chris@0 150
Chris@0 151 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@0 152 loadLibrary(soname);
Chris@0 153 if (m_libraryHandles.find(soname) == m_libraryHandles.end()) {
Chris@0 154 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: loadLibrary failed for " << soname.toStdString() << std::endl;
Chris@0 155 return 0;
Chris@0 156 }
Chris@0 157 firstInLibrary = true;
Chris@0 158 }
Chris@0 159
Chris@0 160 void *libraryHandle = m_libraryHandles[soname];
Chris@0 161
Chris@0 162 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@0 163 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 164
Chris@0 165 if (!fn) {
Chris@0 166 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No descriptor function in library " << soname.toStdString() << std::endl;
Chris@0 167 return 0;
Chris@0 168 }
Chris@0 169
Chris@0 170 const DSSI_Descriptor *descriptor = 0;
Chris@0 171
Chris@0 172 int index = 0;
Chris@0 173 while ((descriptor = fn(index))) {
Chris@0 174 if (descriptor->LADSPA_Plugin->Label == label) {
Chris@0 175 if (firstInLibrary && (descriptor->DSSI_API_Version >= 2)) {
Chris@0 176 descriptor->receive_host_descriptor(&m_hostDescriptor);
Chris@0 177 }
Chris@0 178 return descriptor;
Chris@0 179 }
Chris@0 180 ++index;
Chris@0 181 }
Chris@0 182
Chris@0 183 std::cerr << "WARNING: DSSIPluginFactory::getDSSIDescriptor: No such plugin as " << label.toStdString() << " in library " << soname.toStdString() << std::endl;
Chris@0 184
Chris@0 185 return 0;
Chris@0 186 }
Chris@0 187
Chris@0 188 const LADSPA_Descriptor *
Chris@0 189 DSSIPluginFactory::getLADSPADescriptor(QString identifier)
Chris@0 190 {
Chris@0 191 const DSSI_Descriptor *dssiDescriptor = getDSSIDescriptor(identifier);
Chris@0 192 if (dssiDescriptor) return dssiDescriptor->LADSPA_Plugin;
Chris@0 193 else return 0;
Chris@0 194 }
Chris@0 195
Chris@0 196
Chris@0 197 std::vector<QString>
Chris@0 198 DSSIPluginFactory::getPluginPath()
Chris@0 199 {
Chris@0 200 std::vector<QString> pathList;
Chris@0 201 std::string path;
Chris@0 202
Chris@0 203 char *cpath = getenv("DSSI_PATH");
Chris@0 204 if (cpath) path = cpath;
Chris@0 205
Chris@0 206 if (path == "") {
Chris@0 207 path = "/usr/local/lib/dssi:/usr/lib/dssi";
Chris@0 208 char *home = getenv("HOME");
Chris@66 209 if (home) {
Chris@66 210 path = std::string(home) + "/dssi:" +
Chris@66 211 std::string(home) + "/.dssi:" + path;
Chris@66 212 }
Chris@0 213 }
Chris@0 214
Chris@0 215 std::string::size_type index = 0, newindex = 0;
Chris@0 216
Chris@0 217 while ((newindex = path.find(':', index)) < path.size()) {
Chris@0 218 pathList.push_back(path.substr(index, newindex - index).c_str());
Chris@0 219 index = newindex + 1;
Chris@0 220 }
Chris@0 221
Chris@0 222 pathList.push_back(path.substr(index).c_str());
Chris@0 223
Chris@0 224 return pathList;
Chris@0 225 }
Chris@0 226
Chris@0 227
Chris@0 228 std::vector<QString>
Chris@0 229 DSSIPluginFactory::getLRDFPath(QString &baseUri)
Chris@0 230 {
Chris@150 231 std::vector<QString> lrdfPaths;
Chris@150 232
Chris@150 233 #ifdef HAVE_LRDF
Chris@0 234 std::vector<QString> pathList = getPluginPath();
Chris@0 235
Chris@0 236 lrdfPaths.push_back("/usr/local/share/dssi/rdf");
Chris@0 237 lrdfPaths.push_back("/usr/share/dssi/rdf");
Chris@0 238
Chris@0 239 lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
Chris@0 240 lrdfPaths.push_back("/usr/share/ladspa/rdf");
Chris@0 241
Chris@0 242 for (std::vector<QString>::iterator i = pathList.begin();
Chris@0 243 i != pathList.end(); ++i) {
Chris@0 244 lrdfPaths.push_back(*i + "/rdf");
Chris@0 245 }
Chris@0 246
Chris@0 247 #ifdef DSSI_BASE
Chris@0 248 baseUri = DSSI_BASE;
Chris@0 249 #else
Chris@0 250 baseUri = "http://dssi.sourceforge.net/ontology#";
Chris@0 251 #endif
Chris@150 252 #endif
Chris@0 253
Chris@0 254 return lrdfPaths;
Chris@0 255 }
Chris@0 256
Chris@0 257
Chris@0 258 void
Chris@0 259 DSSIPluginFactory::discoverPlugins(QString soname)
Chris@0 260 {
Chris@0 261 // Note that soname is expected to be a full path at this point,
Chris@0 262 // of a file that is known to exist
Chris@0 263
Chris@0 264 void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
Chris@0 265
Chris@0 266 if (!libraryHandle) {
Chris@0 267 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
Chris@0 268 << soname.toStdString() << " - " << DLERROR() << std::endl;
Chris@0 269 return;
Chris@0 270 }
Chris@0 271
Chris@0 272 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@0 273 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 274
Chris@0 275 if (!fn) {
Chris@0 276 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname.toStdString() << std::endl;
Chris@0 277 return;
Chris@0 278 }
Chris@0 279
Chris@0 280 const DSSI_Descriptor *descriptor = 0;
Chris@0 281
Chris@0 282 int index = 0;
Chris@0 283 while ((descriptor = fn(index))) {
Chris@0 284
Chris@0 285 const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
Chris@0 286 if (!ladspaDescriptor) {
Chris@0 287 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname.toStdString() << std::endl;
Chris@0 288 ++index;
Chris@0 289 continue;
Chris@0 290 }
Chris@0 291
Chris@60 292 RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor;
Chris@60 293 rtd->name = ladspaDescriptor->Name;
Chris@60 294 rtd->label = ladspaDescriptor->Label;
Chris@60 295 rtd->maker = ladspaDescriptor->Maker;
Chris@60 296 rtd->copyright = ladspaDescriptor->Copyright;
Chris@60 297 rtd->category = "";
Chris@60 298 rtd->isSynth = (descriptor->run_synth ||
Chris@60 299 descriptor->run_multiple_synths);
Chris@60 300 rtd->parameterCount = 0;
Chris@60 301 rtd->audioInputPortCount = 0;
Chris@166 302 rtd->audioOutputPortCount = 0;
Chris@60 303 rtd->controlOutputPortCount = 0;
Chris@60 304
Chris@165 305 QString identifier = PluginIdentifier::createIdentifier
Chris@165 306 ("dssi", soname, ladspaDescriptor->Label);
Chris@165 307
Chris@35 308 #ifdef HAVE_LRDF
Chris@0 309 char *def_uri = 0;
Chris@0 310 lrdf_defaults *defs = 0;
Chris@0 311
Chris@165 312 QString category = m_taxonomy[identifier];
Chris@165 313
Chris@166 314 if (category == "" && m_lrdfTaxonomy[ladspaDescriptor->UniqueID] != "") {
Chris@166 315 m_taxonomy[identifier] = m_lrdfTaxonomy[ladspaDescriptor->UniqueID];
Chris@165 316 category = m_taxonomy[identifier];
Chris@165 317 }
Chris@0 318
Chris@0 319 if (category == "" && ladspaDescriptor->Name != 0) {
Chris@0 320 std::string name = ladspaDescriptor->Name;
Chris@0 321 if (name.length() > 4 &&
Chris@0 322 name.substr(name.length() - 4) == " VST") {
Chris@0 323 if (descriptor->run_synth || descriptor->run_multiple_synths) {
Chris@0 324 category = "VST instruments";
Chris@0 325 } else {
Chris@0 326 category = "VST effects";
Chris@0 327 }
Chris@165 328 m_taxonomy[identifier] = category;
Chris@0 329 }
Chris@0 330 }
Chris@60 331
Chris@60 332 rtd->category = category.toStdString();
Chris@0 333
Chris@167 334 // std::cerr << "Plugin id is " << ladspaDescriptor->UniqueID
Chris@167 335 // << ", identifier is \"" << identifier.toStdString()
Chris@167 336 // << "\", category is \"" << category.toStdString()
Chris@167 337 // << "\", name is " << ladspaDescriptor->Name
Chris@167 338 // << ", label is " << ladspaDescriptor->Label
Chris@167 339 // << std::endl;
Chris@0 340
Chris@0 341 def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
Chris@0 342 if (def_uri) {
Chris@0 343 defs = lrdf_get_setting_values(def_uri);
Chris@0 344 }
Chris@0 345
Chris@0 346 int controlPortNumber = 1;
Chris@0 347
Chris@0 348 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@0 349
Chris@0 350 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@0 351
Chris@0 352 if (def_uri && defs) {
Chris@0 353
Chris@0 354 for (int j = 0; j < defs->count; j++) {
Chris@0 355 if (defs->items[j].pid == controlPortNumber) {
Chris@0 356 // std::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] << std::endl;
Chris@0 357 m_portDefaults[ladspaDescriptor->UniqueID][i] =
Chris@0 358 defs->items[j].value;
Chris@0 359 }
Chris@0 360 }
Chris@0 361 }
Chris@0 362
Chris@0 363 ++controlPortNumber;
Chris@0 364 }
Chris@0 365 }
Chris@35 366 #endif // HAVE_LRDF
Chris@0 367
Chris@60 368 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@60 369 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 370 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 371 ++rtd->parameterCount;
Chris@60 372 } else {
Chris@60 373 if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
Chris@60 374 strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
Chris@60 375 ++rtd->controlOutputPortCount;
Chris@60 376 rtd->controlOutputPortNames.push_back
Chris@60 377 (ladspaDescriptor->PortNames[i]);
Chris@60 378 }
Chris@60 379 }
Chris@60 380 } else {
Chris@60 381 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 382 ++rtd->audioInputPortCount;
Chris@166 383 } else if (LADSPA_IS_PORT_OUTPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@166 384 ++rtd->audioOutputPortCount;
Chris@60 385 }
Chris@60 386 }
Chris@60 387 }
Chris@60 388
Chris@0 389 m_identifiers.push_back(identifier);
Chris@0 390
Chris@60 391 m_rtDescriptors[identifier] = rtd;
Chris@60 392
Chris@0 393 ++index;
Chris@0 394 }
Chris@0 395
Chris@0 396 if (DLCLOSE(libraryHandle) != 0) {
Chris@0 397 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << std::endl;
Chris@0 398 return;
Chris@0 399 }
Chris@0 400 }
Chris@0 401
Chris@0 402
Chris@0 403