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.

1525 lines
47KB

  1. /*
  2. * Carla Plugin discovery
  3. * Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or 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 doc/GPL.txt file.
  16. */
  17. #include "CarlaBackendUtils.hpp"
  18. #include "CarlaLibUtils.hpp"
  19. #include "CarlaMathUtils.hpp"
  20. #include "CarlaMIDI.h"
  21. #include "LinkedList.hpp"
  22. #ifdef BUILD_BRIDGE
  23. # undef HAVE_FLUIDSYNTH
  24. #endif
  25. #include "CarlaLadspaUtils.hpp"
  26. #include "CarlaLv2Utils.hpp"
  27. #include "CarlaVstUtils.hpp"
  28. #ifdef CARLA_OS_MAC
  29. # import <Foundation/Foundation.h>
  30. #endif
  31. #ifdef CARLA_OS_WIN
  32. # include <pthread.h>
  33. # include <objbase.h>
  34. #endif
  35. #ifdef HAVE_FLUIDSYNTH
  36. # include <fluidsynth.h>
  37. #endif
  38. #include <iostream>
  39. #ifndef BUILD_BRIDGE
  40. # include "water/files/File.h"
  41. # include "water/text/StringArray.h"
  42. # include "CarlaDssiUtils.cpp"
  43. # include "../backend/utils/CachedPlugins.cpp"
  44. #else
  45. # include "CarlaDssiUtils.hpp"
  46. #endif
  47. #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
  48. using water::CharPointer_UTF8;
  49. using water::File;
  50. using water::StringArray;
  51. CARLA_BACKEND_USE_NAMESPACE
  52. // --------------------------------------------------------------------------
  53. // Dummy values to test plugins with
  54. static const uint32_t kBufferSize = 512;
  55. static const double kSampleRate = 44100.0;
  56. static const int32_t kSampleRatei = 44100;
  57. static const float kSampleRatef = 44100.0f;
  58. // --------------------------------------------------------------------------
  59. // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
  60. static void print_lib_error(const char* const filename)
  61. {
  62. const char* const error(lib_error(filename));
  63. if (error != nullptr &&
  64. std::strstr(error, "wrong ELF class") == nullptr &&
  65. std::strstr(error, "Bad EXE format") == nullptr &&
  66. std::strstr(error, "no suitable image found") == nullptr &&
  67. std::strstr(error, "not a valid Win32 application") == nullptr)
  68. {
  69. DISCOVERY_OUT("error", error);
  70. }
  71. }
  72. // --------------------------------------------------------------------------
  73. // VST stuff
  74. // Check if plugin is currently processing
  75. static bool gVstIsProcessing = false;
  76. // Check if plugin needs idle
  77. static bool gVstNeedsIdle = false;
  78. // Check if plugin wants midi
  79. static bool gVstWantsMidi = false;
  80. // Check if plugin wants time
  81. static bool gVstWantsTime = false;
  82. // Current uniqueId for VST shell plugins
  83. static intptr_t gVstCurrentUniqueId = 0;
  84. // Supported Carla features
  85. static intptr_t vstHostCanDo(const char* const feature)
  86. {
  87. carla_debug("vstHostCanDo(\"%s\")", feature);
  88. if (std::strcmp(feature, "supplyIdle") == 0)
  89. return 1;
  90. if (std::strcmp(feature, "sendVstEvents") == 0)
  91. return 1;
  92. if (std::strcmp(feature, "sendVstMidiEvent") == 0)
  93. return 1;
  94. if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  95. return 1;
  96. if (std::strcmp(feature, "sendVstTimeInfo") == 0)
  97. {
  98. gVstWantsTime = true;
  99. return 1;
  100. }
  101. if (std::strcmp(feature, "receiveVstEvents") == 0)
  102. return 1;
  103. if (std::strcmp(feature, "receiveVstMidiEvent") == 0)
  104. return 1;
  105. if (std::strcmp(feature, "receiveVstTimeInfo") == 0)
  106. return -1;
  107. if (std::strcmp(feature, "reportConnectionChanges") == 0)
  108. return -1;
  109. if (std::strcmp(feature, "acceptIOChanges") == 0)
  110. return 1;
  111. if (std::strcmp(feature, "sizeWindow") == 0)
  112. return 1;
  113. if (std::strcmp(feature, "offline") == 0)
  114. return -1;
  115. if (std::strcmp(feature, "openFileSelector") == 0)
  116. return -1;
  117. if (std::strcmp(feature, "closeFileSelector") == 0)
  118. return -1;
  119. if (std::strcmp(feature, "startStopProcess") == 0)
  120. return 1;
  121. if (std::strcmp(feature, "supportShell") == 0)
  122. return 1;
  123. if (std::strcmp(feature, "shellCategory") == 0)
  124. return 1;
  125. if (std::strcmp(feature, "NIMKPIVendorSpecificCallbacks") == 0)
  126. return -1;
  127. // non-official features found in some plugins:
  128. // "asyncProcessing"
  129. // "editFile"
  130. // unimplemented
  131. carla_stderr("vstHostCanDo(\"%s\") - unknown feature", feature);
  132. return 0;
  133. }
  134. // Host-side callback
  135. static 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)
  136. {
  137. carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  138. static VstTimeInfo timeInfo;
  139. intptr_t ret = 0;
  140. switch (opcode)
  141. {
  142. case audioMasterAutomate:
  143. ret = 1;
  144. break;
  145. case audioMasterVersion:
  146. ret = kVstVersion;
  147. break;
  148. case audioMasterCurrentId:
  149. ret = gVstCurrentUniqueId;
  150. break;
  151. case DECLARE_VST_DEPRECATED(audioMasterWantMidi):
  152. if (gVstWantsMidi) { DISCOVERY_OUT("warning", "Plugin requested MIDI more than once"); }
  153. gVstWantsMidi = true;
  154. ret = 1;
  155. break;
  156. case audioMasterGetTime:
  157. if (! gVstIsProcessing) { DISCOVERY_OUT("warning", "Plugin requested timeInfo out of process"); }
  158. if (! gVstWantsTime) { DISCOVERY_OUT("warning", "Plugin requested timeInfo but didn't ask if host could do \"sendVstTimeInfo\""); }
  159. carla_zeroStruct(timeInfo);
  160. timeInfo.sampleRate = kSampleRate;
  161. // Tempo
  162. timeInfo.tempo = 120.0;
  163. timeInfo.flags |= kVstTempoValid;
  164. // Time Signature
  165. timeInfo.timeSigNumerator = 4;
  166. timeInfo.timeSigDenominator = 4;
  167. timeInfo.flags |= kVstTimeSigValid;
  168. ret = (intptr_t)&timeInfo;
  169. break;
  170. case DECLARE_VST_DEPRECATED(audioMasterTempoAt):
  171. ret = 120 * 10000;
  172. break;
  173. case DECLARE_VST_DEPRECATED(audioMasterGetNumAutomatableParameters):
  174. ret = carla_minPositive(effect->numParams, static_cast<int>(MAX_DEFAULT_PARAMETERS));
  175. break;
  176. case DECLARE_VST_DEPRECATED(audioMasterGetParameterQuantization):
  177. ret = 1; // full single float precision
  178. break;
  179. case DECLARE_VST_DEPRECATED(audioMasterNeedIdle):
  180. if (gVstNeedsIdle) { DISCOVERY_OUT("warning", "Plugin requested idle more than once"); }
  181. gVstNeedsIdle = true;
  182. ret = 1;
  183. break;
  184. case audioMasterGetSampleRate:
  185. ret = kSampleRatei;
  186. break;
  187. case audioMasterGetBlockSize:
  188. ret = kBufferSize;
  189. break;
  190. case DECLARE_VST_DEPRECATED(audioMasterWillReplaceOrAccumulate):
  191. ret = 1; // replace
  192. break;
  193. case audioMasterGetCurrentProcessLevel:
  194. ret = gVstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
  195. break;
  196. case audioMasterGetAutomationState:
  197. ret = kVstAutomationOff;
  198. break;
  199. case audioMasterGetVendorString:
  200. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  201. std::strcpy((char*)ptr, "falkTX");
  202. ret = 1;
  203. break;
  204. case audioMasterGetProductString:
  205. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  206. std::strcpy((char*)ptr, "Carla-Discovery");
  207. ret = 1;
  208. break;
  209. case audioMasterGetVendorVersion:
  210. ret = CARLA_VERSION_HEX;
  211. break;
  212. case audioMasterCanDo:
  213. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  214. ret = vstHostCanDo((const char*)ptr);
  215. break;
  216. case audioMasterGetLanguage:
  217. ret = kVstLangEnglish;
  218. break;
  219. default:
  220. carla_stdout("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  221. break;
  222. }
  223. return ret;
  224. }
  225. // ------------------------------ Plugin Checks -----------------------------
  226. #ifndef BUILD_BRIDGE
  227. static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
  228. {
  229. if (! pinfo->valid)
  230. return;
  231. DISCOVERY_OUT("init", "-----------");
  232. DISCOVERY_OUT("build", BINARY_NATIVE);
  233. DISCOVERY_OUT("hints", pinfo->hints);
  234. DISCOVERY_OUT("name", pinfo->name);
  235. DISCOVERY_OUT("maker", pinfo->maker);
  236. DISCOVERY_OUT("label", pinfo->label);
  237. DISCOVERY_OUT("audio.ins", pinfo->audioIns);
  238. DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
  239. DISCOVERY_OUT("midi.ins", pinfo->midiIns);
  240. DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
  241. DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
  242. DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
  243. DISCOVERY_OUT("end", "------------");
  244. }
  245. static void do_cached_check(const PluginType type)
  246. {
  247. const char* plugPath;
  248. switch (type)
  249. {
  250. case PLUGIN_LV2:
  251. plugPath = std::getenv("LV2_PATH");
  252. break;
  253. case PLUGIN_SFZ:
  254. plugPath = std::getenv("SFZ_PATH");
  255. break;
  256. default:
  257. plugPath = nullptr;
  258. break;
  259. }
  260. const uint count = carla_get_cached_plugin_count(type, plugPath);
  261. for (uint i=0; i<count; ++i)
  262. {
  263. const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i));
  264. CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);
  265. print_cached_plugin(pinfo);
  266. }
  267. }
  268. #endif
  269. static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit)
  270. {
  271. LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  272. if (descFn == nullptr)
  273. {
  274. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  275. return;
  276. }
  277. const LADSPA_Descriptor* descriptor;
  278. {
  279. descriptor = descFn(0);
  280. if (descriptor == nullptr)
  281. {
  282. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  283. return;
  284. }
  285. if (doInit && descriptor->instantiate != nullptr && descriptor->cleanup != nullptr)
  286. {
  287. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  288. if (handle == nullptr)
  289. {
  290. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  291. return;
  292. }
  293. descriptor->cleanup(handle);
  294. lib_close(libHandle);
  295. libHandle = lib_open(filename);
  296. if (libHandle == nullptr)
  297. {
  298. print_lib_error(filename);
  299. return;
  300. }
  301. descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  302. if (descFn == nullptr)
  303. {
  304. DISCOVERY_OUT("error", "Not a LADSPA plugin (#2)");
  305. return;
  306. }
  307. }
  308. }
  309. unsigned long i = 0;
  310. while ((descriptor = descFn(i++)) != nullptr)
  311. {
  312. if (descriptor->instantiate == nullptr)
  313. {
  314. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
  315. continue;
  316. }
  317. if (descriptor->cleanup == nullptr)
  318. {
  319. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
  320. continue;
  321. }
  322. if (descriptor->run == nullptr)
  323. {
  324. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
  325. continue;
  326. }
  327. if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  328. {
  329. DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
  330. }
  331. uint hints = 0x0;
  332. int audioIns = 0;
  333. int audioOuts = 0;
  334. int audioTotal = 0;
  335. int parametersIns = 0;
  336. int parametersOuts = 0;
  337. int parametersTotal = 0;
  338. if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  339. hints |= PLUGIN_IS_RTSAFE;
  340. for (unsigned long j=0; j < descriptor->PortCount; ++j)
  341. {
  342. CARLA_ASSERT(descriptor->PortNames[j] != nullptr);
  343. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  344. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  345. {
  346. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  347. audioIns += 1;
  348. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  349. audioOuts += 1;
  350. audioTotal += 1;
  351. }
  352. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  353. {
  354. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  355. parametersIns += 1;
  356. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(descriptor->PortNames[j], "latency") != 0 && std::strcmp(descriptor->PortNames[j], "_latency") != 0)
  357. parametersOuts += 1;
  358. parametersTotal += 1;
  359. }
  360. }
  361. if (doInit)
  362. {
  363. // -----------------------------------------------------------------------
  364. // start crash-free plugin test
  365. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  366. if (handle == nullptr)
  367. {
  368. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  369. continue;
  370. }
  371. // Test quick init and cleanup
  372. descriptor->cleanup(handle);
  373. handle = descriptor->instantiate(descriptor, kSampleRatei);
  374. if (handle == nullptr)
  375. {
  376. DISCOVERY_OUT("error", "Failed to init LADSPA plugin (#2)");
  377. continue;
  378. }
  379. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  380. LADSPA_Data bufferParams[parametersTotal];
  381. LADSPA_Data min, max, def;
  382. for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; ++j)
  383. {
  384. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  385. const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
  386. const char* const portName = descriptor->PortNames[j];
  387. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  388. {
  389. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  390. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  391. }
  392. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  393. {
  394. // min value
  395. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  396. min = portRangeHints.LowerBound;
  397. else
  398. min = 0.0f;
  399. // max value
  400. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  401. max = portRangeHints.UpperBound;
  402. else
  403. max = 1.0f;
  404. if (min > max)
  405. {
  406. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  407. max = min + 0.1f;
  408. }
  409. else if (carla_isEqual(min, max))
  410. {
  411. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  412. max = min + 0.1f;
  413. }
  414. // default value
  415. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  416. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  417. {
  418. min *= kSampleRatef;
  419. max *= kSampleRatef;
  420. def *= kSampleRatef;
  421. }
  422. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  423. {
  424. // latency parameter
  425. def = 0.0f;
  426. }
  427. else
  428. {
  429. if (def < min)
  430. def = min;
  431. else if (def > max)
  432. def = max;
  433. }
  434. bufferParams[iC] = def;
  435. descriptor->connect_port(handle, j, &bufferParams[iC++]);
  436. }
  437. }
  438. if (descriptor->activate != nullptr)
  439. descriptor->activate(handle);
  440. descriptor->run(handle, kBufferSize);
  441. if (descriptor->deactivate != nullptr)
  442. descriptor->deactivate(handle);
  443. descriptor->cleanup(handle);
  444. // end crash-free plugin test
  445. // -----------------------------------------------------------------------
  446. }
  447. DISCOVERY_OUT("init", "-----------");
  448. DISCOVERY_OUT("build", BINARY_NATIVE);
  449. DISCOVERY_OUT("hints", hints);
  450. DISCOVERY_OUT("name", descriptor->Name);
  451. DISCOVERY_OUT("label", descriptor->Label);
  452. DISCOVERY_OUT("maker", descriptor->Maker);
  453. DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
  454. DISCOVERY_OUT("audio.ins", audioIns);
  455. DISCOVERY_OUT("audio.outs", audioOuts);
  456. DISCOVERY_OUT("parameters.ins", parametersIns);
  457. DISCOVERY_OUT("parameters.outs", parametersOuts);
  458. DISCOVERY_OUT("end", "------------");
  459. }
  460. }
  461. static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit)
  462. {
  463. DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  464. if (descFn == nullptr)
  465. {
  466. DISCOVERY_OUT("error", "Not a DSSI plugin");
  467. return;
  468. }
  469. const DSSI_Descriptor* descriptor;
  470. {
  471. descriptor = descFn(0);
  472. if (descriptor == nullptr)
  473. {
  474. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  475. return;
  476. }
  477. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  478. if (ldescriptor == nullptr)
  479. {
  480. DISCOVERY_OUT("error", "DSSI plugin doesn't provide the LADSPA interface");
  481. return;
  482. }
  483. if (doInit && ldescriptor->instantiate != nullptr && ldescriptor->cleanup != nullptr)
  484. {
  485. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  486. if (handle == nullptr)
  487. {
  488. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  489. return;
  490. }
  491. ldescriptor->cleanup(handle);
  492. lib_close(libHandle);
  493. libHandle = lib_open(filename);
  494. if (libHandle == nullptr)
  495. {
  496. print_lib_error(filename);
  497. return;
  498. }
  499. descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  500. if (descFn == nullptr)
  501. {
  502. DISCOVERY_OUT("error", "Not a DSSI plugin (#2)");
  503. return;
  504. }
  505. }
  506. }
  507. unsigned long i = 0;
  508. while ((descriptor = descFn(i++)) != nullptr)
  509. {
  510. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  511. if (ldescriptor == nullptr)
  512. {
  513. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no LADSPA interface");
  514. continue;
  515. }
  516. if (descriptor->DSSI_API_Version != DSSI_VERSION_MAJOR)
  517. {
  518. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' uses an unsupported DSSI spec version " << descriptor->DSSI_API_Version);
  519. continue;
  520. }
  521. if (ldescriptor->instantiate == nullptr)
  522. {
  523. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
  524. continue;
  525. }
  526. if (ldescriptor->cleanup == nullptr)
  527. {
  528. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
  529. continue;
  530. }
  531. if (ldescriptor->run == nullptr && descriptor->run_synth == nullptr)
  532. {
  533. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run() or run_synth()");
  534. continue;
  535. }
  536. if (descriptor->run_synth == nullptr && descriptor->run_multiple_synths != nullptr)
  537. {
  538. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' requires run_multiple_synths which is not supported");
  539. continue;
  540. }
  541. if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  542. {
  543. DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
  544. }
  545. uint hints = 0x0;
  546. int audioIns = 0;
  547. int audioOuts = 0;
  548. int audioTotal = 0;
  549. int midiIns = 0;
  550. int parametersIns = 0;
  551. int parametersOuts = 0;
  552. int parametersTotal = 0;
  553. if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  554. hints |= PLUGIN_IS_RTSAFE;
  555. for (unsigned long j=0; j < ldescriptor->PortCount; ++j)
  556. {
  557. CARLA_ASSERT(ldescriptor->PortNames[j] != nullptr);
  558. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  559. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  560. {
  561. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  562. audioIns += 1;
  563. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  564. audioOuts += 1;
  565. audioTotal += 1;
  566. }
  567. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  568. {
  569. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  570. parametersIns += 1;
  571. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(ldescriptor->PortNames[j], "latency") != 0 && std::strcmp(ldescriptor->PortNames[j], "_latency") != 0)
  572. parametersOuts += 1;
  573. parametersTotal += 1;
  574. }
  575. }
  576. if (descriptor->run_synth != nullptr)
  577. midiIns = 1;
  578. if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
  579. hints |= PLUGIN_IS_SYNTH;
  580. #ifndef BUILD_BRIDGE
  581. if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label))
  582. {
  583. hints |= PLUGIN_HAS_CUSTOM_UI;
  584. delete[] ui;
  585. }
  586. #endif
  587. if (doInit)
  588. {
  589. // -----------------------------------------------------------------------
  590. // start crash-free plugin test
  591. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  592. if (handle == nullptr)
  593. {
  594. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  595. continue;
  596. }
  597. // Test quick init and cleanup
  598. ldescriptor->cleanup(handle);
  599. handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  600. if (handle == nullptr)
  601. {
  602. DISCOVERY_OUT("error", "Failed to init DSSI plugin (#2)");
  603. continue;
  604. }
  605. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  606. LADSPA_Data bufferParams[parametersTotal];
  607. LADSPA_Data min, max, def;
  608. for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; ++j)
  609. {
  610. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  611. const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
  612. const char* const portName = ldescriptor->PortNames[j];
  613. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  614. {
  615. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  616. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  617. }
  618. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  619. {
  620. // min value
  621. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  622. min = portRangeHints.LowerBound;
  623. else
  624. min = 0.0f;
  625. // max value
  626. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  627. max = portRangeHints.UpperBound;
  628. else
  629. max = 1.0f;
  630. if (min > max)
  631. {
  632. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  633. max = min + 0.1f;
  634. }
  635. else if (carla_isEqual(min, max))
  636. {
  637. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  638. max = min + 0.1f;
  639. }
  640. // default value
  641. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  642. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  643. {
  644. min *= kSampleRatef;
  645. max *= kSampleRatef;
  646. def *= kSampleRatef;
  647. }
  648. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  649. {
  650. // latency parameter
  651. def = 0.0f;
  652. }
  653. else
  654. {
  655. if (def < min)
  656. def = min;
  657. else if (def > max)
  658. def = max;
  659. }
  660. bufferParams[iC] = def;
  661. ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
  662. }
  663. }
  664. // select first midi-program if available
  665. if (descriptor->get_program != nullptr && descriptor->select_program != nullptr)
  666. {
  667. if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
  668. descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
  669. }
  670. if (ldescriptor->activate != nullptr)
  671. ldescriptor->activate(handle);
  672. if (descriptor->run_synth != nullptr)
  673. {
  674. snd_seq_event_t midiEvents[2];
  675. carla_zeroStructs(midiEvents, 2);
  676. const unsigned long midiEventCount = 2;
  677. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  678. midiEvents[0].data.note.note = 64;
  679. midiEvents[0].data.note.velocity = 100;
  680. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  681. midiEvents[1].data.note.note = 64;
  682. midiEvents[1].data.note.velocity = 0;
  683. midiEvents[1].time.tick = kBufferSize/2;
  684. descriptor->run_synth(handle, kBufferSize, midiEvents, midiEventCount);
  685. }
  686. else
  687. ldescriptor->run(handle, kBufferSize);
  688. if (ldescriptor->deactivate != nullptr)
  689. ldescriptor->deactivate(handle);
  690. ldescriptor->cleanup(handle);
  691. // end crash-free plugin test
  692. // -----------------------------------------------------------------------
  693. }
  694. DISCOVERY_OUT("init", "-----------");
  695. DISCOVERY_OUT("build", BINARY_NATIVE);
  696. DISCOVERY_OUT("hints", hints);
  697. DISCOVERY_OUT("name", ldescriptor->Name);
  698. DISCOVERY_OUT("label", ldescriptor->Label);
  699. DISCOVERY_OUT("maker", ldescriptor->Maker);
  700. DISCOVERY_OUT("uniqueId", ldescriptor->UniqueID);
  701. DISCOVERY_OUT("audio.ins", audioIns);
  702. DISCOVERY_OUT("audio.outs", audioOuts);
  703. DISCOVERY_OUT("midi.ins", midiIns);
  704. DISCOVERY_OUT("parameters.ins", parametersIns);
  705. DISCOVERY_OUT("parameters.outs", parametersOuts);
  706. DISCOVERY_OUT("end", "------------");
  707. }
  708. }
  709. #ifndef BUILD_BRIDGE
  710. static void do_lv2_check(const char* const bundle, const bool doInit)
  711. {
  712. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  713. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, bundle));
  714. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(),);
  715. CarlaString sBundle(bundleNode.as_uri());
  716. if (! sBundle.endsWith("/"))
  717. sBundle += "/";
  718. // Load bundle
  719. lv2World.load_bundle(sBundle);
  720. // Load plugins in this bundle
  721. const Lilv::Plugins lilvPlugins(lv2World.get_all_plugins());
  722. // Get all plugin URIs in this bundle
  723. StringArray URIs;
  724. LILV_FOREACH(plugins, it, lilvPlugins)
  725. {
  726. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it));
  727. if (const char* const uri = lilvPlugin.get_uri().as_string())
  728. URIs.addIfNotAlreadyThere(water::String(uri));
  729. }
  730. if (URIs.size() == 0)
  731. {
  732. DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
  733. return;
  734. }
  735. // Get & check every plugin-instance
  736. for (int i=0, count=URIs.size(); i < count; ++i)
  737. {
  738. const char* const URI = URIs[i].toRawUTF8();
  739. ScopedPointer<const LV2_RDF_Descriptor> rdfDescriptor(lv2_rdf_new(URI, false));
  740. if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
  741. {
  742. DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URI << "'");
  743. continue;
  744. }
  745. if (doInit)
  746. {
  747. // test if lib is loadable, twice
  748. const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);
  749. if (libHandle1 == nullptr)
  750. {
  751. print_lib_error(rdfDescriptor->Binary);
  752. delete rdfDescriptor;
  753. continue;
  754. }
  755. lib_close(libHandle1);
  756. const lib_t libHandle2 = lib_open(rdfDescriptor->Binary);
  757. if (libHandle2 == nullptr)
  758. {
  759. print_lib_error(rdfDescriptor->Binary);
  760. delete rdfDescriptor;
  761. continue;
  762. }
  763. lib_close(libHandle2);
  764. }
  765. const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(URI));
  766. CARLA_SAFE_ASSERT_CONTINUE(cPlugin != nullptr);
  767. Lilv::Plugin lilvPlugin(cPlugin);
  768. CARLA_SAFE_ASSERT_CONTINUE(lilvPlugin.get_uri().is_uri());
  769. print_cached_plugin(get_cached_plugin_lv2(lv2World, lilvPlugin));
  770. }
  771. }
  772. #endif
  773. static void do_vst_check(lib_t& libHandle, const char* const filename, const bool doInit)
  774. {
  775. VST_Function vstFn = nullptr;
  776. #ifdef CARLA_OS_MAC
  777. CFBundleRef bundleRef = nullptr;
  778. CFBundleRefNum resFileId = 0;
  779. if (libHandle == nullptr)
  780. {
  781. const CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(0, (const UInt8*)filename, (CFIndex)strlen(filename), true);
  782. CARLA_SAFE_ASSERT_RETURN(urlRef != nullptr,);
  783. bundleRef = CFBundleCreate(kCFAllocatorDefault, urlRef);
  784. CFRelease(urlRef);
  785. CARLA_SAFE_ASSERT_RETURN(bundleRef != nullptr,);
  786. if (! CFBundleLoadExecutable(bundleRef))
  787. {
  788. CFRelease(bundleRef);
  789. DISCOVERY_OUT("error", "Failed to load VST bundle executable");
  790. return;
  791. }
  792. vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleRef, CFSTR("main_macho"));
  793. if (vstFn == nullptr)
  794. vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleRef, CFSTR("VSTPluginMain"));
  795. if (vstFn == nullptr)
  796. {
  797. CFBundleUnloadExecutable(bundleRef);
  798. CFRelease(bundleRef);
  799. DISCOVERY_OUT("error", "Not a VST plugin");
  800. return;
  801. }
  802. resFileId = CFBundleOpenBundleResourceMap(bundleRef);
  803. }
  804. else
  805. #endif
  806. {
  807. vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain");
  808. if (vstFn == nullptr)
  809. {
  810. vstFn = lib_symbol<VST_Function>(libHandle, "main");
  811. if (vstFn == nullptr)
  812. {
  813. DISCOVERY_OUT("error", "Not a VST plugin");
  814. return;
  815. }
  816. }
  817. }
  818. AEffect* effect = vstFn(vstHostCallback);
  819. if (effect == nullptr || effect->magic != kEffectMagic)
  820. {
  821. DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
  822. return;
  823. }
  824. if (effect->uniqueID == 0)
  825. {
  826. DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID");
  827. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  828. return;
  829. }
  830. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  831. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  832. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  833. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  834. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  835. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  836. if (effect->numPrograms > 0)
  837. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  838. const bool isShell = (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f) == kPlugCategShell);
  839. gVstCurrentUniqueId = effect->uniqueID;
  840. char strBuf[STR_MAX+1];
  841. CarlaString cName;
  842. CarlaString cProduct;
  843. CarlaString cVendor;
  844. LinkedList<intptr_t> uniqueIds;
  845. if (isShell)
  846. {
  847. for (;;)
  848. {
  849. carla_zeroChars(strBuf, STR_MAX+1);
  850. gVstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
  851. if (gVstCurrentUniqueId == 0)
  852. break;
  853. uniqueIds.append(gVstCurrentUniqueId);
  854. }
  855. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  856. effect = nullptr;
  857. }
  858. else
  859. {
  860. uniqueIds.append(gVstCurrentUniqueId);
  861. }
  862. for (LinkedList<intptr_t>::Itenerator it = uniqueIds.begin2(); it.valid(); it.next())
  863. {
  864. gVstCurrentUniqueId = it.getValue(0);
  865. if (effect == nullptr)
  866. {
  867. effect = vstFn(vstHostCallback);
  868. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  869. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  870. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  871. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  872. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  873. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  874. if (effect->numPrograms > 0)
  875. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  876. }
  877. // get name
  878. carla_zeroChars(strBuf, STR_MAX+1);
  879. if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
  880. cName = strBuf;
  881. else
  882. cName.clear();
  883. // get product
  884. carla_zeroChars(strBuf, STR_MAX+1);
  885. if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
  886. cProduct = strBuf;
  887. else
  888. cProduct.clear();
  889. // get vendor
  890. carla_zeroChars(strBuf, STR_MAX+1);
  891. if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
  892. cVendor = strBuf;
  893. else
  894. cVendor.clear();
  895. // get everything else
  896. uint hints = 0x0;
  897. int audioIns = effect->numInputs;
  898. int audioOuts = effect->numOutputs;
  899. int midiIns = 0;
  900. int midiOuts = 0;
  901. int parameters = effect->numParams;
  902. if (effect->flags & effFlagsHasEditor)
  903. hints |= PLUGIN_HAS_CUSTOM_UI;
  904. if (effect->flags & effFlagsIsSynth)
  905. hints |= PLUGIN_IS_SYNTH;
  906. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) != 0)
  907. midiIns = 1;
  908. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  909. midiOuts = 1;
  910. // -----------------------------------------------------------------------
  911. // start crash-free plugin test
  912. if (doInit)
  913. {
  914. if (gVstNeedsIdle)
  915. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  916. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  917. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  918. if (gVstNeedsIdle)
  919. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  920. // Plugin might call wantMidi() during resume
  921. if (midiIns == 0 && gVstWantsMidi)
  922. {
  923. midiIns = 1;
  924. }
  925. float* bufferAudioIn[std::max(1, audioIns)];
  926. float* bufferAudioOut[std::max(1, audioOuts)];
  927. if (audioIns == 0)
  928. {
  929. bufferAudioIn[0] = nullptr;
  930. }
  931. else
  932. {
  933. for (int j=0; j < audioIns; ++j)
  934. {
  935. bufferAudioIn[j] = new float[kBufferSize];
  936. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  937. }
  938. }
  939. if (audioOuts == 0)
  940. {
  941. bufferAudioOut[0] = nullptr;
  942. }
  943. else
  944. {
  945. for (int j=0; j < audioOuts; ++j)
  946. {
  947. bufferAudioOut[j] = new float[kBufferSize];
  948. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  949. }
  950. }
  951. struct VstEventsFixed {
  952. int32_t numEvents;
  953. intptr_t reserved;
  954. VstEvent* data[2];
  955. VstEventsFixed()
  956. : numEvents(0),
  957. reserved(0)
  958. {
  959. data[0] = data[1] = nullptr;
  960. }
  961. } events;
  962. VstMidiEvent midiEvents[2];
  963. carla_zeroStructs(midiEvents, 2);
  964. midiEvents[0].type = kVstMidiType;
  965. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  966. midiEvents[0].midiData[0] = char(MIDI_STATUS_NOTE_ON);
  967. midiEvents[0].midiData[1] = 64;
  968. midiEvents[0].midiData[2] = 100;
  969. midiEvents[1].type = kVstMidiType;
  970. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  971. midiEvents[1].midiData[0] = char(MIDI_STATUS_NOTE_OFF);
  972. midiEvents[1].midiData[1] = 64;
  973. midiEvents[1].deltaFrames = kBufferSize/2;
  974. events.numEvents = 2;
  975. events.data[0] = (VstEvent*)&midiEvents[0];
  976. events.data[1] = (VstEvent*)&midiEvents[1];
  977. // processing
  978. gVstIsProcessing = true;
  979. if (midiIns > 0)
  980. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  981. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != nullptr && effect->processReplacing != effect->DECLARE_VST_DEPRECATED(process))
  982. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  983. else if (effect->DECLARE_VST_DEPRECATED(process) != nullptr)
  984. effect->DECLARE_VST_DEPRECATED(process)(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  985. else
  986. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  987. gVstIsProcessing = false;
  988. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  989. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  990. if (gVstNeedsIdle)
  991. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  992. for (int j=0; j < audioIns; ++j)
  993. delete[] bufferAudioIn[j];
  994. for (int j=0; j < audioOuts; ++j)
  995. delete[] bufferAudioOut[j];
  996. }
  997. // end crash-free plugin test
  998. // -----------------------------------------------------------------------
  999. DISCOVERY_OUT("init", "-----------");
  1000. DISCOVERY_OUT("build", BINARY_NATIVE);
  1001. DISCOVERY_OUT("hints", hints);
  1002. DISCOVERY_OUT("name", cName.buffer());
  1003. DISCOVERY_OUT("label", cProduct.buffer());
  1004. DISCOVERY_OUT("maker", cVendor.buffer());
  1005. DISCOVERY_OUT("uniqueId", gVstCurrentUniqueId);
  1006. DISCOVERY_OUT("audio.ins", audioIns);
  1007. DISCOVERY_OUT("audio.outs", audioOuts);
  1008. DISCOVERY_OUT("midi.ins", midiIns);
  1009. DISCOVERY_OUT("midi.outs", midiOuts);
  1010. DISCOVERY_OUT("parameters.ins", parameters);
  1011. DISCOVERY_OUT("end", "------------");
  1012. gVstWantsMidi = false;
  1013. gVstWantsTime = false;
  1014. if (! isShell)
  1015. break;
  1016. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1017. effect = nullptr;
  1018. }
  1019. uniqueIds.clear();
  1020. if (effect != nullptr)
  1021. {
  1022. if (gVstNeedsIdle)
  1023. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1024. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1025. }
  1026. #ifdef CARLA_OS_MAC
  1027. if (bundleRef != nullptr)
  1028. {
  1029. CFBundleCloseBundleResourceMap(bundleRef, resFileId);
  1030. CFBundleUnloadExecutable(bundleRef);
  1031. CFRelease(bundleRef);
  1032. }
  1033. #else
  1034. return;
  1035. // unused
  1036. (void)filename;
  1037. #endif
  1038. }
  1039. static void do_fluidsynth_check(const char* const filename, const bool doInit)
  1040. {
  1041. #ifdef HAVE_FLUIDSYNTH
  1042. const water::String jfilename = water::String(CharPointer_UTF8(filename));
  1043. const File file(jfilename);
  1044. if (! file.existsAsFile())
  1045. {
  1046. DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
  1047. return;
  1048. }
  1049. if (! fluid_is_soundfont(filename))
  1050. {
  1051. DISCOVERY_OUT("error", "Not a SF2 file");
  1052. return;
  1053. }
  1054. int programs = 0;
  1055. if (doInit)
  1056. {
  1057. fluid_settings_t* const f_settings = new_fluid_settings();
  1058. CARLA_SAFE_ASSERT_RETURN(f_settings != nullptr,);
  1059. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  1060. CARLA_SAFE_ASSERT_RETURN(f_synth != nullptr,);
  1061. const int f_id = fluid_synth_sfload(f_synth, filename, 0);
  1062. if (f_id < 0)
  1063. {
  1064. DISCOVERY_OUT("error", "Failed to load SF2 file");
  1065. return;
  1066. }
  1067. if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(f_synth, static_cast<uint>(f_id)))
  1068. {
  1069. #if FLUIDSYNTH_VERSION_MAJOR < 2
  1070. fluid_preset_t f_preset;
  1071. f_sfont->iteration_start(f_sfont);
  1072. for (; f_sfont->iteration_next(f_sfont, &f_preset);)
  1073. #else
  1074. fluid_sfont_iteration_start(f_sfont);
  1075. for (; fluid_sfont_iteration_next(f_sfont);)
  1076. #endif
  1077. ++programs;
  1078. }
  1079. delete_fluid_synth(f_synth);
  1080. delete_fluid_settings(f_settings);
  1081. }
  1082. CarlaString name(file.getFileNameWithoutExtension().toRawUTF8());
  1083. CarlaString label(name);
  1084. // 2 channels
  1085. DISCOVERY_OUT("init", "-----------");
  1086. DISCOVERY_OUT("build", BINARY_NATIVE);
  1087. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1088. DISCOVERY_OUT("name", name.buffer());
  1089. DISCOVERY_OUT("label", label.buffer());
  1090. DISCOVERY_OUT("audio.outs", 2);
  1091. DISCOVERY_OUT("midi.ins", 1);
  1092. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1093. DISCOVERY_OUT("parameters.outs", 1);
  1094. DISCOVERY_OUT("end", "------------");
  1095. // 16 channels
  1096. if (doInit && (name.isEmpty() || programs <= 1))
  1097. return;
  1098. name += " (16 outputs)";
  1099. DISCOVERY_OUT("init", "-----------");
  1100. DISCOVERY_OUT("build", BINARY_NATIVE);
  1101. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1102. DISCOVERY_OUT("name", name.buffer());
  1103. DISCOVERY_OUT("label", label.buffer());
  1104. DISCOVERY_OUT("audio.outs", 32);
  1105. DISCOVERY_OUT("midi.ins", 1);
  1106. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1107. DISCOVERY_OUT("parameters.outs", 1);
  1108. DISCOVERY_OUT("end", "------------");
  1109. #else // HAVE_FLUIDSYNTH
  1110. DISCOVERY_OUT("error", "SF2 support not available");
  1111. return;
  1112. // unused
  1113. (void)filename;
  1114. (void)doInit;
  1115. #endif
  1116. }
  1117. // ------------------------------ main entry point ------------------------------
  1118. int main(int argc, char* argv[])
  1119. {
  1120. if (argc != 3)
  1121. {
  1122. carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
  1123. return 1;
  1124. }
  1125. const char* const stype = argv[1];
  1126. const char* const filename = argv[2];
  1127. const PluginType type = getPluginTypeFromString(stype);
  1128. CarlaString filenameCheck(filename);
  1129. filenameCheck.toLower();
  1130. bool openLib = false;
  1131. lib_t handle = nullptr;
  1132. switch (type)
  1133. {
  1134. case PLUGIN_LADSPA:
  1135. case PLUGIN_DSSI:
  1136. case PLUGIN_VST2:
  1137. openLib = true;
  1138. default:
  1139. break;
  1140. }
  1141. if (type != PLUGIN_SF2 && filenameCheck.contains("fluidsynth", true))
  1142. {
  1143. DISCOVERY_OUT("info", "skipping fluidsynth based plugin");
  1144. return 0;
  1145. }
  1146. #ifdef CARLA_OS_MAC
  1147. if (type == PLUGIN_VST2 && (filenameCheck.endsWith(".vst") || filenameCheck.endsWith(".vst/")))
  1148. openLib = false;
  1149. #endif
  1150. // ---------------------------------------------------------------------
  1151. // Initialize OS features
  1152. #ifdef CARLA_OS_WIN
  1153. OleInitialize(nullptr);
  1154. CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
  1155. # ifndef __WINPTHREADS_VERSION
  1156. // (non-portable) initialization of statically linked pthread library
  1157. pthread_win32_process_attach_np();
  1158. pthread_win32_thread_attach_np();
  1159. # endif
  1160. #endif
  1161. // ---------------------------------------------------------------------
  1162. if (openLib)
  1163. {
  1164. handle = lib_open(filename);
  1165. if (handle == nullptr)
  1166. {
  1167. print_lib_error(filename);
  1168. return 1;
  1169. }
  1170. }
  1171. // never do init for dssi-vst, takes too long and it's crashy
  1172. bool doInit = ! filenameCheck.contains("dssi-vst", true);
  1173. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS") != nullptr)
  1174. doInit = false;
  1175. // ---------------------------------------------------------------------
  1176. if (doInit && openLib && handle != nullptr)
  1177. {
  1178. // test fast loading & unloading DLL without initializing the plugin(s)
  1179. if (! lib_close(handle))
  1180. {
  1181. print_lib_error(filename);
  1182. return 1;
  1183. }
  1184. handle = lib_open(filename);
  1185. if (handle == nullptr)
  1186. {
  1187. print_lib_error(filename);
  1188. return 1;
  1189. }
  1190. }
  1191. #ifndef BUILD_BRIDGE
  1192. if (std::strcmp(filename, ":all") == 0)
  1193. {
  1194. do_cached_check(type);
  1195. return 0;
  1196. }
  1197. #endif
  1198. switch (type)
  1199. {
  1200. case PLUGIN_LADSPA:
  1201. do_ladspa_check(handle, filename, doInit);
  1202. break;
  1203. case PLUGIN_DSSI:
  1204. do_dssi_check(handle, filename, doInit);
  1205. break;
  1206. #ifndef BUILD_BRIDGE
  1207. case PLUGIN_LV2:
  1208. do_lv2_check(filename, doInit);
  1209. break;
  1210. #endif
  1211. case PLUGIN_VST2:
  1212. do_vst_check(handle, filename, doInit);
  1213. break;
  1214. case PLUGIN_SF2:
  1215. do_fluidsynth_check(filename, doInit);
  1216. break;
  1217. default:
  1218. break;
  1219. }
  1220. if (openLib && handle != nullptr)
  1221. lib_close(handle);
  1222. // ---------------------------------------------------------------------
  1223. #ifdef CARLA_OS_WIN
  1224. #ifndef __WINPTHREADS_VERSION
  1225. pthread_win32_thread_detach_np();
  1226. pthread_win32_process_detach_np();
  1227. #endif
  1228. CoUninitialize();
  1229. OleUninitialize();
  1230. #endif
  1231. return 0;
  1232. }
  1233. // --------------------------------------------------------------------------