Audio plugin host https://kx.studio/carla
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.

1521 lines
47KB

  1. /*
  2. * Carla Plugin discovery code
  3. * Copyright (C) 2011-2013 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 "carla_backend.hpp"
  18. #include "carla_juce_utils.hpp"
  19. #include "carla_lib_utils.hpp"
  20. #include "carla_midi.h"
  21. #ifdef WANT_LADSPA
  22. # include "carla_ladspa_utils.hpp"
  23. #endif
  24. #ifdef WANT_DSSI
  25. # include "carla_ladspa_utils.hpp"
  26. # include "dssi/dssi.h"
  27. #endif
  28. #ifdef WANT_LV2
  29. # include <QtCore/QDir>
  30. # include <QtCore/QUrl>
  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 <QtCore/QFileInfo>
  41. # include "linuxsampler/EngineFactory.h"
  42. #endif
  43. #include <iostream>
  44. #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
  45. CARLA_BACKEND_USE_NAMESPACE
  46. #ifdef WANT_LV2
  47. // --------------------------------------------------------------------------
  48. // Our LV2 World class object
  49. Lv2WorldClass lv2World;
  50. #endif
  51. // --------------------------------------------------------------------------
  52. // Dummy values to test plugins with
  53. const uint32_t bufferSize = 512;
  54. const double sampleRate = 44100.0;
  55. // --------------------------------------------------------------------------
  56. // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
  57. void print_lib_error(const char* const filename)
  58. {
  59. const char* const error = lib_error(filename);
  60. if (error && strstr(error, "wrong ELF class") == nullptr && strstr(error, "Bad EXE format") == nullptr)
  61. DISCOVERY_OUT("error", error);
  62. }
  63. // --------------------------------------------------------------------------
  64. // VST stuff
  65. #ifdef WANT_VST
  66. // Check if plugin wants midi
  67. bool vstWantsMidi = false;
  68. // Check if plugin is processing
  69. bool vstIsProcessing = false;
  70. // Current uniqueId for vst shell plugins
  71. intptr_t vstCurrentUniqueId = 0;
  72. // Supported Carla features
  73. intptr_t vstHostCanDo(const char* const feature)
  74. {
  75. #if DEBUG
  76. qDebug("vstHostCanDo(\"%s\")", feature);
  77. #endif
  78. if (strcmp(feature, "supplyIdle") == 0)
  79. return 1;
  80. if (strcmp(feature, "sendVstEvents") == 0)
  81. return 1;
  82. if (strcmp(feature, "sendVstMidiEvent") == 0)
  83. return 1;
  84. if (strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  85. return 1;
  86. if (strcmp(feature, "sendVstTimeInfo") == 0)
  87. return 1;
  88. if (strcmp(feature, "receiveVstEvents") == 0)
  89. return 1;
  90. if (strcmp(feature, "receiveVstMidiEvent") == 0)
  91. return 1;
  92. if (strcmp(feature, "receiveVstTimeInfo") == 0)
  93. return -1;
  94. if (strcmp(feature, "reportConnectionChanges") == 0)
  95. return -1;
  96. if (strcmp(feature, "acceptIOChanges") == 0)
  97. return 1;
  98. if (strcmp(feature, "sizeWindow") == 0)
  99. return 1;
  100. if (strcmp(feature, "offline") == 0)
  101. return -1;
  102. if (strcmp(feature, "openFileSelector") == 0)
  103. return -1;
  104. if (strcmp(feature, "closeFileSelector") == 0)
  105. return -1;
  106. if (strcmp(feature, "startStopProcess") == 0)
  107. return 1;
  108. if (strcmp(feature, "supportShell") == 0)
  109. return 1;
  110. if (strcmp(feature, "shellCategory") == 0)
  111. return 1;
  112. // unimplemented
  113. qWarning("vstHostCanDo(\"%s\") - unknown feature", feature);
  114. return 0;
  115. }
  116. // Host-side callback
  117. 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)
  118. {
  119. #if DEBUG
  120. qDebug("vstHostCallback(%p, %s, %i, " P_INTPTR ", %p, %f)", effect, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  121. #endif
  122. intptr_t ret = 0;
  123. switch (opcode)
  124. {
  125. case audioMasterAutomate:
  126. if (effect)
  127. {
  128. effect->setParameter(effect, index, opt);
  129. ret = 1;
  130. }
  131. break;
  132. case audioMasterVersion:
  133. ret = kVstVersion;
  134. break;
  135. case audioMasterCurrentId:
  136. ret = vstCurrentUniqueId;
  137. break;
  138. #if ! VST_FORCE_DEPRECATED
  139. case audioMasterWantMidi:
  140. vstWantsMidi = true;
  141. ret = 1;
  142. break;
  143. #endif
  144. case audioMasterGetTime:
  145. static VstTimeInfo_R timeInfo;
  146. memset(&timeInfo, 0, sizeof(VstTimeInfo_R));
  147. timeInfo.sampleRate = sampleRate;
  148. // Tempo
  149. timeInfo.tempo = 120.0;
  150. timeInfo.flags |= kVstTempoValid;
  151. // Time Signature
  152. timeInfo.timeSigNumerator = 4;
  153. timeInfo.timeSigDenominator = 4;
  154. timeInfo.flags |= kVstTimeSigValid;
  155. ret = (intptr_t)&timeInfo;
  156. break;
  157. #if ! VST_FORCE_DEPRECATED
  158. case audioMasterTempoAt:
  159. ret = 120 * 10000;
  160. break;
  161. case audioMasterGetNumAutomatableParameters:
  162. ret = carla_min<int32_t>(effect->numParams, MAX_DEFAULT_PARAMETERS, 0);
  163. break;
  164. case audioMasterGetParameterQuantization:
  165. ret = 1; // full single float precision
  166. break;
  167. #endif
  168. case audioMasterGetSampleRate:
  169. ret = sampleRate;
  170. break;
  171. case audioMasterGetBlockSize:
  172. ret = bufferSize;
  173. break;
  174. #if ! VST_FORCE_DEPRECATED
  175. case audioMasterWillReplaceOrAccumulate:
  176. ret = 1; // replace
  177. break;
  178. #endif
  179. case audioMasterGetCurrentProcessLevel:
  180. ret = vstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
  181. break;
  182. case audioMasterGetAutomationState:
  183. ret = kVstAutomationOff;
  184. break;
  185. case audioMasterGetVendorString:
  186. if (ptr)
  187. {
  188. strcpy((char*)ptr, "falkTX");
  189. ret = 1;
  190. }
  191. break;
  192. case audioMasterGetProductString:
  193. if (ptr)
  194. {
  195. strcpy((char*)ptr, "Carla-Discovery");
  196. ret = 1;
  197. }
  198. break;
  199. case audioMasterGetVendorVersion:
  200. ret = 0x050; // 0.5.0
  201. break;
  202. case audioMasterCanDo:
  203. if (ptr)
  204. ret = vstHostCanDo((const char*)ptr);
  205. break;
  206. case audioMasterGetLanguage:
  207. ret = kVstLangEnglish;
  208. break;
  209. default:
  210. qDebug("vstHostCallback(%p, %s, %i, " P_INTPTR ", %p, %f)", effect, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  211. break;
  212. }
  213. return ret;
  214. }
  215. #endif
  216. // ------------------------------ Plugin Checks -----------------------------
  217. void do_ladspa_check(void* const libHandle, const bool init)
  218. {
  219. #ifdef WANT_LADSPA
  220. const LADSPA_Descriptor_Function descFn = (LADSPA_Descriptor_Function)lib_symbol(libHandle, "ladspa_descriptor");
  221. if (! descFn)
  222. {
  223. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  224. return;
  225. }
  226. unsigned long i = 0;
  227. const LADSPA_Descriptor* descriptor;
  228. while ((descriptor = descFn(i++)))
  229. {
  230. if (! descriptor->instantiate)
  231. {
  232. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
  233. continue;
  234. }
  235. if (! descriptor->cleanup)
  236. {
  237. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
  238. continue;
  239. }
  240. if (! descriptor->run)
  241. {
  242. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
  243. continue;
  244. }
  245. if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  246. {
  247. DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
  248. }
  249. int hints = 0;
  250. int audioIns = 0;
  251. int audioOuts = 0;
  252. int audioTotal = 0;
  253. int parametersIns = 0;
  254. int parametersOuts = 0;
  255. int parametersTotal = 0;
  256. if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  257. hints |= PLUGIN_IS_RTSAFE;
  258. for (unsigned long j=0; j < descriptor->PortCount; j++)
  259. {
  260. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  261. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  262. {
  263. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  264. audioIns += 1;
  265. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  266. audioOuts += 1;
  267. audioTotal += 1;
  268. }
  269. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  270. {
  271. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  272. parametersIns += 1;
  273. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(descriptor->PortNames[j], "latency") && strcmp(descriptor->PortNames[j], "_latency"))
  274. parametersOuts += 1;
  275. parametersTotal += 1;
  276. }
  277. }
  278. if (init)
  279. {
  280. // -----------------------------------------------------------------------
  281. // start crash-free plugin test
  282. const LADSPA_Handle handle = descriptor->instantiate(descriptor, sampleRate);
  283. if (! handle)
  284. {
  285. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  286. continue;
  287. }
  288. LADSPA_Data bufferAudio[bufferSize][audioTotal];
  289. LADSPA_Data bufferParams[parametersTotal];
  290. LADSPA_Data min, max, def;
  291. for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; j++)
  292. {
  293. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  294. const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
  295. const char* const portName = descriptor->PortNames[j];
  296. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  297. {
  298. carla_zeroFloat(bufferAudio[iA], bufferSize);
  299. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  300. }
  301. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  302. {
  303. // min value
  304. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  305. min = portRangeHints.LowerBound;
  306. else
  307. min = 0.0f;
  308. // max value
  309. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  310. max = portRangeHints.UpperBound;
  311. else
  312. max = 1.0f;
  313. if (min > max)
  314. {
  315. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  316. max = min + 0.1f;
  317. }
  318. else if (max - min == 0.0f)
  319. {
  320. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max - min == 0");
  321. max = min + 0.1f;
  322. }
  323. // default value
  324. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  325. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  326. {
  327. min *= sampleRate;
  328. max *= sampleRate;
  329. def *= sampleRate;
  330. }
  331. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (strcmp(portName, "latency") == 0 || strcmp(portName, "_latency") == 0))
  332. {
  333. // latency parameter
  334. def = 0.0f;
  335. }
  336. else
  337. {
  338. if (def < min)
  339. def = min;
  340. else if (def > max)
  341. def = max;
  342. }
  343. bufferParams[iC] = def;
  344. descriptor->connect_port(handle, j, &bufferParams[iC++]);
  345. }
  346. }
  347. if (descriptor->activate)
  348. descriptor->activate(handle);
  349. descriptor->run(handle, bufferSize);
  350. if (descriptor->deactivate)
  351. descriptor->deactivate(handle);
  352. descriptor->cleanup(handle);
  353. // end crash-free plugin test
  354. // -----------------------------------------------------------------------
  355. }
  356. DISCOVERY_OUT("init", "-----------");
  357. DISCOVERY_OUT("name", descriptor->Name);
  358. DISCOVERY_OUT("label", descriptor->Label);
  359. DISCOVERY_OUT("maker", descriptor->Maker);
  360. DISCOVERY_OUT("copyright", descriptor->Copyright);
  361. DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
  362. DISCOVERY_OUT("hints", hints);
  363. DISCOVERY_OUT("audio.ins", audioIns);
  364. DISCOVERY_OUT("audio.outs", audioOuts);
  365. DISCOVERY_OUT("audio.total", audioTotal);
  366. DISCOVERY_OUT("parameters.ins", parametersIns);
  367. DISCOVERY_OUT("parameters.outs", parametersOuts);
  368. DISCOVERY_OUT("parameters.total", parametersTotal);
  369. DISCOVERY_OUT("build", BINARY_NATIVE);
  370. DISCOVERY_OUT("end", "------------");
  371. }
  372. #else
  373. DISCOVERY_OUT("error", "LADSPA support not available");
  374. Q_UNUSED(libHandle);
  375. Q_UNUSED(init);
  376. #endif
  377. }
  378. void do_dssi_check(void* const libHandle, const bool init)
  379. {
  380. #ifdef WANT_DSSI
  381. const DSSI_Descriptor_Function descFn = (DSSI_Descriptor_Function)lib_symbol(libHandle, "dssi_descriptor");
  382. if (! descFn)
  383. {
  384. DISCOVERY_OUT("error", "Not a DSSI plugin");
  385. return;
  386. }
  387. unsigned long i = 0;
  388. const DSSI_Descriptor* descriptor;
  389. while ((descriptor = descFn(i++)))
  390. {
  391. const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
  392. if (! ldescriptor)
  393. {
  394. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no LADSPA interface");
  395. continue;
  396. }
  397. if (! ldescriptor->instantiate)
  398. {
  399. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
  400. continue;
  401. }
  402. if (! ldescriptor->cleanup)
  403. {
  404. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
  405. continue;
  406. }
  407. if (! (ldescriptor->run || descriptor->run_synth || descriptor->run_multiple_synths))
  408. {
  409. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run(), run_synth() or run_multiple_synths()");
  410. continue;
  411. }
  412. if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  413. {
  414. DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
  415. }
  416. int hints = 0;
  417. int audioIns = 0;
  418. int audioOuts = 0;
  419. int audioTotal = 0;
  420. int midiIns = 0;
  421. int midiTotal = 0;
  422. int parametersIns = 0;
  423. int parametersOuts = 0;
  424. int parametersTotal = 0;
  425. int programsTotal = 0;
  426. if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  427. hints |= PLUGIN_IS_RTSAFE;
  428. for (unsigned long j=0; j < ldescriptor->PortCount; j++)
  429. {
  430. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  431. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  432. {
  433. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  434. audioIns += 1;
  435. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  436. audioOuts += 1;
  437. audioTotal += 1;
  438. }
  439. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  440. {
  441. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  442. parametersIns += 1;
  443. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && strcmp(ldescriptor->PortNames[j], "latency") && strcmp(ldescriptor->PortNames[j], "_latency"))
  444. parametersOuts += 1;
  445. parametersTotal += 1;
  446. }
  447. }
  448. if (descriptor->run_synth || descriptor->run_multiple_synths)
  449. midiIns = midiTotal = 1;
  450. if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
  451. hints |= PLUGIN_IS_SYNTH;
  452. if (init)
  453. {
  454. // -----------------------------------------------------------------------
  455. // start crash-free plugin test
  456. const LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, sampleRate);
  457. if (! handle)
  458. {
  459. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  460. continue;
  461. }
  462. if (descriptor->get_program && descriptor->select_program)
  463. {
  464. while (descriptor->get_program(handle, programsTotal++))
  465. continue;
  466. }
  467. LADSPA_Data bufferAudio[bufferSize][audioTotal];
  468. LADSPA_Data bufferParams[parametersTotal];
  469. LADSPA_Data min, max, def;
  470. for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; j++)
  471. {
  472. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  473. const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
  474. const char* const portName = ldescriptor->PortNames[j];
  475. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  476. {
  477. carla_zeroFloat(bufferAudio[iA], bufferSize);
  478. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  479. }
  480. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  481. {
  482. // min value
  483. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  484. min = portRangeHints.LowerBound;
  485. else
  486. min = 0.0f;
  487. // max value
  488. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  489. max = portRangeHints.UpperBound;
  490. else
  491. max = 1.0f;
  492. if (min > max)
  493. {
  494. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  495. max = min + 0.1f;
  496. }
  497. else if (max - min == 0.0f)
  498. {
  499. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max - min == 0");
  500. max = min + 0.1f;
  501. }
  502. // default value
  503. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  504. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  505. {
  506. min *= sampleRate;
  507. max *= sampleRate;
  508. def *= sampleRate;
  509. }
  510. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (strcmp(portName, "latency") == 0 || strcmp(portName, "_latency") == 0))
  511. {
  512. // latency parameter
  513. def = 0.0f;
  514. }
  515. else
  516. {
  517. if (def < min)
  518. def = min;
  519. else if (def > max)
  520. def = max;
  521. }
  522. bufferParams[iC] = def;
  523. ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
  524. }
  525. }
  526. // select first midi-program if available
  527. if (programsTotal > 0)
  528. {
  529. if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
  530. descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
  531. }
  532. if (ldescriptor->activate)
  533. ldescriptor->activate(handle);
  534. if (descriptor->run_synth || descriptor->run_multiple_synths)
  535. {
  536. snd_seq_event_t midiEvents[2];
  537. memset(midiEvents, 0, sizeof(snd_seq_event_t)*2);
  538. const unsigned long midiEventCount = 2;
  539. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  540. midiEvents[0].data.note.note = 64;
  541. midiEvents[0].data.note.velocity = 100;
  542. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  543. midiEvents[1].data.note.note = 64;
  544. midiEvents[1].data.note.velocity = 0;
  545. midiEvents[1].time.tick = bufferSize/2;
  546. if (descriptor->run_multiple_synths && ! descriptor->run_synth)
  547. {
  548. LADSPA_Handle handlePtr[1] = { handle };
  549. snd_seq_event_t* midiEventsPtr[1] = { midiEvents };
  550. unsigned long midiEventCountPtr[1] = { midiEventCount };
  551. descriptor->run_multiple_synths(1, handlePtr, bufferSize, midiEventsPtr, midiEventCountPtr);
  552. }
  553. else
  554. descriptor->run_synth(handle, bufferSize, midiEvents, midiEventCount);
  555. }
  556. else
  557. ldescriptor->run(handle, bufferSize);
  558. if (ldescriptor->deactivate)
  559. ldescriptor->deactivate(handle);
  560. ldescriptor->cleanup(handle);
  561. // end crash-free plugin test
  562. // -----------------------------------------------------------------------
  563. }
  564. DISCOVERY_OUT("init", "-----------");
  565. DISCOVERY_OUT("name", ldescriptor->Name);
  566. DISCOVERY_OUT("label", ldescriptor->Label);
  567. DISCOVERY_OUT("maker", ldescriptor->Maker);
  568. DISCOVERY_OUT("copyright", ldescriptor->Copyright);
  569. DISCOVERY_OUT("unique_id", ldescriptor->UniqueID);
  570. DISCOVERY_OUT("hints", hints);
  571. DISCOVERY_OUT("audio.ins", audioIns);
  572. DISCOVERY_OUT("audio.outs", audioOuts);
  573. DISCOVERY_OUT("audio.total", audioTotal);
  574. DISCOVERY_OUT("midi.ins", midiIns);
  575. DISCOVERY_OUT("midi.total", midiTotal);
  576. DISCOVERY_OUT("parameters.ins", parametersIns);
  577. DISCOVERY_OUT("parameters.outs", parametersOuts);
  578. DISCOVERY_OUT("parameters.total", parametersTotal);
  579. DISCOVERY_OUT("programs.total", programsTotal);
  580. DISCOVERY_OUT("build", BINARY_NATIVE);
  581. DISCOVERY_OUT("end", "------------");
  582. }
  583. #else
  584. DISCOVERY_OUT("error", "DSSI support not available");
  585. Q_UNUSED(libHandle);
  586. Q_UNUSED(init);
  587. #endif
  588. }
  589. void do_lv2_check(const char* const bundle, const bool init)
  590. {
  591. #ifdef WANT_LV2
  592. // Convert bundle filename to URI
  593. QString qBundle(QUrl::fromLocalFile(bundle).toString());
  594. if (! qBundle.endsWith(QDir::separator()))
  595. qBundle += QDir::separator();
  596. // Load bundle
  597. Lilv::Node lilvBundle(lv2World.new_uri(qBundle.toUtf8().constData()));
  598. lv2World.load_bundle(lilvBundle);
  599. // Load plugins in this bundle
  600. const Lilv::Plugins lilvPlugins = lv2World.get_all_plugins();
  601. // Get all plugin URIs in this bundle
  602. QStringList URIs;
  603. LILV_FOREACH(plugins, i, lilvPlugins)
  604. {
  605. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, i));
  606. if (const char* const uri = lilvPlugin.get_uri().as_string())
  607. URIs.append(QString(uri));
  608. }
  609. if (URIs.count() == 0)
  610. {
  611. DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
  612. return;
  613. }
  614. // Get & check every plugin-instance
  615. for (int i=0; i < URIs.count(); i++)
  616. {
  617. const LV2_RDF_Descriptor* const rdfDescriptor = lv2_rdf_new(URIs.at(i).toUtf8().constData());
  618. CARLA_ASSERT(rdfDescriptor && rdfDescriptor->URI);
  619. if (! (rdfDescriptor && rdfDescriptor->URI))
  620. {
  621. DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URIs.at(i).toUtf8().constData() << "'");
  622. continue;
  623. }
  624. if (init)
  625. {
  626. // test if DLL is loadable, twice
  627. bool isLoadable = true;
  628. for (int j=0; j < 2; j++)
  629. {
  630. void* const libHandle = lib_open(rdfDescriptor->Binary);
  631. if (! libHandle)
  632. {
  633. isLoadable = false;
  634. print_lib_error(rdfDescriptor->Binary);
  635. delete rdfDescriptor;
  636. break;
  637. }
  638. lib_close(libHandle);
  639. }
  640. if (! isLoadable)
  641. continue;
  642. }
  643. // test if we support all required ports and features
  644. {
  645. bool supported = true;
  646. for (uint32_t j=0; j < rdfDescriptor->PortCount && supported; j++)
  647. {
  648. const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j];
  649. if (is_lv2_port_supported(rdfPort->Types))
  650. {
  651. pass();
  652. }
  653. else if (! LV2_IS_PORT_OPTIONAL(rdfPort->Properties))
  654. {
  655. DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported port type (portName: '" << rdfPort->Name << "')");
  656. supported = false;
  657. break;
  658. }
  659. }
  660. for (uint32_t j=0; j < rdfDescriptor->FeatureCount && supported; j++)
  661. {
  662. const LV2_RDF_Feature* const rdfFeature = &rdfDescriptor->Features[j];
  663. if (is_lv2_feature_supported(rdfFeature->URI))
  664. {
  665. pass();
  666. }
  667. else if (LV2_IS_FEATURE_REQUIRED(rdfFeature->Type))
  668. {
  669. DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported feature '" << rdfFeature->URI << "'");
  670. supported = false;
  671. break;
  672. }
  673. }
  674. if (! supported)
  675. {
  676. delete rdfDescriptor;
  677. continue;
  678. }
  679. }
  680. int hints = 0;
  681. int audioIns = 0;
  682. int audioOuts = 0;
  683. int audioTotal = 0;
  684. int midiIns = 0;
  685. int midiOuts = 0;
  686. int midiTotal = 0;
  687. int parametersIns = 0;
  688. int parametersOuts = 0;
  689. int parametersTotal = 0;
  690. int programsTotal = rdfDescriptor->PresetCount;
  691. for (uint32_t j=0; j < rdfDescriptor->FeatureCount; j++)
  692. {
  693. const LV2_RDF_Feature* const rdfFeature = &rdfDescriptor->Features[j];
  694. if (strcmp(rdfFeature->URI, LV2_CORE__hardRTCapable) == 0)
  695. hints |= PLUGIN_IS_RTSAFE;
  696. }
  697. for (uint32_t j=0; j < rdfDescriptor->PortCount; j++)
  698. {
  699. const LV2_RDF_Port* const rdfPort = &rdfDescriptor->Ports[j];
  700. if (LV2_IS_PORT_AUDIO(rdfPort->Types))
  701. {
  702. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  703. audioIns += 1;
  704. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  705. audioOuts += 1;
  706. audioTotal += 1;
  707. }
  708. else if (LV2_IS_PORT_CONTROL(rdfPort->Types))
  709. {
  710. if (LV2_IS_PORT_DESIGNATION_LATENCY(rdfPort->Designation))
  711. {
  712. pass();
  713. }
  714. else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(rdfPort->Designation))
  715. {
  716. pass();
  717. }
  718. else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(rdfPort->Designation))
  719. {
  720. pass();
  721. }
  722. else if (LV2_IS_PORT_DESIGNATION_TIME(rdfPort->Designation))
  723. {
  724. pass();
  725. }
  726. else
  727. {
  728. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  729. parametersIns += 1;
  730. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  731. parametersOuts += 1;
  732. parametersTotal += 1;
  733. }
  734. }
  735. else if (LV2_PORT_SUPPORTS_MIDI_EVENT(rdfPort->Types))
  736. {
  737. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  738. midiIns += 1;
  739. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  740. midiOuts += 1;
  741. midiTotal += 1;
  742. }
  743. }
  744. if (rdfDescriptor->Type[1] & LV2_PLUGIN_INSTRUMENT)
  745. hints |= PLUGIN_IS_SYNTH;
  746. if (rdfDescriptor->UICount > 0)
  747. hints |= PLUGIN_HAS_GUI;
  748. DISCOVERY_OUT("init", "-----------");
  749. DISCOVERY_OUT("label", rdfDescriptor->URI);
  750. if (rdfDescriptor->Name)
  751. DISCOVERY_OUT("name", rdfDescriptor->Name);
  752. if (rdfDescriptor->Author)
  753. DISCOVERY_OUT("maker", rdfDescriptor->Author);
  754. if (rdfDescriptor->License)
  755. DISCOVERY_OUT("copyright", rdfDescriptor->License);
  756. DISCOVERY_OUT("unique_id", rdfDescriptor->UniqueID);
  757. DISCOVERY_OUT("hints", hints);
  758. DISCOVERY_OUT("audio.ins", audioIns);
  759. DISCOVERY_OUT("audio.outs", audioOuts);
  760. DISCOVERY_OUT("audio.total", audioTotal);
  761. DISCOVERY_OUT("midi.ins", midiIns);
  762. DISCOVERY_OUT("midi.outs", midiOuts);
  763. DISCOVERY_OUT("midi.total", midiTotal);
  764. DISCOVERY_OUT("parameters.ins", parametersIns);
  765. DISCOVERY_OUT("parameters.outs", parametersOuts);
  766. DISCOVERY_OUT("parameters.total", parametersTotal);
  767. DISCOVERY_OUT("programs.total", programsTotal);
  768. DISCOVERY_OUT("build", BINARY_NATIVE);
  769. DISCOVERY_OUT("end", "------------");
  770. delete rdfDescriptor;
  771. }
  772. #else
  773. DISCOVERY_OUT("error", "LV2 support not available");
  774. Q_UNUSED(bundle);
  775. Q_UNUSED(init);
  776. #endif
  777. }
  778. void do_vst_check(void* const libHandle, const bool init)
  779. {
  780. #ifdef WANT_VST
  781. VST_Function vstFn = (VST_Function)lib_symbol(libHandle, "VSTPluginMain");
  782. if (! vstFn)
  783. {
  784. vstFn = (VST_Function)lib_symbol(libHandle, "main");
  785. if (! vstFn)
  786. {
  787. DISCOVERY_OUT("error", "Not a VST plugin");
  788. return;
  789. }
  790. }
  791. AEffect* const effect = vstFn(vstHostCallback);
  792. if (! (effect && effect->magic == kEffectMagic))
  793. {
  794. DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
  795. return;
  796. }
  797. char strBuf[STR_MAX] = { 0 };
  798. CarlaString cName;
  799. CarlaString cProduct;
  800. CarlaString cVendor;
  801. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  802. intptr_t vstCategory = effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f);
  803. if (vstCategory == kPlugCategShell && effect->uniqueID == 0)
  804. {
  805. if ((vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f)) != 0)
  806. cName = strBuf;
  807. }
  808. else
  809. {
  810. vstCurrentUniqueId = effect->uniqueID;
  811. if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
  812. cName = strBuf;
  813. }
  814. memset(strBuf, 0, sizeof(char)*STR_MAX);
  815. if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
  816. cVendor = strBuf;
  817. // FIXME: Waves crash during processing
  818. if (cVendor == "Waves")
  819. memset((void*)&init, 0, sizeof(bool));
  820. if (vstCurrentUniqueId == 0)
  821. {
  822. DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID");
  823. return;
  824. }
  825. while (vstCurrentUniqueId != 0)
  826. {
  827. memset(strBuf, 0, sizeof(char)*STR_MAX);
  828. if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
  829. cProduct = strBuf;
  830. else
  831. cProduct.clear();
  832. vstWantsMidi = false;
  833. int hints = 0;
  834. int audioIns = effect->numInputs;
  835. int audioOuts = effect->numOutputs;
  836. int audioTotal = audioIns + audioOuts;
  837. int midiIns = 0;
  838. int midiOuts = 0;
  839. int midiTotal = 0;
  840. int parametersIns = effect->numParams;
  841. int parametersTotal = parametersIns;
  842. int programsTotal = effect->numPrograms;
  843. if (effect->flags & effFlagsHasEditor)
  844. hints |= PLUGIN_HAS_GUI;
  845. if (effect->flags & effFlagsIsSynth)
  846. hints |= PLUGIN_IS_SYNTH;
  847. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) > 0)
  848. midiIns = 1;
  849. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  850. midiOuts = 1;
  851. midiTotal = midiIns + midiOuts;
  852. // -----------------------------------------------------------------------
  853. // start crash-free plugin test
  854. if (init)
  855. {
  856. #if ! VST_FORCE_DEPRECATED
  857. effect->dispatcher(effect, effSetBlockSizeAndSampleRate, 0, bufferSize, nullptr, sampleRate);
  858. #endif
  859. effect->dispatcher(effect, effSetBlockSize, 0, bufferSize, nullptr, 0.0f);
  860. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, sampleRate);
  861. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  862. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  863. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  864. // Plugin might call wantMidi() during resume
  865. if (midiIns == 0 && vstWantsMidi)
  866. {
  867. midiIns = 1;
  868. midiTotal = midiIns + midiOuts;
  869. }
  870. float* bufferAudioIn[audioIns];
  871. for (int j=0; j < audioIns; j++)
  872. {
  873. bufferAudioIn[j] = new float [bufferSize];
  874. carla_zeroFloat(bufferAudioIn[j], bufferSize);
  875. }
  876. float* bufferAudioOut[audioOuts];
  877. for (int j=0; j < audioOuts; j++)
  878. {
  879. bufferAudioOut[j] = new float [bufferSize];
  880. carla_zeroFloat(bufferAudioOut[j], bufferSize);
  881. }
  882. struct VstEventsFixed {
  883. int32_t numEvents;
  884. intptr_t reserved;
  885. VstEvent* data[2];
  886. };
  887. VstEventsFixed events;
  888. VstMidiEvent midiEvents[2];
  889. memset(&events, 0, sizeof(VstEventsFixed));
  890. memset(midiEvents, 0, sizeof(VstMidiEvent)*2);
  891. midiEvents[0].type = kVstMidiType;
  892. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  893. midiEvents[0].midiData[0] = MIDI_STATUS_NOTE_ON;
  894. midiEvents[0].midiData[1] = 64;
  895. midiEvents[0].midiData[2] = 100;
  896. midiEvents[1].type = kVstMidiType;
  897. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  898. midiEvents[1].midiData[0] = MIDI_STATUS_NOTE_OFF;
  899. midiEvents[1].midiData[1] = 64;
  900. midiEvents[1].deltaFrames = bufferSize/2;
  901. events.numEvents = 2;
  902. events.data[0] = (VstEvent*)&midiEvents[0];
  903. events.data[1] = (VstEvent*)&midiEvents[1];
  904. // processing
  905. {
  906. vstIsProcessing = true;
  907. if (midiIns > 0)
  908. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  909. #if ! VST_FORCE_DEPRECATED
  910. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing && effect->processReplacing != effect->process)
  911. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, bufferSize);
  912. else if (effect->process)
  913. effect->process(effect, bufferAudioIn, bufferAudioOut, bufferSize);
  914. else
  915. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  916. #else
  917. CARLA_ASSERT(effect->flags & effFlagsCanReplacing);
  918. if (effect->flags & effFlagsCanReplacing)
  919. {
  920. if (effect->processReplacing)
  921. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, bufferSize);
  922. else
  923. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  924. }
  925. else
  926. DISCOVERY_OUT("error", "Plugin doesn't have can't do process replacing");
  927. #endif
  928. vstIsProcessing = false;
  929. }
  930. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  931. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  932. for (int j=0; j < audioIns; j++)
  933. delete[] bufferAudioIn[j];
  934. for (int j=0; j < audioOuts; j++)
  935. delete[] bufferAudioOut[j];
  936. }
  937. // end crash-free plugin test
  938. // -----------------------------------------------------------------------
  939. DISCOVERY_OUT("init", "-----------");
  940. DISCOVERY_OUT("name", (const char*)cName);
  941. DISCOVERY_OUT("label", (const char*)cProduct);
  942. DISCOVERY_OUT("maker", (const char*)cVendor);
  943. DISCOVERY_OUT("copyright", (const char*)cVendor);
  944. DISCOVERY_OUT("unique_id", vstCurrentUniqueId);
  945. DISCOVERY_OUT("hints", hints);
  946. DISCOVERY_OUT("audio.ins", audioIns);
  947. DISCOVERY_OUT("audio.outs", audioOuts);
  948. DISCOVERY_OUT("audio.total", audioTotal);
  949. DISCOVERY_OUT("midi.ins", midiIns);
  950. DISCOVERY_OUT("midi.outs", midiOuts);
  951. DISCOVERY_OUT("midi.total", midiTotal);
  952. DISCOVERY_OUT("parameters.ins", parametersIns);
  953. DISCOVERY_OUT("parameters.total", parametersTotal);
  954. DISCOVERY_OUT("programs.total", programsTotal);
  955. DISCOVERY_OUT("build", BINARY_NATIVE);
  956. DISCOVERY_OUT("end", "------------");
  957. if (vstCategory != kPlugCategShell)
  958. break;
  959. // request next Unique ID
  960. intptr_t nextUniqueId = vstCurrentUniqueId;
  961. // FIXME: Waves sometimes return the same ID
  962. while (nextUniqueId == vstCurrentUniqueId)
  963. {
  964. memset(strBuf, 0, sizeof(char)*STR_MAX);
  965. if ((vstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f)) != 0)
  966. cName = strBuf;
  967. }
  968. }
  969. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  970. #else
  971. DISCOVERY_OUT("error", "VST support not available");
  972. Q_UNUSED(libHandle);
  973. Q_UNUSED(init);
  974. #endif
  975. }
  976. void do_fluidsynth_check(const char* const filename, const bool init)
  977. {
  978. #ifdef WANT_FLUIDSYNTH
  979. if (! fluid_is_soundfont(filename))
  980. {
  981. DISCOVERY_OUT("error", "Not a SF2 file");
  982. return;
  983. }
  984. int programs = 0;
  985. if (init)
  986. {
  987. fluid_settings_t* const f_settings = new_fluid_settings();
  988. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  989. const int f_id = fluid_synth_sfload(f_synth, filename, 0);
  990. if (f_id < 0)
  991. {
  992. DISCOVERY_OUT("error", "Failed to load SF2 file");
  993. return;
  994. }
  995. fluid_sfont_t* f_sfont;
  996. fluid_preset_t f_preset;
  997. f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id);
  998. f_sfont->iteration_start(f_sfont);
  999. while (f_sfont->iteration_next(f_sfont, &f_preset))
  1000. programs += 1;
  1001. delete_fluid_synth(f_synth);
  1002. delete_fluid_settings(f_settings);
  1003. }
  1004. DISCOVERY_OUT("init", "-----------");
  1005. DISCOVERY_OUT("name", "");
  1006. DISCOVERY_OUT("label", "");
  1007. DISCOVERY_OUT("maker", "");
  1008. DISCOVERY_OUT("copyright", "");
  1009. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1010. DISCOVERY_OUT("audio.outs", 2);
  1011. DISCOVERY_OUT("audio.total", 2);
  1012. DISCOVERY_OUT("midi.ins", 1);
  1013. DISCOVERY_OUT("midi.total", 1);
  1014. DISCOVERY_OUT("programs.total", programs);
  1015. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1016. DISCOVERY_OUT("parameters.outs", 1);
  1017. DISCOVERY_OUT("parameters.total", 14);
  1018. DISCOVERY_OUT("build", BINARY_NATIVE);
  1019. DISCOVERY_OUT("end", "------------");
  1020. #else
  1021. DISCOVERY_OUT("error", "SF2 support not available");
  1022. Q_UNUSED(filename);
  1023. Q_UNUSED(init);
  1024. #endif
  1025. }
  1026. void do_linuxsampler_check(const char* const filename, const char* const stype, const bool init)
  1027. {
  1028. #ifdef WANT_LINUXSAMPLER
  1029. const QFileInfo file(filename);
  1030. if (! file.exists())
  1031. {
  1032. DISCOVERY_OUT("error", "Requested file does not exist");
  1033. return;
  1034. }
  1035. if (! file.isFile())
  1036. {
  1037. DISCOVERY_OUT("error", "Requested file is not valid");
  1038. return;
  1039. }
  1040. if (! file.isReadable())
  1041. {
  1042. DISCOVERY_OUT("error", "Requested file is not readable");
  1043. return;
  1044. }
  1045. using namespace LinuxSampler;
  1046. class LinuxSamplerScopedEngine
  1047. {
  1048. public:
  1049. LinuxSamplerScopedEngine(const char* const filename, const char* const stype)
  1050. {
  1051. engine = nullptr;
  1052. try {
  1053. engine = EngineFactory::Create(stype);
  1054. }
  1055. catch (const Exception& e)
  1056. {
  1057. DISCOVERY_OUT("error", e.what());
  1058. return;
  1059. }
  1060. if (! engine)
  1061. return;
  1062. ins = engine->GetInstrumentManager();
  1063. if (! ins)
  1064. {
  1065. DISCOVERY_OUT("error", "Failed to get LinuxSampler instrument manager");
  1066. return;
  1067. }
  1068. std::vector<InstrumentManager::instrument_id_t> ids;
  1069. try {
  1070. ids = ins->GetInstrumentFileContent(filename);
  1071. }
  1072. catch (const Exception& e)
  1073. {
  1074. DISCOVERY_OUT("error", e.what());
  1075. return;
  1076. }
  1077. if (ids.size() > 0)
  1078. {
  1079. InstrumentManager::instrument_info_t info = ins->GetInstrumentInfo(ids[0]);
  1080. outputInfo(&info, ids.size());
  1081. }
  1082. }
  1083. ~LinuxSamplerScopedEngine()
  1084. {
  1085. if (engine)
  1086. EngineFactory::Destroy(engine);
  1087. }
  1088. static void outputInfo(InstrumentManager::instrument_info_t* const info, const int programs, const char* const basename = nullptr)
  1089. {
  1090. DISCOVERY_OUT("init", "-----------");
  1091. if (info)
  1092. {
  1093. DISCOVERY_OUT("name", info->InstrumentName);
  1094. DISCOVERY_OUT("label", info->Product);
  1095. DISCOVERY_OUT("maker", info->Artists);
  1096. DISCOVERY_OUT("copyright", info->Artists);
  1097. }
  1098. else
  1099. {
  1100. DISCOVERY_OUT("name", basename);
  1101. DISCOVERY_OUT("label", basename);
  1102. }
  1103. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1104. DISCOVERY_OUT("audio.outs", 2);
  1105. DISCOVERY_OUT("audio.total", 2);
  1106. DISCOVERY_OUT("midi.ins", 1);
  1107. DISCOVERY_OUT("midi.total", 1);
  1108. DISCOVERY_OUT("programs.total", programs);
  1109. //DISCOVERY_OUT("parameters.ins", 13); // defined in Carla - TODO
  1110. //DISCOVERY_OUT("parameters.outs", 1);
  1111. //DISCOVERY_OUT("parameters.total", 14);
  1112. DISCOVERY_OUT("build", BINARY_NATIVE);
  1113. DISCOVERY_OUT("end", "------------");
  1114. }
  1115. private:
  1116. Engine* engine;
  1117. InstrumentManager* ins;
  1118. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LinuxSamplerScopedEngine)
  1119. };
  1120. if (init)
  1121. const LinuxSamplerScopedEngine engine(filename, stype);
  1122. else
  1123. LinuxSamplerScopedEngine::outputInfo(nullptr, 0, file.baseName().toUtf8().constData());
  1124. #else
  1125. DISCOVERY_OUT("error", stype << " support not available");
  1126. Q_UNUSED(filename);
  1127. Q_UNUSED(init);
  1128. #endif
  1129. }
  1130. // ------------------------------ main entry point ------------------------------
  1131. int main(int argc, char* argv[])
  1132. {
  1133. if (argc == 2 && strcmp(argv[1], "-formats") == 0)
  1134. {
  1135. printf("Available plugin formats:\n");
  1136. printf("LADSPA: ");
  1137. #ifdef WANT_LADSPA
  1138. printf("yes\n");
  1139. #else
  1140. printf("no\n");
  1141. #endif
  1142. printf("DSSI: ");
  1143. #ifdef WANT_DSSI
  1144. printf("yes\n");
  1145. #else
  1146. printf("no\n");
  1147. #endif
  1148. printf("LV2: ");
  1149. #ifdef WANT_LV2
  1150. printf("yes\n");
  1151. #else
  1152. printf("no\n");
  1153. #endif
  1154. printf("VST: ");
  1155. #ifdef WANT_VST
  1156. printf("yes\n");
  1157. #else
  1158. printf("no\n");
  1159. #endif
  1160. printf("\n");
  1161. printf("Available sampler formats:\n");
  1162. printf("GIG (LinuxSampler): ");
  1163. #ifdef WANT_LINUXSAMPLER
  1164. printf("yes\n");
  1165. #else
  1166. printf("no\n");
  1167. #endif
  1168. printf("SF2 (FluidSynth): ");
  1169. #ifdef WANT_FLUIDSYNTH
  1170. printf("yes\n");
  1171. #else
  1172. printf("no\n");
  1173. #endif
  1174. printf("SFZ (LinuxSampler): ");
  1175. #ifdef WANT_LINUXSAMPLER
  1176. printf("yes\n");
  1177. #else
  1178. printf("no\n");
  1179. #endif
  1180. return 0;
  1181. }
  1182. if (argc != 3)
  1183. {
  1184. qWarning("usage: %s <type> </path/to/plugin>", argv[0]);
  1185. return 1;
  1186. }
  1187. const char* const stype = argv[1];
  1188. const char* const filename = argv[2];
  1189. bool openLib;
  1190. PluginType type;
  1191. void* handle = nullptr;
  1192. if (strcmp(stype, "LADSPA") == 0)
  1193. {
  1194. openLib = true;
  1195. type = PLUGIN_LADSPA;
  1196. }
  1197. else if (strcmp(stype, "DSSI") == 0)
  1198. {
  1199. openLib = true;
  1200. type = PLUGIN_DSSI;
  1201. }
  1202. else if (strcmp(stype, "LV2") == 0)
  1203. {
  1204. openLib = false;
  1205. type = PLUGIN_LV2;
  1206. }
  1207. else if (strcmp(stype, "VST") == 0)
  1208. {
  1209. openLib = true;
  1210. type = PLUGIN_VST;
  1211. }
  1212. else if (strcmp(stype, "GIG") == 0)
  1213. {
  1214. openLib = false;
  1215. type = PLUGIN_GIG;
  1216. }
  1217. else if (strcmp(stype, "SF2") == 0)
  1218. {
  1219. openLib = false;
  1220. type = PLUGIN_SF2;
  1221. }
  1222. else if (strcmp(stype, "SFZ") == 0)
  1223. {
  1224. openLib = false;
  1225. type = PLUGIN_SFZ;
  1226. }
  1227. else
  1228. {
  1229. DISCOVERY_OUT("error", "Invalid plugin type");
  1230. return 1;
  1231. }
  1232. if (openLib)
  1233. {
  1234. handle = lib_open(filename);
  1235. if (! handle)
  1236. {
  1237. print_lib_error(filename);
  1238. return 1;
  1239. }
  1240. }
  1241. bool doInit = ! QString(filename).endsWith("dssi-vst.so", Qt::CaseInsensitive);
  1242. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS"))
  1243. doInit = false;
  1244. if (doInit && handle)
  1245. {
  1246. // test fast loading & unloading DLL without initializing the plugin(s)
  1247. if (! lib_close(handle))
  1248. {
  1249. print_lib_error(filename);
  1250. return 1;
  1251. }
  1252. handle = lib_open(filename);
  1253. if (! handle)
  1254. {
  1255. print_lib_error(filename);
  1256. return 1;
  1257. }
  1258. }
  1259. switch (type)
  1260. {
  1261. case PLUGIN_LADSPA:
  1262. do_ladspa_check(handle, doInit);
  1263. break;
  1264. case PLUGIN_DSSI:
  1265. do_dssi_check(handle, doInit);
  1266. break;
  1267. case PLUGIN_LV2:
  1268. do_lv2_check(filename, doInit);
  1269. break;
  1270. case PLUGIN_VST:
  1271. do_vst_check(handle, doInit);
  1272. break;
  1273. case PLUGIN_GIG:
  1274. do_linuxsampler_check(filename, "gig", doInit);
  1275. break;
  1276. case PLUGIN_SF2:
  1277. do_fluidsynth_check(filename, doInit);
  1278. break;
  1279. case PLUGIN_SFZ:
  1280. do_linuxsampler_check(filename, "sfz", doInit);
  1281. break;
  1282. default:
  1283. break;
  1284. }
  1285. if (openLib && handle)
  1286. lib_close(handle);
  1287. return 0;
  1288. }