Collection of tools useful for audio production
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1288 lines
40KB

  1. /*
  2. * Carla Plugin discovery code
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the COPYING file
  16. */
  17. #include <iostream>
  18. #include <QtCore/QDir>
  19. #include <QtCore/QFileInfo>
  20. #include <QtCore/QUrl>
  21. #include "carla_backend.hpp"
  22. #include "carla_lib_utils.hpp"
  23. #ifdef WANT_LADSPA
  24. # include "carla_ladspa_utils.hpp"
  25. #endif
  26. #ifdef WANT_DSSI
  27. # include "carla_ladspa_utils.hpp"
  28. # include "dssi/dssi.h"
  29. #endif
  30. #ifdef WANT_LV2
  31. # include "carla_lv2_utils.hpp"
  32. #endif
  33. #ifdef WANT_VST
  34. # include "carla_vst_utils.hpp"
  35. #endif
  36. #ifdef WANT_FLUIDSYNTH
  37. # include <fluidsynth.h>
  38. #endif
  39. #ifdef WANT_LINUXSAMPLER
  40. # include "linuxsampler/EngineFactory.h"
  41. #endif
  42. #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
  43. // Fake values to test plugins with
  44. const uint32_t bufferSize = 512;
  45. const double sampleRate = 44100.0;
  46. // Since discovery can find multi-architecture binaries, don't print ELF/EXE related errors
  47. void print_lib_error(const char* const filename)
  48. {
  49. const char* const error = lib_error(filename);
  50. if (error && strstr(error, "wrong ELF class") == nullptr && strstr(error, "Bad EXE format") == nullptr)
  51. DISCOVERY_OUT("error", error);
  52. }
  53. using namespace CarlaBackend;
  54. // ------------------------------ VST Stuff ------------------------------
  55. #ifdef WANT_VST
  56. intptr_t vstCurrentUniqueId = 0;
  57. intptr_t vstHostCanDo(const char* const feature)
  58. {
  59. qDebug("vstHostCanDo(\"%s\")", feature);
  60. if (strcmp(feature, "supplyIdle") == 0)
  61. return 1;
  62. if (strcmp(feature, "sendVstEvents") == 0)
  63. return 1;
  64. if (strcmp(feature, "sendVstMidiEvent") == 0)
  65. return 1;
  66. if (strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  67. return -1;
  68. if (strcmp(feature, "sendVstTimeInfo") == 0)
  69. return 1;
  70. if (strcmp(feature, "receiveVstEvents") == 0)
  71. return 1;
  72. if (strcmp(feature, "receiveVstMidiEvent") == 0)
  73. return 1;
  74. if (strcmp(feature, "receiveVstTimeInfo") == 0)
  75. return -1;
  76. if (strcmp(feature, "reportConnectionChanges") == 0)
  77. return -1;
  78. if (strcmp(feature, "acceptIOChanges") == 0)
  79. return 1;
  80. if (strcmp(feature, "sizeWindow") == 0)
  81. return 1;
  82. if (strcmp(feature, "offline") == 0)
  83. return -1;
  84. if (strcmp(feature, "openFileSelector") == 0)
  85. return -1;
  86. if (strcmp(feature, "closeFileSelector") == 0)
  87. return -1;
  88. if (strcmp(feature, "startStopProcess") == 0)
  89. return 1;
  90. if (strcmp(feature, "supportShell") == 0)
  91. return 1;
  92. if (strcmp(feature, "shellCategory") == 0)
  93. return 1;
  94. // unimplemented
  95. qWarning("vstHostCanDo(\"%s\") - unknown feature", feature);
  96. return 0;
  97. }
  98. intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt)
  99. {
  100. #if DEBUG
  101. qDebug("vstHostCallback(%p, %s, %i, " P_INTPTR ", %p, %f)", effect, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  102. #endif
  103. intptr_t ret = 0;
  104. switch (opcode)
  105. {
  106. case audioMasterAutomate:
  107. if (effect)
  108. effect->setParameter(effect, index, opt);
  109. break;
  110. case audioMasterVersion:
  111. ret = kVstVersion;
  112. break;
  113. case audioMasterCurrentId:
  114. ret = vstCurrentUniqueId;
  115. break;
  116. case audioMasterGetTime:
  117. static VstTimeInfo_R timeInfo;
  118. memset(&timeInfo, 0, sizeof(VstTimeInfo_R));
  119. timeInfo.sampleRate = sampleRate;
  120. // Tempo
  121. timeInfo.tempo = 120.0;
  122. timeInfo.flags |= kVstTempoValid;
  123. // Time Signature
  124. timeInfo.timeSigNumerator = 4;
  125. timeInfo.timeSigDenominator = 4;
  126. timeInfo.flags |= kVstTimeSigValid;
  127. ret = (intptr_t)&timeInfo;
  128. break;
  129. case audioMasterTempoAt:
  130. // Deprecated in VST SDK 2.4
  131. ret = 120 * 10000;
  132. break;
  133. case audioMasterGetNumAutomatableParameters:
  134. ret = MAX_PARAMETERS;
  135. break;
  136. case audioMasterGetSampleRate:
  137. ret = sampleRate;
  138. break;
  139. case audioMasterGetBlockSize:
  140. ret = bufferSize;
  141. break;
  142. case audioMasterGetCurrentProcessLevel:
  143. ret = kVstProcessLevelUser;
  144. break;
  145. case audioMasterGetAutomationState:
  146. ret = kVstAutomationReadWrite;
  147. break;
  148. case audioMasterGetVendorString:
  149. if (ptr)
  150. strcpy((char*)ptr, "Cadence");
  151. break;
  152. case audioMasterGetProductString:
  153. if (ptr)
  154. strcpy((char*)ptr, "Carla-Discovery");
  155. break;
  156. case audioMasterGetVendorVersion:
  157. ret = 0x050; // 0.5.0
  158. break;
  159. case audioMasterCanDo:
  160. if (ptr)
  161. ret = vstHostCanDo((const char*)ptr);
  162. break;
  163. case audioMasterGetLanguage:
  164. ret = kVstLangEnglish;
  165. break;
  166. default:
  167. qDebug("vstHostCallback(%p, %s, %i, " P_INTPTR ", %p, %f)", effect, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  168. break;
  169. }
  170. return ret;
  171. }
  172. #endif
  173. // ------------------------------ Plugin Checks -----------------------------
  174. void do_ladspa_check(void* const libHandle, const bool init)
  175. {
  176. #ifdef WANT_LADSPA
  177. const LADSPA_Descriptor_Function descFn = (LADSPA_Descriptor_Function)lib_symbol(libHandle, "ladspa_descriptor");
  178. if (! descFn)
  179. {
  180. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  181. return;
  182. }
  183. unsigned long i = 0;
  184. const LADSPA_Descriptor* descriptor;
  185. while ((descriptor = descFn(i++)))
  186. {
  187. CARLA_ASSERT(descriptor->run);
  188. int hints = 0;
  189. int audioIns = 0;
  190. int audioOuts = 0;
  191. int audioTotal = 0;
  192. int parametersIns = 0;
  193. int parametersOuts = 0;
  194. int parametersTotal = 0;
  195. for (unsigned long j=0; j < descriptor->PortCount; j++)
  196. {
  197. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  198. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  199. {
  200. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  201. audioIns += 1;
  202. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  203. audioOuts += 1;
  204. audioTotal += 1;
  205. }
  206. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  207. {
  208. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  209. parametersIns += 1;
  210. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(descriptor->PortNames[j], "latency") && strcmp(descriptor->PortNames[j], "_latency") && strcmp(descriptor->PortNames[j], "_sample-rate"))
  211. parametersOuts += 1;
  212. parametersTotal += 1;
  213. }
  214. }
  215. if (init)
  216. {
  217. // -----------------------------------------------------------------------
  218. // start crash-free plugin test
  219. const LADSPA_Handle handle = descriptor->instantiate(descriptor, sampleRate);
  220. if (! handle)
  221. {
  222. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  223. continue;
  224. }
  225. LADSPA_Data bufferAudio[bufferSize][audioTotal];
  226. memset(bufferAudio, 0, sizeof(float)*bufferSize*audioTotal);
  227. LADSPA_Data bufferParams[parametersTotal];
  228. memset(bufferParams, 0, sizeof(float)*parametersTotal);
  229. LADSPA_Data min, max, def;
  230. for (unsigned long j=0, iA=0, iP=0; j < descriptor->PortCount; j++)
  231. {
  232. const LADSPA_PortDescriptor portType = descriptor->PortDescriptors[j];
  233. const LADSPA_PortRangeHint portHints = descriptor->PortRangeHints[j];
  234. if (LADSPA_IS_PORT_AUDIO(portType))
  235. {
  236. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  237. }
  238. else if (LADSPA_IS_PORT_CONTROL(portType))
  239. {
  240. // min value
  241. if (LADSPA_IS_HINT_BOUNDED_BELOW(portHints.HintDescriptor))
  242. min = portHints.LowerBound;
  243. else
  244. min = 0.0f;
  245. // max value
  246. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portHints.HintDescriptor))
  247. max = portHints.UpperBound;
  248. else
  249. max = 1.0f;
  250. if (min > max)
  251. max = min;
  252. else if (max < min)
  253. min = max;
  254. if (max - min == 0.0f)
  255. {
  256. DISCOVERY_OUT("error", "Broken parameter: max - min == 0");
  257. max = min + 0.1f;
  258. }
  259. // default value
  260. def = get_default_ladspa_port_value(portHints.HintDescriptor, min, max);
  261. if (def < min)
  262. def = min;
  263. else if (def > max)
  264. def = max;
  265. if (LADSPA_IS_HINT_SAMPLE_RATE(portHints.HintDescriptor))
  266. {
  267. min *= sampleRate;
  268. max *= sampleRate;
  269. def *= sampleRate;
  270. }
  271. if (LADSPA_IS_PORT_OUTPUT(portType) && (strcmp(descriptor->PortNames[j], "latency") == 0 || strcmp(descriptor->PortNames[j], "_latency") == 0))
  272. {
  273. // latency parameter
  274. min = 0.0f;
  275. max = sampleRate;
  276. def = 0.0f;
  277. }
  278. bufferParams[iP] = def;
  279. descriptor->connect_port(handle, j, &bufferParams[iP++]);
  280. }
  281. }
  282. if (descriptor->activate)
  283. descriptor->activate(handle);
  284. descriptor->run(handle, bufferSize);
  285. if (descriptor->deactivate)
  286. descriptor->deactivate(handle);
  287. if (descriptor->cleanup)
  288. descriptor->cleanup(handle);
  289. // end crash-free plugin test
  290. // -----------------------------------------------------------------------
  291. }
  292. DISCOVERY_OUT("init", "-----------");
  293. DISCOVERY_OUT("name", descriptor->Name);
  294. DISCOVERY_OUT("label", descriptor->Label);
  295. DISCOVERY_OUT("maker", descriptor->Maker);
  296. DISCOVERY_OUT("copyright", descriptor->Copyright);
  297. DISCOVERY_OUT("unique_id", descriptor->UniqueID);
  298. DISCOVERY_OUT("hints", hints);
  299. DISCOVERY_OUT("audio.ins", audioIns);
  300. DISCOVERY_OUT("audio.outs", audioOuts);
  301. DISCOVERY_OUT("audio.total", audioTotal);
  302. DISCOVERY_OUT("parameters.ins", parametersIns);
  303. DISCOVERY_OUT("parameters.outs", parametersOuts);
  304. DISCOVERY_OUT("parameters.total", parametersTotal);
  305. DISCOVERY_OUT("build", BINARY_NATIVE);
  306. DISCOVERY_OUT("end", "------------");
  307. }
  308. #else
  309. DISCOVERY_OUT("error", "LADSPA support not available");
  310. Q_UNUSED(libHandle);
  311. Q_UNUSED(init);
  312. #endif
  313. }
  314. void do_dssi_check(void* const libHandle, const bool init)
  315. {
  316. #ifdef WANT_DSSI
  317. const DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)lib_symbol(libHandle, "dssi_descriptor");
  318. if (! descFn)
  319. {
  320. DISCOVERY_OUT("error", "Not a DSSI plugin");
  321. return;
  322. }
  323. unsigned long i = 0;
  324. const DSSI_Descriptor* descriptor;
  325. while ((descriptor = descFn(i++)))
  326. {
  327. const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
  328. CARLA_ASSERT(ldescriptor);
  329. CARLA_ASSERT(ldescriptor->run || descriptor->run_synth || descriptor->run_multiple_synths);
  330. int hints = 0;
  331. int audioIns = 0;
  332. int audioOuts = 0;
  333. int audioTotal = 0;
  334. int midiIns = 0;
  335. int midiTotal = 0;
  336. int parametersIns = 0;
  337. int parametersOuts = 0;
  338. int parametersTotal = 0;
  339. int programsTotal = 0;
  340. for (unsigned long j=0; j < ldescriptor->PortCount; j++)
  341. {
  342. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  343. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  344. {
  345. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  346. audioIns += 1;
  347. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  348. audioOuts += 1;
  349. audioTotal += 1;
  350. }
  351. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  352. {
  353. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  354. parametersIns += 1;
  355. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(ldescriptor->PortNames[j], "latency") && strcmp(ldescriptor->PortNames[j], "_latency") && strcmp(ldescriptor->PortNames[j], "_sample-rate"))
  356. parametersOuts += 1;
  357. parametersTotal += 1;
  358. }
  359. }
  360. if (descriptor->run_synth || descriptor->run_multiple_synths)
  361. midiIns = midiTotal = 1;
  362. if (midiIns > 0 && audioOuts > 0)
  363. hints |= PLUGIN_IS_SYNTH;
  364. if (init)
  365. {
  366. // -----------------------------------------------------------------------
  367. // start crash-free plugin test
  368. const LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, sampleRate);
  369. if (! handle)
  370. {
  371. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  372. continue;
  373. }
  374. // we can only get program info per-handle
  375. if (descriptor->get_program)
  376. {
  377. while ((descriptor->get_program(handle, programsTotal++)))
  378. continue;
  379. }
  380. LADSPA_Data bufferAudio[bufferSize][audioTotal];
  381. memset(bufferAudio, 0, sizeof(float)*bufferSize*audioTotal);
  382. LADSPA_Data bufferParams[parametersTotal];
  383. memset(bufferParams, 0, sizeof(float)*parametersTotal);
  384. LADSPA_Data min, max, def;
  385. for (unsigned long j=0, iA=0, iP=0; j < ldescriptor->PortCount; j++)
  386. {
  387. const LADSPA_PortDescriptor portType = ldescriptor->PortDescriptors[j];
  388. const LADSPA_PortRangeHint portHints = ldescriptor->PortRangeHints[j];
  389. if (LADSPA_IS_PORT_AUDIO(portType))
  390. {
  391. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  392. }
  393. else if (LADSPA_IS_PORT_CONTROL(portType))
  394. {
  395. // min value
  396. if (LADSPA_IS_HINT_BOUNDED_BELOW(portHints.HintDescriptor))
  397. min = portHints.LowerBound;
  398. else
  399. min = 0.0f;
  400. // max value
  401. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portHints.HintDescriptor))
  402. max = portHints.UpperBound;
  403. else
  404. max = 1.0f;
  405. if (min > max)
  406. max = min;
  407. else if (max < min)
  408. min = max;
  409. if (max - min == 0.0f)
  410. {
  411. DISCOVERY_OUT("error", "Broken parameter: max - min == 0");
  412. max = min + 0.1f;
  413. }
  414. // default value
  415. def = get_default_ladspa_port_value(portHints.HintDescriptor, min, max);
  416. if (def < min)
  417. def = min;
  418. else if (def > max)
  419. def = max;
  420. if (LADSPA_IS_HINT_SAMPLE_RATE(portHints.HintDescriptor))
  421. {
  422. min *= sampleRate;
  423. max *= sampleRate;
  424. def *= sampleRate;
  425. }
  426. if (LADSPA_IS_PORT_OUTPUT(portType) && (strcmp(ldescriptor->PortNames[j], "latency") == 0 || strcmp(ldescriptor->PortNames[j], "_latency") == 0))
  427. {
  428. // latency parameter
  429. min = 0.0f;
  430. max = sampleRate;
  431. def = 0.0f;
  432. }
  433. bufferParams[iP] = def;
  434. ldescriptor->connect_port(handle, j, &bufferParams[iP++]);
  435. }
  436. }
  437. if (ldescriptor->activate)
  438. ldescriptor->activate(handle);
  439. if (descriptor->run_synth || descriptor->run_multiple_synths)
  440. {
  441. snd_seq_event_t midiEvents[2];
  442. memset(midiEvents, 0, sizeof(snd_seq_event_t)*2);
  443. const unsigned long midiEventCount = 2;
  444. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  445. midiEvents[0].data.note.note = 64;
  446. midiEvents[0].data.note.velocity = 100;
  447. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  448. midiEvents[1].data.note.note = 64;
  449. midiEvents[1].data.note.velocity = 0;
  450. midiEvents[1].time.tick = bufferSize/2;
  451. if (descriptor->run_multiple_synths && ! descriptor->run_synth)
  452. {
  453. LADSPA_Handle handlePtr[1] = { handle };
  454. snd_seq_event_t* midiEventsPtr[1] = { midiEvents };
  455. unsigned long midiEventCountPtr[1] = { midiEventCount };
  456. descriptor->run_multiple_synths(1, handlePtr, bufferSize, midiEventsPtr, midiEventCountPtr);
  457. }
  458. else
  459. descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount);
  460. }
  461. else
  462. ldescriptor->run(handle, bufferSize);
  463. if (ldescriptor->deactivate)
  464. ldescriptor->deactivate(handle);
  465. if (ldescriptor->cleanup)
  466. ldescriptor->cleanup(handle);
  467. // end crash-free plugin test
  468. // -----------------------------------------------------------------------
  469. }
  470. DISCOVERY_OUT("init", "-----------");
  471. DISCOVERY_OUT("name", ldescriptor->Name);
  472. DISCOVERY_OUT("label", ldescriptor->Label);
  473. DISCOVERY_OUT("maker", ldescriptor->Maker);
  474. DISCOVERY_OUT("copyright", ldescriptor->Copyright);
  475. DISCOVERY_OUT("unique_id", ldescriptor->UniqueID);
  476. DISCOVERY_OUT("hints", hints);
  477. DISCOVERY_OUT("audio.ins", audioIns);
  478. DISCOVERY_OUT("audio.outs", audioOuts);
  479. DISCOVERY_OUT("audio.total", audioTotal);
  480. DISCOVERY_OUT("midi.ins", midiIns);
  481. DISCOVERY_OUT("midi.total", midiTotal);
  482. DISCOVERY_OUT("parameters.ins", parametersIns);
  483. DISCOVERY_OUT("parameters.outs", parametersOuts);
  484. DISCOVERY_OUT("parameters.total", parametersTotal);
  485. DISCOVERY_OUT("programs.total", programsTotal);
  486. DISCOVERY_OUT("build", BINARY_NATIVE);
  487. DISCOVERY_OUT("end", "------------");
  488. }
  489. #else
  490. DISCOVERY_OUT("error", "DSSI support not available");
  491. Q_UNUSED(libHandle);
  492. Q_UNUSED(init);
  493. #endif
  494. }
  495. void do_lv2_check(const char* const bundle, const bool init)
  496. {
  497. #ifdef WANT_LV2
  498. // Convert bundle filename to URI
  499. QString qBundle(QUrl::fromLocalFile(bundle).toString());
  500. if (! qBundle.endsWith(QDir::separator()))
  501. qBundle += QDir::separator();
  502. // Load bundle
  503. Lilv::Node lilvBundle(lv2World.new_uri(qBundle.toUtf8().constData()));
  504. lv2World.load_bundle(lilvBundle);
  505. // Load plugins in this bundle
  506. const Lilv::Plugins lilvPlugins = lv2World.get_all_plugins();
  507. // Get all plugin URIs in this bundle
  508. QStringList URIs;
  509. LILV_FOREACH(plugins, i, lilvPlugins)
  510. {
  511. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, i));
  512. URIs.append(QString(lilvPlugin.get_uri().as_string()));
  513. }
  514. // Get & check every plugin-instance
  515. for (int i=0; i < URIs.count(); i++)
  516. {
  517. const LV2_RDF_Descriptor* const rdf_descriptor = lv2_rdf_new(URIs.at(i).toUtf8().constData());
  518. CARLA_ASSERT(rdf_descriptor && rdf_descriptor->URI);
  519. if (init)
  520. {
  521. // test if DLL is loadable
  522. void* const libHandle = lib_open(rdf_descriptor->Binary);
  523. if (! libHandle)
  524. {
  525. print_lib_error(rdf_descriptor->Binary);
  526. continue;
  527. }
  528. lib_close(libHandle);
  529. // test if we support all required ports and features
  530. bool supported = true;
  531. for (uint32_t j=0; j < rdf_descriptor->PortCount; j++)
  532. {
  533. const LV2_RDF_Port* const port = &rdf_descriptor->Ports[j];
  534. bool validPort = (LV2_IS_PORT_CONTROL(port->Type) || LV2_IS_PORT_AUDIO(port->Type) || LV2_IS_PORT_ATOM_SEQUENCE(port->Type) /*|| LV2_IS_PORT_CV(port->Type)*/ || LV2_IS_PORT_EVENT(port->Type) || LV2_IS_PORT_MIDI_LL(port->Type));
  535. if (! (validPort || LV2_IS_PORT_OPTIONAL(port->Properties)))
  536. {
  537. DISCOVERY_OUT("error", "plugin requires a non-supported port type, port-name: " << port->Name);
  538. supported = false;
  539. break;
  540. }
  541. }
  542. for (uint32_t j=0; j < rdf_descriptor->FeatureCount && supported; j++)
  543. {
  544. const LV2_RDF_Feature* const feature = &rdf_descriptor->Features[j];
  545. if (LV2_IS_FEATURE_REQUIRED(feature->Type) && ! is_lv2_feature_supported(feature->URI))
  546. {
  547. DISCOVERY_OUT("error", "plugin requires a non-supported feature " << feature->URI);
  548. supported = false;
  549. break;
  550. }
  551. }
  552. if (! supported)
  553. continue;
  554. }
  555. int hints = 0;
  556. int audioIns = 0;
  557. int audioOuts = 0;
  558. int audioTotal = 0;
  559. int midiIns = 0;
  560. int midiOuts = 0;
  561. int midiTotal = 0;
  562. int parametersIns = 0;
  563. int parametersOuts = 0;
  564. int parametersTotal = 0;
  565. for (uint32_t j=0; j < rdf_descriptor->PortCount; j++)
  566. {
  567. const LV2_RDF_Port* const port = &rdf_descriptor->Ports[j];
  568. if (LV2_IS_PORT_AUDIO(port->Type))
  569. {
  570. if (LV2_IS_PORT_INPUT(port->Type))
  571. audioIns += 1;
  572. else if (LV2_IS_PORT_OUTPUT(port->Type))
  573. audioOuts += 1;
  574. audioTotal += 1;
  575. }
  576. else if (LV2_IS_PORT_CONTROL(port->Type))
  577. {
  578. if (LV2_IS_PORT_DESIGNATION_LATENCY(port->Designation) || LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(port->Designation) ||
  579. LV2_IS_PORT_DESIGNATION_FREEWHEELING(port->Designation) || LV2_IS_PORT_DESIGNATION_TIME(port->Designation))
  580. {
  581. pass();
  582. }
  583. else
  584. {
  585. if (LV2_IS_PORT_INPUT(port->Type))
  586. parametersIns += 1;
  587. else if (LV2_IS_PORT_OUTPUT(port->Type))
  588. parametersOuts += 1;
  589. parametersTotal += 1;
  590. }
  591. }
  592. else if (port->Type & LV2_PORT_SUPPORTS_MIDI_EVENT)
  593. {
  594. if (LV2_IS_PORT_INPUT(port->Type))
  595. midiIns += 1;
  596. else if (LV2_IS_PORT_OUTPUT(port->Type))
  597. midiOuts += 1;
  598. midiTotal += 1;
  599. }
  600. }
  601. if (rdf_descriptor->Type & LV2_CLASS_INSTRUMENT)
  602. hints |= PLUGIN_IS_SYNTH;
  603. if (rdf_descriptor->UICount > 0)
  604. hints |= PLUGIN_HAS_GUI;
  605. DISCOVERY_OUT("init", "-----------");
  606. DISCOVERY_OUT("label", rdf_descriptor->URI);
  607. if (rdf_descriptor->Name)
  608. DISCOVERY_OUT("name", rdf_descriptor->Name);
  609. if (rdf_descriptor->Author)
  610. DISCOVERY_OUT("maker", rdf_descriptor->Author);
  611. if (rdf_descriptor->License)
  612. DISCOVERY_OUT("copyright", rdf_descriptor->License);
  613. DISCOVERY_OUT("unique_id", rdf_descriptor->UniqueID);
  614. DISCOVERY_OUT("hints", hints);
  615. DISCOVERY_OUT("audio.ins", audioIns);
  616. DISCOVERY_OUT("audio.outs", audioOuts);
  617. DISCOVERY_OUT("audio.total", audioTotal);
  618. DISCOVERY_OUT("midi.ins", midiIns);
  619. DISCOVERY_OUT("midi.outs", midiOuts);
  620. DISCOVERY_OUT("midi.total", midiTotal);
  621. DISCOVERY_OUT("parameters.ins", parametersIns);
  622. DISCOVERY_OUT("parameters.outs", parametersOuts);
  623. DISCOVERY_OUT("parameters.total", parametersTotal);
  624. DISCOVERY_OUT("build", BINARY_NATIVE);
  625. DISCOVERY_OUT("end", "------------");
  626. }
  627. #else
  628. DISCOVERY_OUT("error", "LV2 support not available");
  629. Q_UNUSED(bundle);
  630. Q_UNUSED(init);
  631. #endif
  632. }
  633. void do_vst_check(void* const libHandle, const bool init)
  634. {
  635. #ifdef WANT_VST
  636. VST_Function vstFn = (VST_Function)lib_symbol(libHandle, "VSTPluginMain");
  637. if (! vstFn)
  638. vstFn = (VST_Function)lib_symbol(libHandle, "main");
  639. if (! vstFn)
  640. {
  641. DISCOVERY_OUT("error", "Not a VST plugin");
  642. return;
  643. }
  644. AEffect* const effect = vstFn(vstHostCallback);
  645. if (! (effect && effect->magic == kEffectMagic))
  646. {
  647. DISCOVERY_OUT("error", "Failed to init VST plugin");
  648. return;
  649. }
  650. const char* cName;
  651. const char* cProduct;
  652. const char* cVendor;
  653. char strBuf[255] = { 0 };
  654. effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f);
  655. cName = strdup((strBuf[0] != 0) ? strBuf : "");
  656. strBuf[0] = 0;
  657. effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f);
  658. cProduct = strdup((strBuf[0] != 0) ? strBuf : "");
  659. strBuf[0] = 0;
  660. effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f);
  661. cVendor = strdup((strBuf[0] != 0) ? strBuf : "");
  662. vstCurrentUniqueId = effect->uniqueID;
  663. intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f);
  664. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  665. while (true)
  666. {
  667. int hints = 0;
  668. int audioIns = effect->numInputs;
  669. int audioOuts = effect->numOutputs;
  670. int audioTotal = audioIns + audioOuts;
  671. int midiIns = 0;
  672. int midiOuts = 0;
  673. int midiTotal = 0;
  674. int parametersIns = effect->numParams;
  675. int parametersTotal = parametersIns;
  676. int programsTotal = effect->numPrograms;
  677. if (effect->flags & effFlagsHasEditor)
  678. hints |= PLUGIN_HAS_GUI;
  679. if (effect->flags & effFlagsIsSynth)
  680. hints |= PLUGIN_IS_SYNTH;
  681. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) > 0)
  682. midiIns = 1;
  683. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  684. midiOuts = 1;
  685. midiTotal = midiIns + midiOuts;
  686. // -----------------------------------------------------------------------
  687. // start crash-free plugin test
  688. if (init)
  689. {
  690. float** bufferAudioIn = new float* [audioIns];
  691. for (int j=0; j < audioIns; j++)
  692. {
  693. bufferAudioIn[j] = new float [bufferSize];
  694. memset(bufferAudioIn[j], 0, sizeof(float)*bufferSize);
  695. }
  696. float** bufferAudioOut = new float* [audioOuts];
  697. for (int j=0; j < audioOuts; j++)
  698. {
  699. bufferAudioOut[j] = new float [bufferSize];
  700. memset(bufferAudioOut[j], 0, sizeof(float)*bufferSize);
  701. }
  702. struct {
  703. int32_t numEvents;
  704. intptr_t reserved;
  705. VstEvent* data[2];
  706. } events;
  707. VstMidiEvent midiEvents[2];
  708. memset(midiEvents, 0, sizeof(VstMidiEvent)*2);
  709. midiEvents[0].type = kVstMidiType;
  710. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  711. midiEvents[0].midiData[0] = 0x90;
  712. midiEvents[0].midiData[1] = 64;
  713. midiEvents[0].midiData[2] = 100;
  714. midiEvents[1].type = kVstMidiType;
  715. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  716. midiEvents[1].midiData[0] = 0x80;
  717. midiEvents[1].midiData[1] = 64;
  718. midiEvents[1].deltaFrames = bufferSize/2;
  719. events.numEvents = 2;
  720. events.reserved = 0;
  721. events.data[0] = (VstEvent*)&midiEvents[0];
  722. events.data[1] = (VstEvent*)&midiEvents[1];
  723. #if ! VST_FORCE_DEPRECATED
  724. effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, bufferSize, nullptr, sampleRate);
  725. #endif
  726. effect->dispatcher(effect, effSetBlockSize, 0, bufferSize, nullptr, 0.0f);
  727. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, sampleRate);
  728. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  729. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  730. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  731. if (midiIns > 0)
  732. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  733. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != effect->process)
  734. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, bufferSize);
  735. #if ! VST_FORCE_DEPRECATED
  736. else
  737. effect->process(effect, bufferAudioIn, bufferAudioOut, bufferSize);
  738. #endif
  739. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  740. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  741. for (int j=0; j < audioIns; j++)
  742. delete[] bufferAudioIn[j];
  743. for (int j=0; j < audioOuts; j++)
  744. delete[] bufferAudioOut[j];
  745. delete[] bufferAudioIn;
  746. delete[] bufferAudioOut;
  747. }
  748. // end crash-free plugin test
  749. // -----------------------------------------------------------------------
  750. DISCOVERY_OUT("init", "-----------");
  751. DISCOVERY_OUT("name", cName);
  752. DISCOVERY_OUT("label", cProduct);
  753. DISCOVERY_OUT("maker", cVendor);
  754. DISCOVERY_OUT("copyright", cVendor);
  755. DISCOVERY_OUT("unique_id", vstCurrentUniqueId);
  756. DISCOVERY_OUT("hints", hints);
  757. DISCOVERY_OUT("audio.ins", audioIns);
  758. DISCOVERY_OUT("audio.outs", audioOuts);
  759. DISCOVERY_OUT("audio.total", audioTotal);
  760. DISCOVERY_OUT("midi.ins", midiIns);
  761. DISCOVERY_OUT("midi.outs", midiOuts);
  762. DISCOVERY_OUT("midi.total", midiTotal);
  763. DISCOVERY_OUT("parameters.ins", parametersIns);
  764. DISCOVERY_OUT("parameters.total", parametersTotal);
  765. DISCOVERY_OUT("programs.total", programsTotal);
  766. DISCOVERY_OUT("build", BINARY_NATIVE);
  767. DISCOVERY_OUT("end", "------------");
  768. if (vstCategory != kPlugCategShell)
  769. break;
  770. strBuf[0] = 0;
  771. vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
  772. if (vstCurrentUniqueId != 0)
  773. {
  774. free((void*)cName);
  775. cName = strdup((strBuf[0] != 0) ? strBuf : "");
  776. }
  777. else
  778. break;
  779. }
  780. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  781. free((void*)cName);
  782. free((void*)cProduct);
  783. free((void*)cVendor);
  784. #else
  785. DISCOVERY_OUT("error", "VST support not available");
  786. Q_UNUSED(libHandle);
  787. Q_UNUSED(init);
  788. #endif
  789. }
  790. void do_fluidsynth_check(const char* const filename, const bool init)
  791. {
  792. #ifdef WANT_FLUIDSYNTH
  793. if (! fluid_is_soundfont(filename))
  794. {
  795. DISCOVERY_OUT("error", "Not a SF2 file");
  796. return;
  797. }
  798. int programs = 0;
  799. if (init)
  800. {
  801. fluid_settings_t* const f_settings = new_fluid_settings();
  802. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  803. const int f_id = fluid_synth_sfload(f_synth, filename, 0);
  804. if (f_id < 0)
  805. {
  806. DISCOVERY_OUT("error", "Failed to load SF2 file");
  807. return;
  808. }
  809. fluid_sfont_t* f_sfont;
  810. fluid_preset_t f_preset;
  811. f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id);
  812. f_sfont->iteration_start(f_sfont);
  813. while (f_sfont->iteration_next(f_sfont, &f_preset))
  814. programs += 1;
  815. delete_fluid_synth(f_synth);
  816. delete_fluid_settings(f_settings);
  817. }
  818. DISCOVERY_OUT("init", "-----------");
  819. DISCOVERY_OUT("name", "");
  820. DISCOVERY_OUT("label", "");
  821. DISCOVERY_OUT("maker", "");
  822. DISCOVERY_OUT("copyright", "");
  823. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  824. DISCOVERY_OUT("audio.outs", 2);
  825. DISCOVERY_OUT("audio.total", 2);
  826. DISCOVERY_OUT("midi.ins", 1);
  827. DISCOVERY_OUT("midi.total", 1);
  828. DISCOVERY_OUT("programs.total", programs);
  829. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  830. DISCOVERY_OUT("parameters.outs", 1);
  831. DISCOVERY_OUT("parameters.total", 14);
  832. DISCOVERY_OUT("build", BINARY_NATIVE);
  833. DISCOVERY_OUT("end", "------------");
  834. #else
  835. DISCOVERY_OUT("error", "SF2 support not available");
  836. Q_UNUSED(filename);
  837. Q_UNUSED(init);
  838. #endif
  839. }
  840. void do_linuxsampler_check(const char* const filename, const char* const stype, const bool init)
  841. {
  842. #ifdef WANT_LINUXSAMPLER
  843. const QFileInfo file(filename);
  844. if (! file.exists())
  845. {
  846. DISCOVERY_OUT("error", "Requested file does not exist");
  847. return;
  848. }
  849. if (! file.isFile())
  850. {
  851. DISCOVERY_OUT("error", "Requested file is not valid");
  852. return;
  853. }
  854. if (! file.isReadable())
  855. {
  856. DISCOVERY_OUT("error", "Requested file is not readable");
  857. return;
  858. }
  859. using namespace LinuxSampler;
  860. class LinuxSamplerScopedEngine {
  861. public:
  862. LinuxSamplerScopedEngine(const char* const filename, const char* const stype)
  863. {
  864. engine = nullptr;
  865. try {
  866. engine = EngineFactory::Create(stype);
  867. }
  868. catch (const Exception& e)
  869. {
  870. DISCOVERY_OUT("error", e.what());
  871. return;
  872. }
  873. if (! engine)
  874. return;
  875. ins = engine->GetInstrumentManager();
  876. if (! ins)
  877. {
  878. DISCOVERY_OUT("error", "Failed to get LinuxSampeler instrument manager");
  879. return;
  880. }
  881. std::vector<InstrumentManager::instrument_id_t> ids;
  882. try {
  883. ids = ins->GetInstrumentFileContent(filename);
  884. }
  885. catch (const Exception& e)
  886. {
  887. DISCOVERY_OUT("error", e.what());
  888. return;
  889. }
  890. if (ids.size() > 0)
  891. {
  892. InstrumentManager::instrument_info_t info = ins->GetInstrumentInfo(ids[0]);
  893. outputInfo(&info, ids.size());
  894. }
  895. }
  896. ~LinuxSamplerScopedEngine()
  897. {
  898. if (engine)
  899. EngineFactory::Destroy(engine);
  900. }
  901. static void outputInfo(InstrumentManager::instrument_info_t* const info, const int programs, const char* const basename = nullptr)
  902. {
  903. DISCOVERY_OUT("init", "-----------");
  904. if (info)
  905. {
  906. DISCOVERY_OUT("name", info->InstrumentName);
  907. DISCOVERY_OUT("label", info->Product);
  908. DISCOVERY_OUT("maker", info->Artists);
  909. DISCOVERY_OUT("copyright", info->Artists);
  910. }
  911. else
  912. {
  913. DISCOVERY_OUT("name", basename);
  914. DISCOVERY_OUT("label", basename);
  915. }
  916. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  917. DISCOVERY_OUT("audio.outs", 2);
  918. DISCOVERY_OUT("audio.total", 2);
  919. DISCOVERY_OUT("midi.ins", 1);
  920. DISCOVERY_OUT("midi.total", 1);
  921. DISCOVERY_OUT("programs.total", programs);
  922. //DISCOVERY_OUT("parameters.ins", 13); // defined in Carla - TODO
  923. //DISCOVERY_OUT("parameters.outs", 1);
  924. //DISCOVERY_OUT("parameters.total", 14);
  925. DISCOVERY_OUT("build", BINARY_NATIVE);
  926. DISCOVERY_OUT("end", "------------");
  927. }
  928. private:
  929. Engine* engine;
  930. InstrumentManager* ins;
  931. };
  932. if (init)
  933. const LinuxSamplerScopedEngine engine(filename, stype);
  934. else
  935. LinuxSamplerScopedEngine::outputInfo(nullptr, 0, file.baseName().toUtf8().constData());
  936. #else
  937. DISCOVERY_OUT("error", stype << " support not available");
  938. Q_UNUSED(filename);
  939. Q_UNUSED(init);
  940. #endif
  941. }
  942. // ------------------------------ main entry point ------------------------------
  943. int main(int argc, char* argv[])
  944. {
  945. if (argc == 2 && strcmp(argv[1], "-formats") == 0)
  946. {
  947. printf("Available plugin formats:\n");
  948. printf("LADSPA: ");
  949. #ifdef WANT_LADSPA
  950. printf("yes\n");
  951. #else
  952. printf("no\n");
  953. #endif
  954. printf("DSSI: ");
  955. #ifdef WANT_DSSI
  956. printf("yes\n");
  957. #else
  958. printf("no\n");
  959. #endif
  960. printf("LV2: ");
  961. #ifdef WANT_LV2
  962. printf("yes\n");
  963. #else
  964. printf("no\n");
  965. #endif
  966. printf("VST: ");
  967. #ifdef WANT_VST
  968. printf("yes\n");
  969. #else
  970. printf("no\n");
  971. #endif
  972. printf("\n");
  973. printf("Available sampler formats:\n");
  974. printf("GIG (LinuxSampler): ");
  975. #ifdef WANT_LINUXSAMPLER
  976. printf("yes\n");
  977. #else
  978. printf("no\n");
  979. #endif
  980. printf("SF2 (FluidSynth): ");
  981. #ifdef WANT_FLUIDSYNTH
  982. printf("yes\n");
  983. #else
  984. printf("no\n");
  985. #endif
  986. printf("SFZ (LinuxSampler): ");
  987. #ifdef WANT_LINUXSAMPLER
  988. printf("yes\n");
  989. #else
  990. printf("no\n");
  991. #endif
  992. return 0;
  993. }
  994. if (argc != 3)
  995. {
  996. qWarning("usage: %s <type> </path/to/plugin>", argv[0]);
  997. return 1;
  998. }
  999. const char* const stype = argv[1];
  1000. const char* const filename = argv[2];
  1001. bool openLib;
  1002. PluginType type;
  1003. void* handle = nullptr;
  1004. if (strcmp(stype, "LADSPA") == 0)
  1005. {
  1006. openLib = true;
  1007. type = PLUGIN_LADSPA;
  1008. }
  1009. else if (strcmp(stype, "DSSI") == 0)
  1010. {
  1011. openLib = true;
  1012. type = PLUGIN_DSSI;
  1013. }
  1014. else if (strcmp(stype, "LV2") == 0)
  1015. {
  1016. openLib = false;
  1017. type = PLUGIN_LV2;
  1018. }
  1019. else if (strcmp(stype, "VST") == 0)
  1020. {
  1021. openLib = true;
  1022. type = PLUGIN_VST;
  1023. }
  1024. else if (strcmp(stype, "GIG") == 0)
  1025. {
  1026. openLib = false;
  1027. type = PLUGIN_GIG;
  1028. }
  1029. else if (strcmp(stype, "SF2") == 0)
  1030. {
  1031. openLib = false;
  1032. type = PLUGIN_SF2;
  1033. }
  1034. else if (strcmp(stype, "SFZ") == 0)
  1035. {
  1036. openLib = false;
  1037. type = PLUGIN_SFZ;
  1038. }
  1039. else
  1040. {
  1041. DISCOVERY_OUT("error", "Invalid plugin type");
  1042. return 1;
  1043. }
  1044. if (openLib)
  1045. {
  1046. handle = lib_open(filename);
  1047. if (! handle)
  1048. {
  1049. print_lib_error(filename);
  1050. return 1;
  1051. }
  1052. }
  1053. bool doInit = ! QString(filename).endsWith("dssi-vst.so", Qt::CaseInsensitive);
  1054. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"))
  1055. doInit = false;
  1056. switch (type)
  1057. {
  1058. case PLUGIN_LADSPA:
  1059. do_ladspa_check(handle, doInit);
  1060. break;
  1061. case PLUGIN_DSSI:
  1062. do_dssi_check(handle, doInit);
  1063. break;
  1064. case PLUGIN_LV2:
  1065. do_lv2_check(filename, doInit);
  1066. break;
  1067. case PLUGIN_VST:
  1068. do_vst_check(handle, doInit);
  1069. break;
  1070. case PLUGIN_GIG:
  1071. do_linuxsampler_check(filename, "gig", doInit);
  1072. break;
  1073. case PLUGIN_SF2:
  1074. do_fluidsynth_check(filename, doInit);
  1075. break;
  1076. case PLUGIN_SFZ:
  1077. do_linuxsampler_check(filename, "sfz", doInit);
  1078. break;
  1079. default:
  1080. break;
  1081. }
  1082. if (openLib)
  1083. lib_close(handle);
  1084. return 0;
  1085. }