annotate plugin/DSSIPluginFactory.cpp @ 117:c30728d5625c sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents 7afcfe666910
children 4b2ea82fd0ed
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@0 30 #include "plugins/SamplePlayer.h"
Chris@0 31
Chris@0 32 #include "base/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@0 76 list.push_back(m_taxonomy[descriptor->UniqueID]);
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@35 228 #ifdef HAVE_LRDF
Chris@0 229 std::vector<QString>
Chris@0 230 DSSIPluginFactory::getLRDFPath(QString &baseUri)
Chris@0 231 {
Chris@0 232 std::vector<QString> pathList = getPluginPath();
Chris@0 233 std::vector<QString> lrdfPaths;
Chris@0 234
Chris@0 235 lrdfPaths.push_back("/usr/local/share/dssi/rdf");
Chris@0 236 lrdfPaths.push_back("/usr/share/dssi/rdf");
Chris@0 237
Chris@0 238 lrdfPaths.push_back("/usr/local/share/ladspa/rdf");
Chris@0 239 lrdfPaths.push_back("/usr/share/ladspa/rdf");
Chris@0 240
Chris@0 241 for (std::vector<QString>::iterator i = pathList.begin();
Chris@0 242 i != pathList.end(); ++i) {
Chris@0 243 lrdfPaths.push_back(*i + "/rdf");
Chris@0 244 }
Chris@0 245
Chris@0 246 #ifdef DSSI_BASE
Chris@0 247 baseUri = DSSI_BASE;
Chris@0 248 #else
Chris@0 249 baseUri = "http://dssi.sourceforge.net/ontology#";
Chris@0 250 #endif
Chris@0 251
Chris@0 252 return lrdfPaths;
Chris@0 253 }
Chris@0 254 #endif
Chris@0 255
Chris@0 256
Chris@0 257 void
Chris@0 258 DSSIPluginFactory::discoverPlugins(QString soname)
Chris@0 259 {
Chris@0 260 // Note that soname is expected to be a full path at this point,
Chris@0 261 // of a file that is known to exist
Chris@0 262
Chris@0 263 void *libraryHandle = DLOPEN(soname, RTLD_LAZY);
Chris@0 264
Chris@0 265 if (!libraryHandle) {
Chris@0 266 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: couldn't load plugin library "
Chris@0 267 << soname.toStdString() << " - " << DLERROR() << std::endl;
Chris@0 268 return;
Chris@0 269 }
Chris@0 270
Chris@0 271 DSSI_Descriptor_Function fn = (DSSI_Descriptor_Function)
Chris@0 272 DLSYM(libraryHandle, "dssi_descriptor");
Chris@0 273
Chris@0 274 if (!fn) {
Chris@0 275 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No descriptor function in " << soname.toStdString() << std::endl;
Chris@0 276 return;
Chris@0 277 }
Chris@0 278
Chris@0 279 const DSSI_Descriptor *descriptor = 0;
Chris@0 280
Chris@0 281 int index = 0;
Chris@0 282 while ((descriptor = fn(index))) {
Chris@0 283
Chris@0 284 const LADSPA_Descriptor *ladspaDescriptor = descriptor->LADSPA_Plugin;
Chris@0 285 if (!ladspaDescriptor) {
Chris@0 286 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins: No LADSPA descriptor for plugin " << index << " in " << soname.toStdString() << std::endl;
Chris@0 287 ++index;
Chris@0 288 continue;
Chris@0 289 }
Chris@0 290
Chris@60 291 RealTimePluginDescriptor *rtd = new RealTimePluginDescriptor;
Chris@60 292 rtd->name = ladspaDescriptor->Name;
Chris@60 293 rtd->label = ladspaDescriptor->Label;
Chris@60 294 rtd->maker = ladspaDescriptor->Maker;
Chris@60 295 rtd->copyright = ladspaDescriptor->Copyright;
Chris@60 296 rtd->category = "";
Chris@60 297 rtd->isSynth = (descriptor->run_synth ||
Chris@60 298 descriptor->run_multiple_synths);
Chris@60 299 rtd->parameterCount = 0;
Chris@60 300 rtd->audioInputPortCount = 0;
Chris@60 301 rtd->controlOutputPortCount = 0;
Chris@60 302
Chris@35 303 #ifdef HAVE_LRDF
Chris@0 304 char *def_uri = 0;
Chris@0 305 lrdf_defaults *defs = 0;
Chris@0 306
Chris@0 307 QString category = m_taxonomy[ladspaDescriptor->UniqueID];
Chris@0 308
Chris@0 309 if (category == "" && ladspaDescriptor->Name != 0) {
Chris@0 310 std::string name = ladspaDescriptor->Name;
Chris@0 311 if (name.length() > 4 &&
Chris@0 312 name.substr(name.length() - 4) == " VST") {
Chris@0 313 if (descriptor->run_synth || descriptor->run_multiple_synths) {
Chris@0 314 category = "VST instruments";
Chris@0 315 } else {
Chris@0 316 category = "VST effects";
Chris@0 317 }
Chris@0 318 m_taxonomy[ladspaDescriptor->UniqueID] = category;
Chris@0 319 }
Chris@0 320 }
Chris@60 321
Chris@60 322 rtd->category = category.toStdString();
Chris@0 323
Chris@0 324 // std::cerr << "Plugin id is " << ladspaDescriptor->UniqueID
Chris@0 325 // << ", category is \"" << (category ? category : QString("(none)"))
Chris@0 326 // << "\", name is " << ladspaDescriptor->Name
Chris@0 327 // << ", label is " << ladspaDescriptor->Label
Chris@0 328 // << std::endl;
Chris@0 329
Chris@0 330 def_uri = lrdf_get_default_uri(ladspaDescriptor->UniqueID);
Chris@0 331 if (def_uri) {
Chris@0 332 defs = lrdf_get_setting_values(def_uri);
Chris@0 333 }
Chris@0 334
Chris@0 335 int controlPortNumber = 1;
Chris@0 336
Chris@0 337 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@0 338
Chris@0 339 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@0 340
Chris@0 341 if (def_uri && defs) {
Chris@0 342
Chris@0 343 for (int j = 0; j < defs->count; j++) {
Chris@0 344 if (defs->items[j].pid == controlPortNumber) {
Chris@0 345 // 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 346 m_portDefaults[ladspaDescriptor->UniqueID][i] =
Chris@0 347 defs->items[j].value;
Chris@0 348 }
Chris@0 349 }
Chris@0 350 }
Chris@0 351
Chris@0 352 ++controlPortNumber;
Chris@0 353 }
Chris@0 354 }
Chris@35 355 #endif // HAVE_LRDF
Chris@0 356
Chris@60 357 for (unsigned long i = 0; i < ladspaDescriptor->PortCount; i++) {
Chris@60 358 if (LADSPA_IS_PORT_CONTROL(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 359 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 360 ++rtd->parameterCount;
Chris@60 361 } else {
Chris@60 362 if (strcmp(ladspaDescriptor->PortNames[i], "latency") &&
Chris@60 363 strcmp(ladspaDescriptor->PortNames[i], "_latency")) {
Chris@60 364 ++rtd->controlOutputPortCount;
Chris@60 365 rtd->controlOutputPortNames.push_back
Chris@60 366 (ladspaDescriptor->PortNames[i]);
Chris@60 367 }
Chris@60 368 }
Chris@60 369 } else {
Chris@60 370 if (LADSPA_IS_PORT_INPUT(ladspaDescriptor->PortDescriptors[i])) {
Chris@60 371 ++rtd->audioInputPortCount;
Chris@60 372 }
Chris@60 373 }
Chris@60 374 }
Chris@60 375
Chris@0 376 QString identifier = PluginIdentifier::createIdentifier
Chris@0 377 ("dssi", soname, ladspaDescriptor->Label);
Chris@0 378 m_identifiers.push_back(identifier);
Chris@0 379
Chris@60 380 m_rtDescriptors[identifier] = rtd;
Chris@60 381
Chris@0 382 ++index;
Chris@0 383 }
Chris@0 384
Chris@0 385 if (DLCLOSE(libraryHandle) != 0) {
Chris@0 386 std::cerr << "WARNING: DSSIPluginFactory::discoverPlugins - can't unload " << libraryHandle << std::endl;
Chris@0 387 return;
Chris@0 388 }
Chris@0 389 }
Chris@0 390
Chris@0 391
Chris@0 392