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.

3055 lines
101KB

  1. // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "CarlaBackendUtils.hpp"
  4. #include "CarlaLibUtils.hpp"
  5. #include "CarlaMathUtils.hpp"
  6. #include "CarlaScopeUtils.hpp"
  7. #include "CarlaMIDI.h"
  8. #include "LinkedList.hpp"
  9. #include "CarlaLadspaUtils.hpp"
  10. #include "CarlaDssiUtils.hpp"
  11. #include "CarlaLv2Utils.hpp"
  12. #include "CarlaVst2Utils.hpp"
  13. #include "CarlaVst3Utils.hpp"
  14. #include "CarlaClapUtils.hpp"
  15. #ifndef BUILDING_CARLA_FOR_WINE
  16. # include "CarlaPipeUtils.cpp"
  17. #endif
  18. #ifdef CARLA_OS_MAC
  19. # include "CarlaMacUtils.cpp"
  20. # include <AudioToolbox/AudioUnit.h>
  21. # ifdef __aarch64__
  22. # include <spawn.h>
  23. # endif
  24. # ifndef __MAC_13_0
  25. enum {
  26. kAudioUnitType_SpeechSynthesizer = 'ausp',
  27. };
  28. # endif
  29. #endif
  30. #ifdef CARLA_OS_WIN
  31. # include <pthread.h>
  32. # include <objbase.h>
  33. #endif
  34. #ifdef BUILD_BRIDGE
  35. # undef HAVE_FLUIDSYNTH
  36. # undef HAVE_YSFX
  37. #endif
  38. #ifdef HAVE_FLUIDSYNTH
  39. # include <fluidsynth.h>
  40. #endif
  41. #include <iostream>
  42. #include <sstream>
  43. #include "water/files/File.h"
  44. #ifndef BUILD_BRIDGE
  45. # include "CarlaDssiUtils.cpp"
  46. # include "CarlaJsfxUtils.hpp"
  47. # include "../backend/utils/CachedPlugins.cpp"
  48. #endif
  49. // must be last
  50. #ifdef BUILDING_CARLA_FOR_WINE
  51. # include "../jackbridge/JackBridge.hpp"
  52. #endif
  53. #define MAX_DISCOVERY_AUDIO_IO 64
  54. #define MAX_DISCOVERY_CV_IO 32
  55. #define DISCOVERY_OUT(x, y) \
  56. if (gPipe != nullptr) { std::stringstream s; s << y; gPipe->writeDiscoveryMessage(x, s.str().c_str()); } \
  57. else { std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl; }
  58. using water::File;
  59. CARLA_BACKEND_USE_NAMESPACE
  60. // --------------------------------------------------------------------------------------------------------------------
  61. // Dummy values to test plugins with
  62. static constexpr const uint32_t kBufferSize = 512;
  63. static constexpr const double kSampleRate = 44100.0;
  64. static constexpr const int32_t kSampleRatei = 44100;
  65. static constexpr const float kSampleRatef = 44100.0f;
  66. // --------------------------------------------------------------------------------------------------------------------
  67. // Dynamic discovery
  68. #ifndef BUILDING_CARLA_FOR_WINE
  69. class DiscoveryPipe : public CarlaPipeClient
  70. {
  71. public:
  72. DiscoveryPipe() {}
  73. ~DiscoveryPipe()
  74. {
  75. writeExitingMessageAndWait();
  76. }
  77. bool writeDiscoveryMessage(const char* const key, const char* const value) const noexcept
  78. {
  79. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
  80. CARLA_SAFE_ASSERT_RETURN(value != nullptr, false);
  81. const CarlaMutexLocker cml(pData->writeLock);
  82. if (! writeAndFixMessage(key))
  83. return false;
  84. if (! writeAndFixMessage(value))
  85. return false;
  86. syncMessages();
  87. return true;
  88. }
  89. protected:
  90. bool msgReceived(const char* const msg) noexcept
  91. {
  92. carla_stdout("discovery msgReceived %s", msg);
  93. return true;
  94. }
  95. };
  96. #else
  97. class DiscoveryPipe
  98. {
  99. void* pipe;
  100. public:
  101. DiscoveryPipe() noexcept : pipe(nullptr) {}
  102. ~DiscoveryPipe()
  103. {
  104. if (pipe != nullptr)
  105. jackbridge_discovery_pipe_destroy(pipe);
  106. }
  107. bool initPipeClient(const char* argv[])
  108. {
  109. if (jackbridge_is_ok())
  110. pipe = jackbridge_discovery_pipe_create(argv);
  111. return pipe != nullptr;
  112. }
  113. bool writeDiscoveryMessage(const char* const key, const char* const value) const noexcept
  114. {
  115. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false);
  116. CARLA_SAFE_ASSERT_RETURN(value != nullptr, false);
  117. jackbridge_discovery_pipe_message(pipe, key, value);
  118. return true;
  119. }
  120. };
  121. #endif
  122. CarlaScopedPointer<DiscoveryPipe> gPipe;
  123. // --------------------------------------------------------------------------------------------------------------------
  124. // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
  125. static void print_lib_error(const char* const filename)
  126. {
  127. const char* const error = lib_error(filename);
  128. if (error != nullptr &&
  129. std::strstr(error, "wrong ELF class") == nullptr &&
  130. std::strstr(error, "invalid ELF header") == nullptr &&
  131. std::strstr(error, "Bad EXE format") == nullptr &&
  132. std::strstr(error, "no suitable image found") == nullptr &&
  133. std::strstr(error, "not a valid Win32 application") == nullptr)
  134. {
  135. DISCOVERY_OUT("error", error);
  136. }
  137. }
  138. #ifdef CARLA_OS_WIN
  139. // --------------------------------------------------------------------------------------------------------------------
  140. // Do not show error message box on Windows
  141. static LONG WINAPI winExceptionFilter(_EXCEPTION_POINTERS*)
  142. {
  143. return EXCEPTION_EXECUTE_HANDLER;
  144. }
  145. #endif
  146. // --------------------------------------------------------------------------------------------------------------------
  147. // Carla Cached API
  148. #ifndef BUILD_BRIDGE
  149. static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
  150. {
  151. if (! pinfo->valid)
  152. return;
  153. DISCOVERY_OUT("init", "------------");
  154. DISCOVERY_OUT("build", BINARY_NATIVE);
  155. DISCOVERY_OUT("hints", pinfo->hints);
  156. DISCOVERY_OUT("category", getPluginCategoryAsString(pinfo->category));
  157. DISCOVERY_OUT("name", pinfo->name);
  158. DISCOVERY_OUT("maker", pinfo->maker);
  159. DISCOVERY_OUT("label", pinfo->label);
  160. DISCOVERY_OUT("audio.ins", pinfo->audioIns);
  161. DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
  162. DISCOVERY_OUT("cv.ins", pinfo->cvIns);
  163. DISCOVERY_OUT("cv.outs", pinfo->cvOuts);
  164. DISCOVERY_OUT("midi.ins", pinfo->midiIns);
  165. DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
  166. DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
  167. DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
  168. DISCOVERY_OUT("end", "------------");
  169. }
  170. static void do_cached_check(const PluginType type)
  171. {
  172. const char* plugPath = std::getenv("CARLA_DISCOVERY_PATH");
  173. if (plugPath == nullptr)
  174. {
  175. switch (type)
  176. {
  177. case PLUGIN_LV2:
  178. plugPath = std::getenv("LV2_PATH");
  179. break;
  180. case PLUGIN_SFZ:
  181. plugPath = std::getenv("SFZ_PATH");
  182. break;
  183. default:
  184. plugPath = nullptr;
  185. break;
  186. }
  187. }
  188. const uint count = carla_get_cached_plugin_count(type, plugPath);
  189. for (uint i=0; i<count; ++i)
  190. {
  191. const CarlaCachedPluginInfo* pinfo = carla_get_cached_plugin_info(type, i);
  192. CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);
  193. print_cached_plugin(pinfo);
  194. }
  195. }
  196. #endif // ! BUILD_BRIDGE
  197. // --------------------------------------------------------------------------------------------------------------------
  198. // LADSPA
  199. static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit)
  200. {
  201. LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  202. if (descFn == nullptr)
  203. {
  204. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  205. return;
  206. }
  207. const LADSPA_Descriptor* descriptor;
  208. {
  209. descriptor = descFn(0);
  210. if (descriptor == nullptr)
  211. {
  212. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  213. return;
  214. }
  215. if (doInit && descriptor->instantiate != nullptr && descriptor->cleanup != nullptr)
  216. {
  217. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  218. if (handle == nullptr)
  219. {
  220. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  221. return;
  222. }
  223. descriptor->cleanup(handle);
  224. lib_close(libHandle);
  225. libHandle = lib_open(filename);
  226. if (libHandle == nullptr)
  227. {
  228. print_lib_error(filename);
  229. return;
  230. }
  231. descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  232. if (descFn == nullptr)
  233. {
  234. DISCOVERY_OUT("error", "Not a LADSPA plugin (#2)");
  235. return;
  236. }
  237. }
  238. }
  239. unsigned long i = 0;
  240. while ((descriptor = descFn(i++)) != nullptr)
  241. {
  242. if (descriptor->instantiate == nullptr)
  243. {
  244. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
  245. continue;
  246. }
  247. if (descriptor->cleanup == nullptr)
  248. {
  249. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
  250. continue;
  251. }
  252. if (descriptor->run == nullptr)
  253. {
  254. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
  255. continue;
  256. }
  257. if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  258. {
  259. DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
  260. }
  261. uint hints = 0x0;
  262. uint audioIns = 0;
  263. uint audioOuts = 0;
  264. uint parametersIns = 0;
  265. uint parametersOuts = 0;
  266. uint parametersTotal = 0;
  267. if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  268. hints |= PLUGIN_IS_RTSAFE;
  269. for (unsigned long j=0; j < descriptor->PortCount; ++j)
  270. {
  271. CARLA_ASSERT(descriptor->PortNames[j] != nullptr);
  272. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  273. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  274. {
  275. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  276. audioIns += 1;
  277. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  278. audioOuts += 1;
  279. }
  280. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  281. {
  282. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  283. parametersIns += 1;
  284. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(descriptor->PortNames[j], "latency") != 0 && std::strcmp(descriptor->PortNames[j], "_latency") != 0)
  285. parametersOuts += 1;
  286. parametersTotal += 1;
  287. }
  288. }
  289. CARLA_SAFE_ASSERT_CONTINUE(audioIns <= MAX_DISCOVERY_AUDIO_IO);
  290. CARLA_SAFE_ASSERT_CONTINUE(audioOuts <= MAX_DISCOVERY_AUDIO_IO);
  291. if (doInit)
  292. {
  293. // -----------------------------------------------------------------------
  294. // start crash-free plugin test
  295. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  296. if (handle == nullptr)
  297. {
  298. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  299. continue;
  300. }
  301. // Test quick init and cleanup
  302. descriptor->cleanup(handle);
  303. handle = descriptor->instantiate(descriptor, kSampleRatei);
  304. if (handle == nullptr)
  305. {
  306. DISCOVERY_OUT("error", "Failed to init LADSPA plugin (#2)");
  307. continue;
  308. }
  309. LADSPA_Data* bufferParams = new LADSPA_Data[parametersTotal];
  310. LADSPA_Data bufferAudio[kBufferSize][MAX_DISCOVERY_AUDIO_IO];
  311. LADSPA_Data min, max, def;
  312. for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; ++j)
  313. {
  314. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  315. const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
  316. const char* const portName = descriptor->PortNames[j];
  317. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  318. {
  319. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  320. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  321. }
  322. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  323. {
  324. // min value
  325. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  326. min = portRangeHints.LowerBound;
  327. else
  328. min = 0.0f;
  329. // max value
  330. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  331. max = portRangeHints.UpperBound;
  332. else
  333. max = 1.0f;
  334. if (min > max)
  335. {
  336. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  337. max = min + 0.1f;
  338. }
  339. else if (carla_isEqual(min, max))
  340. {
  341. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  342. max = min + 0.1f;
  343. }
  344. // default value
  345. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  346. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  347. {
  348. min *= kSampleRatef;
  349. max *= kSampleRatef;
  350. def *= kSampleRatef;
  351. }
  352. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  353. {
  354. // latency parameter
  355. def = 0.0f;
  356. }
  357. else
  358. {
  359. if (def < min)
  360. def = min;
  361. else if (def > max)
  362. def = max;
  363. }
  364. bufferParams[iC] = def;
  365. descriptor->connect_port(handle, j, &bufferParams[iC++]);
  366. }
  367. }
  368. if (descriptor->activate != nullptr)
  369. descriptor->activate(handle);
  370. descriptor->run(handle, kBufferSize);
  371. if (descriptor->deactivate != nullptr)
  372. descriptor->deactivate(handle);
  373. descriptor->cleanup(handle);
  374. delete[] bufferParams;
  375. // end crash-free plugin test
  376. // -----------------------------------------------------------------------
  377. }
  378. DISCOVERY_OUT("init", "------------");
  379. DISCOVERY_OUT("build", BINARY_NATIVE);
  380. DISCOVERY_OUT("hints", hints);
  381. DISCOVERY_OUT("category", getPluginCategoryAsString(getPluginCategoryFromName(descriptor->Name)));
  382. DISCOVERY_OUT("name", descriptor->Name);
  383. DISCOVERY_OUT("label", descriptor->Label);
  384. DISCOVERY_OUT("maker", descriptor->Maker);
  385. DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
  386. DISCOVERY_OUT("audio.ins", audioIns);
  387. DISCOVERY_OUT("audio.outs", audioOuts);
  388. DISCOVERY_OUT("parameters.ins", parametersIns);
  389. DISCOVERY_OUT("parameters.outs", parametersOuts);
  390. DISCOVERY_OUT("end", "------------");
  391. }
  392. }
  393. // --------------------------------------------------------------------------------------------------------------------
  394. // DSSI
  395. static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit)
  396. {
  397. DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  398. if (descFn == nullptr)
  399. {
  400. DISCOVERY_OUT("error", "Not a DSSI plugin");
  401. return;
  402. }
  403. const DSSI_Descriptor* descriptor;
  404. {
  405. descriptor = descFn(0);
  406. if (descriptor == nullptr)
  407. {
  408. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  409. return;
  410. }
  411. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  412. if (ldescriptor == nullptr)
  413. {
  414. DISCOVERY_OUT("error", "DSSI plugin doesn't provide the LADSPA interface");
  415. return;
  416. }
  417. if (doInit && ldescriptor->instantiate != nullptr && ldescriptor->cleanup != nullptr)
  418. {
  419. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  420. if (handle == nullptr)
  421. {
  422. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  423. return;
  424. }
  425. ldescriptor->cleanup(handle);
  426. lib_close(libHandle);
  427. libHandle = lib_open(filename);
  428. if (libHandle == nullptr)
  429. {
  430. print_lib_error(filename);
  431. return;
  432. }
  433. descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  434. if (descFn == nullptr)
  435. {
  436. DISCOVERY_OUT("error", "Not a DSSI plugin (#2)");
  437. return;
  438. }
  439. }
  440. }
  441. unsigned long i = 0;
  442. while ((descriptor = descFn(i++)) != nullptr)
  443. {
  444. const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
  445. if (ldescriptor == nullptr)
  446. {
  447. DISCOVERY_OUT("error", "Plugin has no LADSPA interface");
  448. continue;
  449. }
  450. if (descriptor->DSSI_API_Version != DSSI_VERSION_MAJOR)
  451. {
  452. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' uses an unsupported DSSI spec version " << descriptor->DSSI_API_Version);
  453. continue;
  454. }
  455. if (ldescriptor->instantiate == nullptr)
  456. {
  457. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
  458. continue;
  459. }
  460. if (ldescriptor->cleanup == nullptr)
  461. {
  462. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
  463. continue;
  464. }
  465. if (ldescriptor->run == nullptr && descriptor->run_synth == nullptr)
  466. {
  467. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run() or run_synth()");
  468. continue;
  469. }
  470. if (descriptor->run_synth == nullptr && descriptor->run_multiple_synths != nullptr)
  471. {
  472. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' requires run_multiple_synths which is not supported");
  473. continue;
  474. }
  475. if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  476. {
  477. DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
  478. }
  479. uint hints = 0x0;
  480. uint audioIns = 0;
  481. uint audioOuts = 0;
  482. uint midiIns = 0;
  483. uint parametersIns = 0;
  484. uint parametersOuts = 0;
  485. uint parametersTotal = 0;
  486. if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  487. hints |= PLUGIN_IS_RTSAFE;
  488. for (unsigned long j=0; j < ldescriptor->PortCount; ++j)
  489. {
  490. CARLA_ASSERT(ldescriptor->PortNames[j] != nullptr);
  491. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  492. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  493. {
  494. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  495. audioIns += 1;
  496. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  497. audioOuts += 1;
  498. }
  499. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  500. {
  501. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  502. parametersIns += 1;
  503. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(ldescriptor->PortNames[j], "latency") != 0 && std::strcmp(ldescriptor->PortNames[j], "_latency") != 0)
  504. parametersOuts += 1;
  505. parametersTotal += 1;
  506. }
  507. }
  508. CARLA_SAFE_ASSERT_CONTINUE(audioIns <= MAX_DISCOVERY_AUDIO_IO);
  509. CARLA_SAFE_ASSERT_CONTINUE(audioOuts <= MAX_DISCOVERY_AUDIO_IO);
  510. if (descriptor->run_synth != nullptr)
  511. midiIns = 1;
  512. if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
  513. hints |= PLUGIN_IS_SYNTH;
  514. #ifndef BUILD_BRIDGE
  515. if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label))
  516. {
  517. hints |= PLUGIN_HAS_CUSTOM_UI;
  518. delete[] ui;
  519. }
  520. #endif
  521. if (doInit)
  522. {
  523. // -----------------------------------------------------------------------
  524. // start crash-free plugin test
  525. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  526. if (handle == nullptr)
  527. {
  528. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  529. continue;
  530. }
  531. // Test quick init and cleanup
  532. ldescriptor->cleanup(handle);
  533. handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  534. if (handle == nullptr)
  535. {
  536. DISCOVERY_OUT("error", "Failed to init DSSI plugin (#2)");
  537. continue;
  538. }
  539. LADSPA_Data* bufferParams = new LADSPA_Data[parametersTotal];
  540. LADSPA_Data bufferAudio[kBufferSize][MAX_DISCOVERY_AUDIO_IO];
  541. LADSPA_Data min, max, def;
  542. for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; ++j)
  543. {
  544. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  545. const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
  546. const char* const portName = ldescriptor->PortNames[j];
  547. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  548. {
  549. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  550. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  551. }
  552. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  553. {
  554. // min value
  555. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  556. min = portRangeHints.LowerBound;
  557. else
  558. min = 0.0f;
  559. // max value
  560. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  561. max = portRangeHints.UpperBound;
  562. else
  563. max = 1.0f;
  564. if (min > max)
  565. {
  566. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  567. max = min + 0.1f;
  568. }
  569. else if (carla_isEqual(min, max))
  570. {
  571. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  572. max = min + 0.1f;
  573. }
  574. // default value
  575. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  576. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  577. {
  578. min *= kSampleRatef;
  579. max *= kSampleRatef;
  580. def *= kSampleRatef;
  581. }
  582. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  583. {
  584. // latency parameter
  585. def = 0.0f;
  586. }
  587. else
  588. {
  589. if (def < min)
  590. def = min;
  591. else if (def > max)
  592. def = max;
  593. }
  594. bufferParams[iC] = def;
  595. ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
  596. }
  597. }
  598. // select first midi-program if available
  599. if (descriptor->get_program != nullptr && descriptor->select_program != nullptr)
  600. {
  601. if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
  602. descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
  603. }
  604. if (ldescriptor->activate != nullptr)
  605. ldescriptor->activate(handle);
  606. if (descriptor->run_synth != nullptr)
  607. {
  608. snd_seq_event_t midiEvents[2];
  609. carla_zeroStructs(midiEvents, 2);
  610. const unsigned long midiEventCount = 2;
  611. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  612. midiEvents[0].data.note.note = 64;
  613. midiEvents[0].data.note.velocity = 100;
  614. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  615. midiEvents[1].data.note.note = 64;
  616. midiEvents[1].data.note.velocity = 0;
  617. midiEvents[1].time.tick = kBufferSize/2;
  618. descriptor->run_synth(handle, kBufferSize, midiEvents, midiEventCount);
  619. }
  620. else
  621. ldescriptor->run(handle, kBufferSize);
  622. if (ldescriptor->deactivate != nullptr)
  623. ldescriptor->deactivate(handle);
  624. ldescriptor->cleanup(handle);
  625. delete[] bufferParams;
  626. // end crash-free plugin test
  627. // -----------------------------------------------------------------------
  628. }
  629. DISCOVERY_OUT("init", "------------");
  630. DISCOVERY_OUT("build", BINARY_NATIVE);
  631. DISCOVERY_OUT("category", ((hints & PLUGIN_IS_SYNTH)
  632. ? "synth"
  633. : getPluginCategoryAsString(getPluginCategoryFromName(ldescriptor->Name))));
  634. DISCOVERY_OUT("hints", hints);
  635. DISCOVERY_OUT("name", ldescriptor->Name);
  636. DISCOVERY_OUT("label", ldescriptor->Label);
  637. DISCOVERY_OUT("maker", ldescriptor->Maker);
  638. DISCOVERY_OUT("uniqueId", ldescriptor->UniqueID);
  639. DISCOVERY_OUT("audio.ins", audioIns);
  640. DISCOVERY_OUT("audio.outs", audioOuts);
  641. DISCOVERY_OUT("midi.ins", midiIns);
  642. DISCOVERY_OUT("parameters.ins", parametersIns);
  643. DISCOVERY_OUT("parameters.outs", parametersOuts);
  644. DISCOVERY_OUT("end", "------------");
  645. }
  646. }
  647. // --------------------------------------------------------------------------------------------------------------------
  648. // LV2
  649. #ifndef BUILD_BRIDGE
  650. static void do_lv2_check(const char* const bundle, const bool doInit)
  651. {
  652. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  653. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, bundle));
  654. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(),);
  655. CarlaString sBundle(bundleNode.as_uri());
  656. if (! sBundle.endsWith("/"))
  657. sBundle += "/";
  658. // Load bundle
  659. lv2World.load_bundle(sBundle);
  660. // Load plugins in this bundle
  661. const Lilv::Plugins lilvPlugins(lv2World.get_all_plugins());
  662. // Get all plugin URIs in this bundle
  663. CarlaStringList URIs;
  664. LILV_FOREACH(plugins, it, lilvPlugins)
  665. {
  666. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it));
  667. if (const char* const uri = lilvPlugin.get_uri().as_string())
  668. URIs.appendUnique(uri);
  669. }
  670. if (URIs.isEmpty())
  671. {
  672. DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
  673. return;
  674. }
  675. // Get & check every plugin-instance
  676. for (CarlaStringList::Itenerator it=URIs.begin2(); it.valid(); it.next())
  677. {
  678. const char* const URI = it.getValue(nullptr);
  679. CARLA_SAFE_ASSERT_CONTINUE(URI != nullptr);
  680. CarlaScopedPointer<const LV2_RDF_Descriptor> rdfDescriptor(lv2_rdf_new(URI, false));
  681. if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
  682. {
  683. DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URI << "'");
  684. continue;
  685. }
  686. if (doInit)
  687. {
  688. // test if lib is loadable, twice
  689. const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);
  690. if (libHandle1 == nullptr)
  691. {
  692. print_lib_error(rdfDescriptor->Binary);
  693. delete rdfDescriptor;
  694. continue;
  695. }
  696. lib_close(libHandle1);
  697. const lib_t libHandle2 = lib_open(rdfDescriptor->Binary);
  698. if (libHandle2 == nullptr)
  699. {
  700. print_lib_error(rdfDescriptor->Binary);
  701. delete rdfDescriptor;
  702. continue;
  703. }
  704. lib_close(libHandle2);
  705. }
  706. const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(URI));
  707. CARLA_SAFE_ASSERT_CONTINUE(cPlugin != nullptr);
  708. Lilv::Plugin lilvPlugin(cPlugin);
  709. CARLA_SAFE_ASSERT_CONTINUE(lilvPlugin.get_uri().is_uri());
  710. print_cached_plugin(get_cached_plugin_lv2(lv2World, lilvPlugin));
  711. }
  712. }
  713. #endif // ! BUILD_BRIDGE
  714. // --------------------------------------------------------------------------------------------------------------------
  715. // VST2
  716. // Check if plugin is currently processing
  717. static bool gVstIsProcessing = false;
  718. // Check if plugin needs idle
  719. static bool gVstNeedsIdle = false;
  720. // Check if plugin wants midi
  721. static bool gVstWantsMidi = false;
  722. // Check if plugin wants time
  723. static bool gVstWantsTime = false;
  724. // Current uniqueId for VST shell plugins
  725. static intptr_t gVstCurrentUniqueId = 0;
  726. // Supported Carla features
  727. static intptr_t vstHostCanDo(const char* const feature)
  728. {
  729. carla_debug("vstHostCanDo(\"%s\")", feature);
  730. if (std::strcmp(feature, "supplyIdle") == 0)
  731. return 1;
  732. if (std::strcmp(feature, "sendVstEvents") == 0)
  733. return 1;
  734. if (std::strcmp(feature, "sendVstMidiEvent") == 0)
  735. return 1;
  736. if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  737. return 1;
  738. if (std::strcmp(feature, "sendVstTimeInfo") == 0)
  739. {
  740. gVstWantsTime = true;
  741. return 1;
  742. }
  743. if (std::strcmp(feature, "receiveVstEvents") == 0)
  744. return 1;
  745. if (std::strcmp(feature, "receiveVstMidiEvent") == 0)
  746. return 1;
  747. if (std::strcmp(feature, "receiveVstTimeInfo") == 0)
  748. return -1;
  749. if (std::strcmp(feature, "reportConnectionChanges") == 0)
  750. return -1;
  751. if (std::strcmp(feature, "acceptIOChanges") == 0)
  752. return 1;
  753. if (std::strcmp(feature, "sizeWindow") == 0)
  754. return 1;
  755. if (std::strcmp(feature, "offline") == 0)
  756. return -1;
  757. if (std::strcmp(feature, "openFileSelector") == 0)
  758. return -1;
  759. if (std::strcmp(feature, "closeFileSelector") == 0)
  760. return -1;
  761. if (std::strcmp(feature, "startStopProcess") == 0)
  762. return 1;
  763. if (std::strcmp(feature, "supportShell") == 0)
  764. return 1;
  765. if (std::strcmp(feature, "shellCategory") == 0)
  766. return 1;
  767. if (std::strcmp(feature, "NIMKPIVendorSpecificCallbacks") == 0)
  768. return -1;
  769. // non-official features found in some plugins:
  770. // "asyncProcessing"
  771. // "editFile"
  772. // unimplemented
  773. carla_stderr("vstHostCanDo(\"%s\") - unknown feature", feature);
  774. return 0;
  775. }
  776. // Host-side callback
  777. 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)
  778. {
  779. carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
  780. effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
  781. static VstTimeInfo timeInfo;
  782. intptr_t ret = 0;
  783. switch (opcode)
  784. {
  785. case audioMasterAutomate:
  786. ret = 1;
  787. break;
  788. case audioMasterVersion:
  789. ret = kVstVersion;
  790. break;
  791. case audioMasterCurrentId:
  792. ret = gVstCurrentUniqueId;
  793. break;
  794. case DECLARE_VST_DEPRECATED(audioMasterWantMidi):
  795. if (gVstWantsMidi) { DISCOVERY_OUT("warning", "Plugin requested MIDI more than once"); }
  796. gVstWantsMidi = true;
  797. ret = 1;
  798. break;
  799. case audioMasterGetTime:
  800. if (! gVstIsProcessing) { DISCOVERY_OUT("warning", "Plugin requested timeInfo out of process"); }
  801. if (! gVstWantsTime) { DISCOVERY_OUT("warning", "Plugin requested timeInfo but didn't ask if host could do \"sendVstTimeInfo\""); }
  802. carla_zeroStruct(timeInfo);
  803. timeInfo.sampleRate = kSampleRate;
  804. // Tempo
  805. timeInfo.tempo = 120.0;
  806. timeInfo.flags |= kVstTempoValid;
  807. // Time Signature
  808. timeInfo.timeSigNumerator = 4;
  809. timeInfo.timeSigDenominator = 4;
  810. timeInfo.flags |= kVstTimeSigValid;
  811. ret = (intptr_t)&timeInfo;
  812. break;
  813. case DECLARE_VST_DEPRECATED(audioMasterTempoAt):
  814. ret = 120 * 10000;
  815. break;
  816. case DECLARE_VST_DEPRECATED(audioMasterGetNumAutomatableParameters):
  817. ret = carla_minPositive(effect->numParams, static_cast<int>(MAX_DEFAULT_PARAMETERS));
  818. break;
  819. case DECLARE_VST_DEPRECATED(audioMasterGetParameterQuantization):
  820. ret = 1; // full single float precision
  821. break;
  822. case DECLARE_VST_DEPRECATED(audioMasterNeedIdle):
  823. if (gVstNeedsIdle) { DISCOVERY_OUT("warning", "Plugin requested idle more than once"); }
  824. gVstNeedsIdle = true;
  825. ret = 1;
  826. break;
  827. case audioMasterGetSampleRate:
  828. ret = kSampleRatei;
  829. break;
  830. case audioMasterGetBlockSize:
  831. ret = kBufferSize;
  832. break;
  833. case DECLARE_VST_DEPRECATED(audioMasterWillReplaceOrAccumulate):
  834. ret = 1; // replace
  835. break;
  836. case audioMasterGetCurrentProcessLevel:
  837. ret = gVstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
  838. break;
  839. case audioMasterGetAutomationState:
  840. ret = kVstAutomationOff;
  841. break;
  842. case audioMasterGetVendorString:
  843. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  844. std::strcpy((char*)ptr, "falkTX");
  845. ret = 1;
  846. break;
  847. case audioMasterGetProductString:
  848. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  849. std::strcpy((char*)ptr, "Carla-Discovery");
  850. ret = 1;
  851. break;
  852. case audioMasterGetVendorVersion:
  853. ret = CARLA_VERSION_HEX;
  854. break;
  855. case audioMasterCanDo:
  856. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  857. ret = vstHostCanDo((const char*)ptr);
  858. break;
  859. case audioMasterGetLanguage:
  860. ret = kVstLangEnglish;
  861. break;
  862. default:
  863. carla_stdout("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
  864. effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
  865. break;
  866. }
  867. return ret;
  868. }
  869. static bool do_vst2_check(lib_t& libHandle, const char* const filename, const bool doInit)
  870. {
  871. VST_Function vstFn = nullptr;
  872. #ifdef CARLA_OS_MAC
  873. BundleLoader bundleLoader;
  874. if (libHandle == nullptr)
  875. {
  876. if (! bundleLoader.load(filename))
  877. {
  878. #ifdef __aarch64__
  879. return true;
  880. #else
  881. DISCOVERY_OUT("error", "Failed to load VST2 bundle executable");
  882. return false;
  883. #endif
  884. }
  885. vstFn = bundleLoader.getSymbol<VST_Function>(CFSTR("main_macho"));
  886. if (vstFn == nullptr)
  887. vstFn = bundleLoader.getSymbol<VST_Function>(CFSTR("VSTPluginMain"));
  888. if (vstFn == nullptr)
  889. {
  890. DISCOVERY_OUT("error", "Not a VST2 plugin");
  891. return false;
  892. }
  893. }
  894. else
  895. #endif
  896. {
  897. vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain");
  898. if (vstFn == nullptr)
  899. {
  900. vstFn = lib_symbol<VST_Function>(libHandle, "main");
  901. if (vstFn == nullptr)
  902. {
  903. DISCOVERY_OUT("error", "Not a VST plugin");
  904. return false;
  905. }
  906. }
  907. }
  908. AEffect* effect = vstFn(vstHostCallback);
  909. if (effect == nullptr || effect->magic != kEffectMagic)
  910. {
  911. DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
  912. return false;
  913. }
  914. if (effect->uniqueID == 0)
  915. {
  916. DISCOVERY_OUT("warning", "Plugin doesn't have an Unique ID when first loaded");
  917. }
  918. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  919. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  920. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  921. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  922. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  923. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  924. if (effect->numPrograms > 0)
  925. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  926. const bool isShell = (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f) == kPlugCategShell);
  927. if (effect->uniqueID == 0 && !isShell)
  928. {
  929. DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID after being open");
  930. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  931. return false;
  932. }
  933. gVstCurrentUniqueId = effect->uniqueID;
  934. char strBuf[STR_MAX+1];
  935. CarlaString cName;
  936. CarlaString cProduct;
  937. CarlaString cVendor;
  938. PluginCategory category;
  939. LinkedList<intptr_t> uniqueIds;
  940. if (isShell)
  941. {
  942. for (;;)
  943. {
  944. carla_zeroChars(strBuf, STR_MAX+1);
  945. gVstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
  946. if (gVstCurrentUniqueId == 0)
  947. break;
  948. uniqueIds.append(gVstCurrentUniqueId);
  949. }
  950. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  951. effect = nullptr;
  952. }
  953. else
  954. {
  955. uniqueIds.append(gVstCurrentUniqueId);
  956. }
  957. for (LinkedList<intptr_t>::Itenerator it = uniqueIds.begin2(); it.valid(); it.next())
  958. {
  959. gVstCurrentUniqueId = it.getValue(0);
  960. if (effect == nullptr)
  961. {
  962. effect = vstFn(vstHostCallback);
  963. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  964. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  965. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  966. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  967. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  968. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  969. if (effect->numPrograms > 0)
  970. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  971. }
  972. // get name
  973. carla_zeroChars(strBuf, STR_MAX+1);
  974. if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
  975. cName = strBuf;
  976. else
  977. cName.clear();
  978. // get product
  979. carla_zeroChars(strBuf, STR_MAX+1);
  980. if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
  981. cProduct = strBuf;
  982. else
  983. cProduct.clear();
  984. // get vendor
  985. carla_zeroChars(strBuf, STR_MAX+1);
  986. if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
  987. cVendor = strBuf;
  988. else
  989. cVendor.clear();
  990. // get category
  991. switch (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f))
  992. {
  993. case kPlugCategSynth:
  994. category = PLUGIN_CATEGORY_SYNTH;
  995. break;
  996. case kPlugCategAnalysis:
  997. category = PLUGIN_CATEGORY_UTILITY;
  998. break;
  999. case kPlugCategMastering:
  1000. category = PLUGIN_CATEGORY_DYNAMICS;
  1001. break;
  1002. case kPlugCategRoomFx:
  1003. category = PLUGIN_CATEGORY_DELAY;
  1004. break;
  1005. case kPlugCategRestoration:
  1006. category = PLUGIN_CATEGORY_UTILITY;
  1007. break;
  1008. case kPlugCategGenerator:
  1009. category = PLUGIN_CATEGORY_SYNTH;
  1010. break;
  1011. default:
  1012. if (effect->flags & effFlagsIsSynth)
  1013. category = PLUGIN_CATEGORY_SYNTH;
  1014. else
  1015. category = PLUGIN_CATEGORY_NONE;
  1016. break;
  1017. }
  1018. // get everything else
  1019. uint hints = 0x0;
  1020. uint audioIns = static_cast<uint>(std::max(0, effect->numInputs));
  1021. uint audioOuts = static_cast<uint>(std::max(0, effect->numOutputs));
  1022. uint midiIns = 0;
  1023. uint midiOuts = 0;
  1024. uint parameters = static_cast<uint>(std::max(0, effect->numParams));
  1025. if (effect->flags & effFlagsHasEditor)
  1026. {
  1027. hints |= PLUGIN_HAS_CUSTOM_UI;
  1028. #ifndef BUILD_BRIDGE
  1029. hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
  1030. #endif
  1031. }
  1032. if (effect->flags & effFlagsIsSynth)
  1033. {
  1034. hints |= PLUGIN_IS_SYNTH;
  1035. midiIns = 1;
  1036. }
  1037. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) != 0)
  1038. midiIns = 1;
  1039. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  1040. midiOuts = 1;
  1041. CARLA_SAFE_ASSERT_CONTINUE(audioIns <= MAX_DISCOVERY_AUDIO_IO);
  1042. CARLA_SAFE_ASSERT_CONTINUE(audioOuts <= MAX_DISCOVERY_AUDIO_IO);
  1043. // -----------------------------------------------------------------------
  1044. // start crash-free plugin test
  1045. if (doInit)
  1046. {
  1047. if (gVstNeedsIdle)
  1048. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1049. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  1050. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  1051. if (gVstNeedsIdle)
  1052. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1053. // Plugin might call wantMidi() during resume
  1054. if (midiIns == 0 && gVstWantsMidi)
  1055. {
  1056. midiIns = 1;
  1057. }
  1058. float* bufferAudioIn[MAX_DISCOVERY_AUDIO_IO];
  1059. float* bufferAudioOut[MAX_DISCOVERY_AUDIO_IO];
  1060. if (audioIns == 0)
  1061. {
  1062. bufferAudioIn[0] = nullptr;
  1063. }
  1064. else
  1065. {
  1066. for (uint j=0; j < audioIns; ++j)
  1067. {
  1068. bufferAudioIn[j] = new float[kBufferSize];
  1069. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  1070. }
  1071. }
  1072. if (audioOuts == 0)
  1073. {
  1074. bufferAudioOut[0] = nullptr;
  1075. }
  1076. else
  1077. {
  1078. for (uint j=0; j < audioOuts; ++j)
  1079. {
  1080. bufferAudioOut[j] = new float[kBufferSize];
  1081. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  1082. }
  1083. }
  1084. struct VstEventsFixed {
  1085. int32_t numEvents;
  1086. intptr_t reserved;
  1087. VstEvent* data[2];
  1088. VstEventsFixed()
  1089. : numEvents(0),
  1090. reserved(0)
  1091. {
  1092. data[0] = data[1] = nullptr;
  1093. }
  1094. } events;
  1095. VstMidiEvent midiEvents[2];
  1096. carla_zeroStructs(midiEvents, 2);
  1097. midiEvents[0].type = kVstMidiType;
  1098. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  1099. midiEvents[0].midiData[0] = char(MIDI_STATUS_NOTE_ON);
  1100. midiEvents[0].midiData[1] = 64;
  1101. midiEvents[0].midiData[2] = 100;
  1102. midiEvents[1].type = kVstMidiType;
  1103. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  1104. midiEvents[1].midiData[0] = char(MIDI_STATUS_NOTE_OFF);
  1105. midiEvents[1].midiData[1] = 64;
  1106. midiEvents[1].deltaFrames = kBufferSize/2;
  1107. events.numEvents = 2;
  1108. events.data[0] = (VstEvent*)&midiEvents[0];
  1109. events.data[1] = (VstEvent*)&midiEvents[1];
  1110. // processing
  1111. gVstIsProcessing = true;
  1112. if (midiIns > 0)
  1113. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  1114. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != nullptr && effect->processReplacing != effect->DECLARE_VST_DEPRECATED(process))
  1115. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1116. else if (effect->DECLARE_VST_DEPRECATED(process) != nullptr)
  1117. effect->DECLARE_VST_DEPRECATED(process)(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1118. else
  1119. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  1120. gVstIsProcessing = false;
  1121. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  1122. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  1123. if (gVstNeedsIdle)
  1124. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1125. for (uint j=0; j < audioIns; ++j)
  1126. delete[] bufferAudioIn[j];
  1127. for (uint j=0; j < audioOuts; ++j)
  1128. delete[] bufferAudioOut[j];
  1129. }
  1130. // end crash-free plugin test
  1131. // -----------------------------------------------------------------------
  1132. DISCOVERY_OUT("init", "------------");
  1133. DISCOVERY_OUT("build", BINARY_NATIVE);
  1134. DISCOVERY_OUT("hints", hints);
  1135. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  1136. DISCOVERY_OUT("name", cName.buffer());
  1137. DISCOVERY_OUT("label", cProduct.buffer());
  1138. DISCOVERY_OUT("maker", cVendor.buffer());
  1139. DISCOVERY_OUT("uniqueId", gVstCurrentUniqueId);
  1140. DISCOVERY_OUT("audio.ins", audioIns);
  1141. DISCOVERY_OUT("audio.outs", audioOuts);
  1142. DISCOVERY_OUT("midi.ins", midiIns);
  1143. DISCOVERY_OUT("midi.outs", midiOuts);
  1144. DISCOVERY_OUT("parameters.ins", parameters);
  1145. DISCOVERY_OUT("end", "------------");
  1146. gVstWantsMidi = false;
  1147. gVstWantsTime = false;
  1148. if (! isShell)
  1149. break;
  1150. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1151. effect = nullptr;
  1152. }
  1153. uniqueIds.clear();
  1154. if (effect != nullptr)
  1155. {
  1156. if (gVstNeedsIdle)
  1157. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1158. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1159. }
  1160. return false;
  1161. #ifndef CARLA_OS_MAC
  1162. // unused
  1163. (void)filename;
  1164. #endif
  1165. }
  1166. // --------------------------------------------------------------------------------------------------------------------
  1167. // VST3
  1168. struct carla_v3_host_application : v3_host_application_cpp {
  1169. carla_v3_host_application()
  1170. {
  1171. query_interface = v3_query_interface_static<v3_host_application_iid>;
  1172. ref = v3_ref_static;
  1173. unref = v3_unref_static;
  1174. app.get_name = carla_get_name;
  1175. app.create_instance = carla_create_instance;
  1176. }
  1177. private:
  1178. static v3_result V3_API carla_get_name(void*, v3_str_128 name)
  1179. {
  1180. static constexpr const char hostname[] = "Carla-Discovery\0";
  1181. for (size_t i=0; i<sizeof(hostname); ++i)
  1182. name[i] = hostname[i];
  1183. return V3_OK;
  1184. }
  1185. static v3_result V3_API carla_create_instance(void*, v3_tuid, v3_tuid, void**)
  1186. {
  1187. return V3_NOT_IMPLEMENTED;
  1188. }
  1189. CARLA_DECLARE_NON_COPYABLE(carla_v3_host_application)
  1190. CARLA_PREVENT_HEAP_ALLOCATION
  1191. };
  1192. struct carla_v3_param_value_queue : v3_param_value_queue_cpp {
  1193. carla_v3_param_value_queue()
  1194. {
  1195. query_interface = v3_query_interface_static<v3_param_value_queue_iid>;
  1196. ref = v3_ref_static;
  1197. unref = v3_unref_static;
  1198. queue.get_param_id = carla_get_param_id;
  1199. queue.get_point_count = carla_get_point_count;
  1200. queue.get_point = carla_get_point;
  1201. queue.add_point = carla_add_point;
  1202. }
  1203. private:
  1204. static v3_param_id V3_API carla_get_param_id(void*) { return 0; }
  1205. static int32_t V3_API carla_get_point_count(void*) { return 0; }
  1206. static v3_result V3_API carla_get_point(void*, int32_t, int32_t*, double*) { return V3_NOT_IMPLEMENTED; }
  1207. static v3_result V3_API carla_add_point(void*, int32_t, double, int32_t*) { return V3_NOT_IMPLEMENTED; }
  1208. CARLA_DECLARE_NON_COPYABLE(carla_v3_param_value_queue)
  1209. CARLA_PREVENT_HEAP_ALLOCATION
  1210. };
  1211. struct carla_v3_param_changes : v3_param_changes_cpp {
  1212. carla_v3_param_changes()
  1213. {
  1214. query_interface = v3_query_interface_static<v3_param_changes_iid>;
  1215. ref = v3_ref_static;
  1216. unref = v3_unref_static;
  1217. changes.get_param_count = carla_get_param_count;
  1218. changes.get_param_data = carla_get_param_data;
  1219. changes.add_param_data = carla_add_param_data;
  1220. }
  1221. private:
  1222. static int32_t V3_API carla_get_param_count(void*) { return 0; }
  1223. static v3_param_value_queue** V3_API carla_get_param_data(void*, int32_t) { return nullptr; }
  1224. static v3_param_value_queue** V3_API carla_add_param_data(void*, const v3_param_id*, int32_t*) { return nullptr; }
  1225. CARLA_DECLARE_NON_COPYABLE(carla_v3_param_changes)
  1226. CARLA_PREVENT_HEAP_ALLOCATION
  1227. };
  1228. struct carla_v3_event_list : v3_event_list_cpp {
  1229. carla_v3_event_list()
  1230. {
  1231. query_interface = v3_query_interface_static<v3_event_list_iid>;
  1232. ref = v3_ref_static;
  1233. unref = v3_unref_static;
  1234. list.get_event_count = carla_get_event_count;
  1235. list.get_event = carla_get_event;
  1236. list.add_event = carla_add_event;
  1237. }
  1238. private:
  1239. static uint32_t V3_API carla_get_event_count(void*) { return 0; }
  1240. static v3_result V3_API carla_get_event(void*, int32_t, v3_event*) { return V3_NOT_IMPLEMENTED; }
  1241. static v3_result V3_API carla_add_event(void*, v3_event*) { return V3_NOT_IMPLEMENTED; }
  1242. CARLA_DECLARE_NON_COPYABLE(carla_v3_event_list)
  1243. CARLA_PREVENT_HEAP_ALLOCATION
  1244. };
  1245. static bool v3_exit_false(const V3_EXITFN v3_exit)
  1246. {
  1247. v3_exit();
  1248. return false;
  1249. }
  1250. static bool do_vst3_check(lib_t& libHandle, const char* const filename, const bool doInit)
  1251. {
  1252. V3_ENTRYFN v3_entry = nullptr;
  1253. V3_EXITFN v3_exit = nullptr;
  1254. V3_GETFN v3_get = nullptr;
  1255. #ifdef CARLA_OS_MAC
  1256. BundleLoader bundleLoader;
  1257. #endif
  1258. // if passed filename is not a plugin binary directly, inspect bundle and find one
  1259. if (libHandle == nullptr)
  1260. {
  1261. #ifdef CARLA_OS_MAC
  1262. if (! bundleLoader.load(filename))
  1263. {
  1264. #ifdef __aarch64__
  1265. return true;
  1266. #else
  1267. DISCOVERY_OUT("error", "Failed to load VST3 bundle executable");
  1268. return false;
  1269. #endif
  1270. }
  1271. v3_entry = bundleLoader.getSymbol<V3_ENTRYFN>(CFSTR(V3_ENTRYFNNAME));
  1272. v3_exit = bundleLoader.getSymbol<V3_EXITFN>(CFSTR(V3_EXITFNNAME));
  1273. v3_get = bundleLoader.getSymbol<V3_GETFN>(CFSTR(V3_GETFNNAME));
  1274. #else
  1275. water::String binaryfilename = filename;
  1276. if (!binaryfilename.endsWithChar(CARLA_OS_SEP))
  1277. binaryfilename += CARLA_OS_SEP_STR;
  1278. binaryfilename += "Contents" CARLA_OS_SEP_STR V3_CONTENT_DIR CARLA_OS_SEP_STR;
  1279. binaryfilename += water::File(filename).getFileNameWithoutExtension();
  1280. #ifdef CARLA_OS_WIN
  1281. binaryfilename += ".vst3";
  1282. #else
  1283. binaryfilename += ".so";
  1284. #endif
  1285. if (! water::File(binaryfilename.toRawUTF8()).existsAsFile())
  1286. {
  1287. DISCOVERY_OUT("error", "Failed to find a suitable VST3 bundle binary");
  1288. return false;
  1289. }
  1290. libHandle = lib_open(binaryfilename.toRawUTF8());
  1291. if (libHandle == nullptr)
  1292. {
  1293. print_lib_error(filename);
  1294. return false;
  1295. }
  1296. #endif
  1297. }
  1298. #ifndef CARLA_OS_MAC
  1299. v3_entry = lib_symbol<V3_ENTRYFN>(libHandle, V3_ENTRYFNNAME);
  1300. v3_exit = lib_symbol<V3_EXITFN>(libHandle, V3_EXITFNNAME);
  1301. v3_get = lib_symbol<V3_GETFN>(libHandle, V3_GETFNNAME);
  1302. #endif
  1303. // ensure entry and exit points are available
  1304. if (v3_entry == nullptr || v3_exit == nullptr || v3_get == nullptr)
  1305. {
  1306. DISCOVERY_OUT("error", "Not a VST3 plugin");
  1307. return false;
  1308. }
  1309. // call entry point
  1310. #if defined(CARLA_OS_MAC)
  1311. v3_entry(bundleLoader.getRef());
  1312. #elif defined(CARLA_OS_WIN)
  1313. v3_entry();
  1314. #else
  1315. v3_entry(libHandle);
  1316. #endif
  1317. carla_v3_host_application hostApplication;
  1318. carla_v3_host_application* hostApplicationPtr = &hostApplication;
  1319. v3_funknown** const hostContext = (v3_funknown**)&hostApplicationPtr;
  1320. // fetch initial factory
  1321. v3_plugin_factory** factory1 = v3_get();
  1322. CARLA_SAFE_ASSERT_RETURN(factory1 != nullptr, v3_exit_false(v3_exit));
  1323. // get factory info
  1324. v3_factory_info factoryInfo = {};
  1325. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->get_factory_info(factory1, &factoryInfo) == V3_OK,
  1326. v3_exit_false(v3_exit));
  1327. // get num classes
  1328. const int32_t numClasses = v3_cpp_obj(factory1)->num_classes(factory1);
  1329. CARLA_SAFE_ASSERT_RETURN(numClasses > 0, v3_exit_false(v3_exit));
  1330. // query 2nd factory
  1331. v3_plugin_factory_2** factory2 = nullptr;
  1332. if (v3_cpp_obj_query_interface(factory1, v3_plugin_factory_2_iid, &factory2) == V3_OK)
  1333. {
  1334. CARLA_SAFE_ASSERT_RETURN(factory2 != nullptr, v3_exit_false(v3_exit));
  1335. }
  1336. else
  1337. {
  1338. CARLA_SAFE_ASSERT(factory2 == nullptr);
  1339. factory2 = nullptr;
  1340. }
  1341. // query 3rd factory
  1342. v3_plugin_factory_3** factory3 = nullptr;
  1343. if (factory2 != nullptr && v3_cpp_obj_query_interface(factory2, v3_plugin_factory_3_iid, &factory3) == V3_OK)
  1344. {
  1345. CARLA_SAFE_ASSERT_RETURN(factory3 != nullptr, v3_exit_false(v3_exit));
  1346. }
  1347. else
  1348. {
  1349. CARLA_SAFE_ASSERT(factory3 == nullptr);
  1350. factory3 = nullptr;
  1351. }
  1352. // set host context (application) if 3rd factory provided
  1353. if (factory3 != nullptr)
  1354. v3_cpp_obj(factory3)->set_host_context(factory3, hostContext);
  1355. // go through all relevant classes
  1356. for (int32_t i=0; i<numClasses; ++i)
  1357. {
  1358. v3_result res;
  1359. // v3_class_info_2 is ABI compatible with v3_class_info
  1360. union {
  1361. v3_class_info v1;
  1362. v3_class_info_2 v2;
  1363. } classInfo = {};
  1364. if (factory2 != nullptr)
  1365. v3_cpp_obj(factory2)->get_class_info_2(factory2, i, &classInfo.v2);
  1366. else
  1367. v3_cpp_obj(factory1)->get_class_info(factory1, i, &classInfo.v1);
  1368. // safety check
  1369. CARLA_SAFE_ASSERT_CONTINUE(classInfo.v1.cardinality == 0x7FFFFFFF);
  1370. // only check for audio plugins
  1371. if (std::strcmp(classInfo.v1.category, "Audio Module Class") != 0)
  1372. continue;
  1373. // create instance
  1374. void* instance = nullptr;
  1375. res = v3_cpp_obj(factory1)->create_instance(factory1, classInfo.v1.class_id, v3_component_iid, &instance);
  1376. CARLA_SAFE_ASSERT_INT_CONTINUE(res == V3_OK, res);
  1377. CARLA_SAFE_ASSERT_CONTINUE(instance != nullptr);
  1378. // initialize instance
  1379. v3_component** const component = static_cast<v3_component**>(instance);
  1380. res = v3_cpp_obj_initialize(component, hostContext);
  1381. CARLA_SAFE_ASSERT_INT_CONTINUE(res == V3_OK, res);
  1382. // create edit controller
  1383. v3_edit_controller** controller = nullptr;
  1384. bool shouldTerminateController;
  1385. if (v3_cpp_obj_query_interface(component, v3_edit_controller_iid, &controller) != V3_OK)
  1386. controller = nullptr;
  1387. if (controller != nullptr)
  1388. {
  1389. // got edit controller from casting component, assume they belong to the same object
  1390. shouldTerminateController = false;
  1391. }
  1392. else
  1393. {
  1394. // try to create edit controller from factory
  1395. v3_tuid uid = {};
  1396. if (v3_cpp_obj(component)->get_controller_class_id(component, uid) == V3_OK)
  1397. {
  1398. instance = nullptr;
  1399. if (v3_cpp_obj(factory1)->create_instance(factory1, uid, v3_edit_controller_iid, &instance) == V3_OK)
  1400. controller = static_cast<v3_edit_controller**>(instance);
  1401. }
  1402. if (controller == nullptr)
  1403. {
  1404. DISCOVERY_OUT("warning", "Plugin '" << classInfo.v1.name << "' does not have an edit controller");
  1405. v3_cpp_obj_terminate(component);
  1406. v3_cpp_obj_unref(component);
  1407. continue;
  1408. }
  1409. // component is separate from controller, needs its dedicated initialize and terminate
  1410. shouldTerminateController = true;
  1411. v3_cpp_obj_initialize(controller, hostContext);
  1412. }
  1413. // connect component to controller
  1414. v3_connection_point** connComponent = nullptr;
  1415. if (v3_cpp_obj_query_interface(component, v3_connection_point_iid, &connComponent) != V3_OK)
  1416. connComponent = nullptr;
  1417. v3_connection_point** connController = nullptr;
  1418. if (v3_cpp_obj_query_interface(controller, v3_connection_point_iid, &connController) != V3_OK)
  1419. connController = nullptr;
  1420. if (connComponent != nullptr && connController != nullptr)
  1421. {
  1422. v3_cpp_obj(connComponent)->connect(connComponent, connController);
  1423. v3_cpp_obj(connController)->connect(connController, connComponent);
  1424. }
  1425. // fill in all the details
  1426. uint hints = 0x0;
  1427. int audioIns = 0;
  1428. int audioOuts = 0;
  1429. int cvIns = 0;
  1430. int cvOuts = 0;
  1431. int parameterIns = 0;
  1432. int parameterOuts = 0;
  1433. const int32_t numAudioInputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_AUDIO, V3_INPUT);
  1434. const int32_t numEventInputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_EVENT, V3_INPUT);
  1435. const int32_t numAudioOutputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_AUDIO, V3_OUTPUT);
  1436. const int32_t numEventOutputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_EVENT, V3_OUTPUT);
  1437. const int32_t numParameters = v3_cpp_obj(controller)->get_parameter_count(controller);
  1438. CARLA_SAFE_ASSERT(numAudioInputBuses >= 0);
  1439. CARLA_SAFE_ASSERT(numEventInputBuses >= 0);
  1440. CARLA_SAFE_ASSERT(numAudioOutputBuses >= 0);
  1441. CARLA_SAFE_ASSERT(numEventOutputBuses >= 0);
  1442. CARLA_SAFE_ASSERT(numParameters >= 0);
  1443. for (int32_t b=0; b<numAudioInputBuses; ++b)
  1444. {
  1445. v3_bus_info busInfo = {};
  1446. res = v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_INPUT, b, &busInfo);
  1447. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1448. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1449. cvIns += busInfo.channel_count;
  1450. else
  1451. audioIns += busInfo.channel_count;
  1452. }
  1453. for (int32_t b=0; b<numAudioOutputBuses; ++b)
  1454. {
  1455. v3_bus_info busInfo = {};
  1456. res = v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_OUTPUT, b, &busInfo);
  1457. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1458. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1459. cvOuts += busInfo.channel_count;
  1460. else
  1461. audioOuts += busInfo.channel_count;
  1462. }
  1463. for (int32_t p=0; p<numParameters; ++p)
  1464. {
  1465. v3_param_info paramInfo = {};
  1466. res = v3_cpp_obj(controller)->get_parameter_info(controller, p, &paramInfo);
  1467. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1468. if (paramInfo.flags & (V3_PARAM_IS_BYPASS|V3_PARAM_IS_HIDDEN|V3_PARAM_PROGRAM_CHANGE))
  1469. continue;
  1470. if (paramInfo.flags & V3_PARAM_READ_ONLY)
  1471. ++parameterOuts;
  1472. else
  1473. ++parameterIns;
  1474. }
  1475. CARLA_SAFE_ASSERT_CONTINUE(audioIns <= MAX_DISCOVERY_AUDIO_IO);
  1476. CARLA_SAFE_ASSERT_CONTINUE(audioOuts <= MAX_DISCOVERY_AUDIO_IO);
  1477. CARLA_SAFE_ASSERT_CONTINUE(cvIns <= MAX_DISCOVERY_CV_IO);
  1478. CARLA_SAFE_ASSERT_CONTINUE(cvOuts <= MAX_DISCOVERY_CV_IO);
  1479. #ifdef V3_VIEW_PLATFORM_TYPE_NATIVE
  1480. if (v3_plugin_view** const view = v3_cpp_obj(controller)->create_view(controller, "editor"))
  1481. {
  1482. if (v3_cpp_obj(view)->is_platform_type_supported(view, V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_TRUE)
  1483. {
  1484. hints |= PLUGIN_HAS_CUSTOM_UI;
  1485. #ifndef BUILD_BRIDGE
  1486. hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
  1487. #endif
  1488. }
  1489. v3_cpp_obj_unref(view);
  1490. }
  1491. #endif
  1492. if (factory2 != nullptr && std::strstr(classInfo.v2.sub_categories, "Instrument") != nullptr)
  1493. hints |= PLUGIN_IS_SYNTH;
  1494. if (doInit)
  1495. {
  1496. v3_audio_processor** processor = nullptr;
  1497. v3_process_setup setup = { V3_REALTIME, V3_SAMPLE_32, kBufferSize, kSampleRate };
  1498. res = v3_cpp_obj_query_interface(component, v3_audio_processor_iid, &processor);
  1499. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1500. CARLA_SAFE_ASSERT_BREAK(processor != nullptr);
  1501. res = v3_cpp_obj(processor)->can_process_sample_size(processor, V3_SAMPLE_32);
  1502. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1503. res = v3_cpp_obj(component)->set_active(component, true);
  1504. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1505. res = v3_cpp_obj(processor)->setup_processing(processor, &setup);
  1506. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1507. res = v3_cpp_obj(component)->set_active(component, false);
  1508. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1509. v3_audio_bus_buffers* const inputsBuffers = numAudioInputBuses > 0
  1510. ? new v3_audio_bus_buffers[numAudioInputBuses]
  1511. : nullptr;
  1512. v3_audio_bus_buffers* const outputsBuffers = numAudioOutputBuses > 0
  1513. ? new v3_audio_bus_buffers[numAudioOutputBuses]
  1514. : nullptr;
  1515. for (int32_t b=0; b<numAudioInputBuses; ++b)
  1516. {
  1517. v3_bus_info busInfo = {};
  1518. carla_zeroStruct(inputsBuffers[b]);
  1519. res = v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_INPUT, b, &busInfo);
  1520. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1521. res = v3_cpp_obj(component)->activate_bus(component, V3_AUDIO, V3_INPUT, b, true);
  1522. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1523. inputsBuffers[b].num_channels = busInfo.channel_count;
  1524. }
  1525. for (int32_t b=0; b<numAudioOutputBuses; ++b)
  1526. {
  1527. v3_bus_info busInfo = {};
  1528. carla_zeroStruct(outputsBuffers[b]);
  1529. res = v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_OUTPUT, b, &busInfo);
  1530. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1531. res = v3_cpp_obj(component)->activate_bus(component, V3_AUDIO, V3_OUTPUT, b, true);
  1532. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1533. outputsBuffers[b].num_channels = busInfo.channel_count;
  1534. }
  1535. res = v3_cpp_obj(component)->set_active(component, true);
  1536. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1537. res = v3_cpp_obj(processor)->set_processing(processor, true);
  1538. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK || res == V3_NOT_IMPLEMENTED, res);
  1539. float* bufferAudioIn[MAX_DISCOVERY_AUDIO_IO + MAX_DISCOVERY_CV_IO];
  1540. float* bufferAudioOut[MAX_DISCOVERY_AUDIO_IO + MAX_DISCOVERY_CV_IO];
  1541. for (int j=0; j < audioIns + cvIns; ++j)
  1542. {
  1543. bufferAudioIn[j] = new float[kBufferSize];
  1544. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  1545. }
  1546. for (int j=0; j < audioOuts + cvOuts; ++j)
  1547. {
  1548. bufferAudioOut[j] = new float[kBufferSize];
  1549. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  1550. }
  1551. for (int32_t b = 0, j = 0; b < numAudioInputBuses; ++b)
  1552. {
  1553. inputsBuffers[b].channel_buffers_32 = bufferAudioIn + j;
  1554. j += inputsBuffers[b].num_channels;
  1555. }
  1556. for (int32_t b = 0, j = 0; b < numAudioOutputBuses; ++b)
  1557. {
  1558. outputsBuffers[b].channel_buffers_32 = bufferAudioOut + j;
  1559. j += outputsBuffers[b].num_channels;
  1560. }
  1561. carla_v3_event_list eventList;
  1562. carla_v3_event_list* eventListPtr = &eventList;
  1563. carla_v3_param_changes paramChanges;
  1564. carla_v3_param_changes* paramChangesPtr = &paramChanges;
  1565. v3_process_context processContext = {};
  1566. processContext.sample_rate = kSampleRate;
  1567. v3_process_data processData = {
  1568. V3_REALTIME,
  1569. V3_SAMPLE_32,
  1570. kBufferSize,
  1571. numAudioInputBuses,
  1572. numAudioOutputBuses,
  1573. inputsBuffers,
  1574. outputsBuffers,
  1575. (v3_param_changes**)&paramChangesPtr,
  1576. (v3_param_changes**)&paramChangesPtr,
  1577. (v3_event_list**)&eventListPtr,
  1578. (v3_event_list**)&eventListPtr,
  1579. &processContext
  1580. };
  1581. res = v3_cpp_obj(processor)->process(processor, &processData);
  1582. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1583. delete[] inputsBuffers;
  1584. delete[] outputsBuffers;
  1585. for (int j=0; j < audioIns + cvIns; ++j)
  1586. delete[] bufferAudioIn[j];
  1587. for (int j=0; j < audioOuts + cvOuts; ++j)
  1588. delete[] bufferAudioOut[j];
  1589. res = v3_cpp_obj(processor)->set_processing(processor, false);
  1590. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK || res == V3_NOT_IMPLEMENTED, res);
  1591. res = v3_cpp_obj(component)->set_active(component, false);
  1592. CARLA_SAFE_ASSERT_INT_BREAK(res == V3_OK, res);
  1593. v3_cpp_obj_unref(processor);
  1594. }
  1595. // disconnect and unref connection points
  1596. if (connComponent != nullptr && connController != nullptr)
  1597. {
  1598. v3_cpp_obj(connComponent)->disconnect(connComponent, connController);
  1599. v3_cpp_obj(connController)->disconnect(connController, connComponent);
  1600. }
  1601. if (connComponent != nullptr)
  1602. v3_cpp_obj_unref(connComponent);
  1603. if (connController != nullptr)
  1604. v3_cpp_obj_unref(connController);
  1605. if (shouldTerminateController)
  1606. v3_cpp_obj_terminate(controller);
  1607. v3_cpp_obj_unref(controller);
  1608. v3_cpp_obj_terminate(component);
  1609. v3_cpp_obj_unref(component);
  1610. DISCOVERY_OUT("init", "------------");
  1611. DISCOVERY_OUT("build", BINARY_NATIVE);
  1612. DISCOVERY_OUT("hints", hints);
  1613. DISCOVERY_OUT("category", getPluginCategoryAsString(factory2 != nullptr ? getPluginCategoryFromV3SubCategories(classInfo.v2.sub_categories)
  1614. : getPluginCategoryFromName(classInfo.v1.name)));
  1615. DISCOVERY_OUT("name", classInfo.v1.name);
  1616. DISCOVERY_OUT("label", tuid2str(classInfo.v1.class_id));
  1617. DISCOVERY_OUT("maker", (factory2 != nullptr ? classInfo.v2.vendor : factoryInfo.vendor));
  1618. DISCOVERY_OUT("audio.ins", audioIns);
  1619. DISCOVERY_OUT("audio.outs", audioOuts);
  1620. DISCOVERY_OUT("cv.ins", cvIns);
  1621. DISCOVERY_OUT("cv.outs", cvOuts);
  1622. DISCOVERY_OUT("midi.ins", numEventInputBuses);
  1623. DISCOVERY_OUT("midi.outs", numEventOutputBuses);
  1624. DISCOVERY_OUT("parameters.ins", parameterIns);
  1625. DISCOVERY_OUT("parameters.outs", parameterOuts);
  1626. DISCOVERY_OUT("end", "------------");
  1627. }
  1628. // unref interfaces
  1629. if (factory3 != nullptr)
  1630. v3_cpp_obj_unref(factory3);
  1631. if (factory2 != nullptr)
  1632. v3_cpp_obj_unref(factory2);
  1633. v3_cpp_obj_unref(factory1);
  1634. v3_exit();
  1635. return false;
  1636. }
  1637. // --------------------------------------------------------------------------------------------------------------------
  1638. // AU
  1639. #ifdef CARLA_OS_MAC
  1640. typedef AudioComponentPlugInInterface* (*FactoryFn)(const AudioComponentDescription*);
  1641. typedef OSStatus (*InitializeFn)(void*);
  1642. typedef OSStatus (*UninitializeFn)(void*);
  1643. typedef OSStatus (*GetPropertyInfoFn)(void*, AudioUnitPropertyID, AudioUnitScope, AudioUnitElement, UInt32*, Boolean*);
  1644. typedef OSStatus (*GetPropertyFn)(void*, AudioUnitPropertyID, AudioUnitScope, AudioUnitElement, void*, UInt32*);
  1645. typedef OSStatus (*MIDIEventFn)(void*, UInt32, UInt32, UInt32, UInt32);
  1646. static constexpr FourCharCode getFourCharCodeFromString(const char str[4])
  1647. {
  1648. return (str[0] << 24) + (str[1] << 16) + (str[2] << 8) + str[3];
  1649. }
  1650. static bool do_au_check(const char* const filename, const bool doInit)
  1651. {
  1652. BundleLoader bundleLoader;
  1653. if (! bundleLoader.load(filename))
  1654. {
  1655. #ifdef __aarch64__
  1656. return true;
  1657. #else
  1658. DISCOVERY_OUT("error", "Failed to load AU bundle executable");
  1659. return false;
  1660. #endif
  1661. }
  1662. const CFTypeRef componentsRef = CFBundleGetValueForInfoDictionaryKey(bundleLoader.getRef(), CFSTR("AudioComponents"));
  1663. if (componentsRef == nullptr || CFGetTypeID(componentsRef) != CFArrayGetTypeID())
  1664. {
  1665. DISCOVERY_OUT("error", "Not an AU component");
  1666. return false;
  1667. }
  1668. const CFArrayRef components = static_cast<CFArrayRef>(componentsRef);
  1669. for (uint32_t c = 0, count = CFArrayGetCount(components); c < count; ++c)
  1670. {
  1671. const CFTypeRef componentRef = CFArrayGetValueAtIndex(components, c);
  1672. CARLA_SAFE_ASSERT_CONTINUE(componentRef != nullptr);
  1673. CARLA_SAFE_ASSERT_CONTINUE(CFGetTypeID(componentRef) == CFDictionaryGetTypeID());
  1674. const CFDictionaryRef component = static_cast<CFDictionaryRef>(componentRef);
  1675. CFStringRef componentName = nullptr;
  1676. CARLA_SAFE_ASSERT_CONTINUE(CFDictionaryGetValueIfPresent(component, CFSTR("name"), (const void **)&componentName));
  1677. CFStringRef componentFactoryFunction = nullptr;
  1678. CARLA_SAFE_ASSERT_CONTINUE(CFDictionaryGetValueIfPresent(component, CFSTR("factoryFunction"), (const void **)&componentFactoryFunction));
  1679. CFStringRef componentType = nullptr;
  1680. CARLA_SAFE_ASSERT_CONTINUE(CFDictionaryGetValueIfPresent(component, CFSTR("type"), (const void **)&componentType));
  1681. CARLA_SAFE_ASSERT_CONTINUE(CFStringGetLength(componentType) == 4);
  1682. CFStringRef componentSubType = nullptr;
  1683. CARLA_SAFE_ASSERT_CONTINUE(CFDictionaryGetValueIfPresent(component, CFSTR("subtype"), (const void **)&componentSubType));
  1684. CARLA_SAFE_ASSERT_CONTINUE(CFStringGetLength(componentSubType) == 4);
  1685. CFStringRef componentManufacturer = nullptr;
  1686. CARLA_SAFE_ASSERT_CONTINUE(CFDictionaryGetValueIfPresent(component, CFSTR("manufacturer"), (const void **)&componentManufacturer));
  1687. CARLA_SAFE_ASSERT_CONTINUE(CFStringGetLength(componentManufacturer) == 4);
  1688. const FactoryFn factoryFn = bundleLoader.getSymbol<FactoryFn>(componentFactoryFunction);
  1689. CARLA_SAFE_ASSERT_CONTINUE(factoryFn != nullptr);
  1690. char label[15] = {};
  1691. CFStringGetCString(componentType, label, 5, kCFStringEncodingASCII);
  1692. CFStringGetCString(componentSubType, label + 5, 5, kCFStringEncodingASCII);
  1693. CFStringGetCString(componentManufacturer, label + 10, 5, kCFStringEncodingASCII);
  1694. const AudioComponentDescription desc = {
  1695. getFourCharCodeFromString(label),
  1696. getFourCharCodeFromString(label + 5),
  1697. getFourCharCodeFromString(label + 10),
  1698. 0, 0
  1699. };
  1700. CARLA_SAFE_ASSERT_CONTINUE(desc.componentType != 0);
  1701. CARLA_SAFE_ASSERT_CONTINUE(desc.componentSubType != 0);
  1702. CARLA_SAFE_ASSERT_CONTINUE(desc.componentManufacturer != 0);
  1703. label[4] = label[9] = ',';
  1704. AudioComponentPlugInInterface* const interface = factoryFn(&desc);
  1705. CARLA_SAFE_ASSERT_CONTINUE(interface != nullptr);
  1706. const InitializeFn auInitialize = (InitializeFn)interface->Lookup(kAudioUnitInitializeSelect);
  1707. const UninitializeFn auUninitialize = (UninitializeFn)interface->Lookup(kAudioUnitUninitializeSelect);
  1708. const GetPropertyInfoFn auGetPropertyInfo = (GetPropertyInfoFn)interface->Lookup(kAudioUnitGetPropertyInfoSelect);
  1709. const GetPropertyFn auGetProperty = (GetPropertyFn)interface->Lookup(kAudioUnitGetPropertySelect);
  1710. const MIDIEventFn auMIDIEvent = (MIDIEventFn)interface->Lookup(kMusicDeviceMIDIEventSelect);
  1711. if (auInitialize == nullptr || auUninitialize == nullptr)
  1712. continue;
  1713. if (auGetPropertyInfo == nullptr || auGetProperty == nullptr)
  1714. continue;
  1715. if (interface->Open(interface, (AudioUnit)(void*)0x1) == noErr)
  1716. {
  1717. uint hints = 0x0;
  1718. uint audioIns = 0;
  1719. uint audioOuts = 0;
  1720. uint midiIns = 0;
  1721. uint midiOuts = 0;
  1722. uint parametersIns = 0;
  1723. uint parametersOuts = 0;
  1724. PluginCategory category;
  1725. switch (desc.componentType)
  1726. {
  1727. case kAudioUnitType_Effect:
  1728. case kAudioUnitType_MusicEffect:
  1729. category = PLUGIN_CATEGORY_NONE;
  1730. break;
  1731. case kAudioUnitType_Generator:
  1732. case kAudioUnitType_MusicDevice:
  1733. category = PLUGIN_CATEGORY_SYNTH;
  1734. break;
  1735. case kAudioUnitType_MIDIProcessor:
  1736. case kAudioUnitType_Mixer:
  1737. case kAudioUnitType_Panner:
  1738. case kAudioUnitType_SpeechSynthesizer:
  1739. category = PLUGIN_CATEGORY_UTILITY;
  1740. break;
  1741. case kAudioUnitType_FormatConverter:
  1742. case kAudioUnitType_OfflineEffect:
  1743. case kAudioUnitType_Output:
  1744. category = PLUGIN_CATEGORY_OTHER;
  1745. break;
  1746. default:
  1747. category = PLUGIN_CATEGORY_NONE;
  1748. break;
  1749. }
  1750. UInt32 outDataSize;
  1751. Boolean outWritable = false;
  1752. // audio port count
  1753. outDataSize = 0;
  1754. if (auGetPropertyInfo(interface,
  1755. kAudioUnitProperty_SupportedNumChannels,
  1756. kAudioUnitScope_Global,
  1757. 0, &outDataSize, &outWritable) == noErr
  1758. && outDataSize != 0
  1759. && outDataSize % sizeof(AUChannelInfo) == 0)
  1760. {
  1761. const uint32_t numChannels = outDataSize / sizeof(AUChannelInfo);
  1762. AUChannelInfo* const channelInfo = new AUChannelInfo[numChannels];
  1763. if (auGetProperty(interface,
  1764. kAudioUnitProperty_SupportedNumChannels,
  1765. kAudioUnitScope_Global,
  1766. 0, channelInfo, &outDataSize) == noErr
  1767. && outDataSize == numChannels * sizeof(AUChannelInfo))
  1768. {
  1769. AUChannelInfo* highestInfo = &channelInfo[0];
  1770. for (uint32_t i=1; i<numChannels; ++i)
  1771. {
  1772. if (channelInfo[i].inChannels > highestInfo->inChannels
  1773. && channelInfo[i].outChannels > highestInfo->outChannels)
  1774. {
  1775. highestInfo = &channelInfo[i];
  1776. }
  1777. }
  1778. audioIns = highestInfo->inChannels;
  1779. audioOuts = highestInfo->outChannels;
  1780. }
  1781. delete[] channelInfo;
  1782. }
  1783. // parameter count
  1784. outDataSize = 0;
  1785. if (auGetPropertyInfo(interface,
  1786. kAudioUnitProperty_ParameterList,
  1787. kAudioUnitScope_Global,
  1788. 0, &outDataSize, &outWritable) == noErr
  1789. && outDataSize != 0
  1790. && outDataSize % sizeof(AudioUnitParameterID) == 0)
  1791. {
  1792. const uint32_t numParams = outDataSize / sizeof(AudioUnitParameterID);
  1793. AudioUnitParameterID* const paramIds = new AudioUnitParameterID[numParams];
  1794. if (auGetProperty(interface,
  1795. kAudioUnitProperty_ParameterList,
  1796. kAudioUnitScope_Global,
  1797. 0, paramIds, &outDataSize) == noErr
  1798. && outDataSize == numParams * sizeof(AudioUnitParameterID))
  1799. {
  1800. AudioUnitParameterInfo info;
  1801. for (uint32_t i=0; i<numParams; ++i)
  1802. {
  1803. carla_zeroStruct(info);
  1804. outDataSize = 0;
  1805. if (auGetPropertyInfo(interface,
  1806. kAudioUnitProperty_ParameterInfo,
  1807. kAudioUnitScope_Global,
  1808. paramIds[i], &outDataSize, &outWritable) != noErr)
  1809. break;
  1810. if (outDataSize != sizeof(AudioUnitParameterInfo))
  1811. break;
  1812. if (auGetProperty(interface,
  1813. kAudioUnitProperty_ParameterInfo,
  1814. kAudioUnitScope_Global,
  1815. paramIds[i], &info, &outDataSize) != noErr)
  1816. break;
  1817. if ((info.flags & kAudioUnitParameterFlag_IsReadable) == 0)
  1818. continue;
  1819. if (info.flags & kAudioUnitParameterFlag_IsWritable)
  1820. ++parametersIns;
  1821. else
  1822. ++parametersOuts;
  1823. }
  1824. }
  1825. delete[] paramIds;
  1826. }
  1827. // MIDI input
  1828. if (auMIDIEvent != nullptr && auInitialize(interface) == noErr)
  1829. {
  1830. if (auMIDIEvent(interface, 0x90, 60, 64, 0) == noErr)
  1831. midiIns = 1;
  1832. auUninitialize(interface);
  1833. }
  1834. // MIDI output
  1835. outDataSize = 0;
  1836. outWritable = false;
  1837. if (auGetPropertyInfo(interface,
  1838. kAudioUnitProperty_MIDIOutputCallback,
  1839. kAudioUnitScope_Global,
  1840. 0, &outDataSize, &outWritable) == noErr
  1841. && outDataSize == sizeof(AUMIDIOutputCallbackStruct)
  1842. && outWritable)
  1843. {
  1844. midiOuts = 1;
  1845. }
  1846. // hints
  1847. if (category == PLUGIN_CATEGORY_SYNTH)
  1848. hints |= PLUGIN_IS_SYNTH;
  1849. outDataSize = 0;
  1850. if (auGetPropertyInfo(interface,
  1851. kAudioUnitProperty_CocoaUI,
  1852. kAudioUnitScope_Global,
  1853. 0, &outDataSize, &outWritable) == noErr
  1854. && outDataSize == sizeof(AudioUnitCocoaViewInfo))
  1855. {
  1856. hints |= PLUGIN_HAS_CUSTOM_UI;
  1857. #ifndef BUILD_BRIDGE
  1858. /* FIXME only enable this after doing custom AU hosting
  1859. hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
  1860. */
  1861. #endif
  1862. }
  1863. if (doInit)
  1864. {
  1865. // test valid scopes
  1866. outDataSize = 0;
  1867. if (auGetPropertyInfo(interface, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &outDataSize, &outWritable) == noErr && outDataSize == sizeof(UInt32))
  1868. {
  1869. UInt32 count = 0;
  1870. if (auGetProperty(interface, kAudioUnitProperty_ElementCount, kAudioUnitScope_Input, 0, &count, &outDataSize) == noErr && outDataSize == sizeof(UInt32) && count != 0)
  1871. {
  1872. }
  1873. }
  1874. // TODO
  1875. }
  1876. const CFIndex componentNameLen = CFStringGetLength(componentName);
  1877. char* const nameBuffer = new char[componentNameLen + 1];
  1878. const char* name;
  1879. const char* maker;
  1880. if (CFStringGetCString(componentName, nameBuffer, componentNameLen + 1, kCFStringEncodingUTF8))
  1881. {
  1882. if (char* const sep = std::strstr(nameBuffer, ": "))
  1883. {
  1884. sep[0] = sep[1] = '\0';
  1885. name = sep + 2;
  1886. maker = nameBuffer;
  1887. }
  1888. else
  1889. {
  1890. name = nameBuffer;
  1891. maker = nameBuffer + componentNameLen;
  1892. }
  1893. }
  1894. else
  1895. {
  1896. nameBuffer[0] = '\0';
  1897. name = maker = nameBuffer;
  1898. }
  1899. interface->Close(interface);
  1900. DISCOVERY_OUT("init", "------------");
  1901. DISCOVERY_OUT("build", BINARY_NATIVE);
  1902. DISCOVERY_OUT("hints", hints);
  1903. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  1904. DISCOVERY_OUT("name", name);
  1905. DISCOVERY_OUT("label", label);
  1906. DISCOVERY_OUT("maker", maker);
  1907. DISCOVERY_OUT("audio.ins", audioIns);
  1908. DISCOVERY_OUT("audio.outs", audioOuts);
  1909. DISCOVERY_OUT("midi.ins", midiIns);
  1910. DISCOVERY_OUT("midi.outs", midiOuts);
  1911. DISCOVERY_OUT("parameters.ins", parametersIns);
  1912. DISCOVERY_OUT("parameters.outs", parametersOuts);
  1913. DISCOVERY_OUT("end", "------------");
  1914. delete[] nameBuffer;
  1915. }
  1916. }
  1917. return false;
  1918. }
  1919. #endif // CARLA_OS_MAC
  1920. // --------------------------------------------------------------------------------------------------------------------
  1921. // CLAP
  1922. struct carla_clap_host : clap_host_t {
  1923. carla_clap_host()
  1924. {
  1925. clap_version = CLAP_VERSION;
  1926. host_data = this;
  1927. name = "Carla-Discovery";
  1928. vendor = "falkTX";
  1929. url = "https://kx.studio/carla";
  1930. version = CARLA_VERSION_STRING;
  1931. get_extension = carla_get_extension;
  1932. request_restart = carla_request_restart;
  1933. request_process = carla_request_process;
  1934. request_callback = carla_request_callback;
  1935. }
  1936. private:
  1937. static const void* CLAP_ABI carla_get_extension(const clap_host_t* const host, const char* const extension_id)
  1938. {
  1939. carla_stdout("carla_get_extension %p %s", host, extension_id);
  1940. return nullptr;
  1941. }
  1942. static void CLAP_ABI carla_request_restart(const clap_host_t* const host)
  1943. {
  1944. carla_stdout("carla_request_restart %p", host);
  1945. }
  1946. static void CLAP_ABI carla_request_process(const clap_host_t* const host)
  1947. {
  1948. carla_stdout("carla_request_process %p", host);
  1949. }
  1950. static void CLAP_ABI carla_request_callback(const clap_host_t* const host)
  1951. {
  1952. carla_stdout("carla_request_callback %p", host);
  1953. }
  1954. };
  1955. static bool clap_deinit_false(const clap_plugin_entry_t* const entry)
  1956. {
  1957. entry->deinit();
  1958. return false;
  1959. }
  1960. static bool do_clap_check(lib_t& libHandle, const char* const filename, const bool doInit)
  1961. {
  1962. const clap_plugin_entry_t* entry = nullptr;
  1963. #ifdef CARLA_OS_MAC
  1964. BundleLoader bundleLoader;
  1965. // if passed filename is not a plugin binary directly, inspect bundle and find one
  1966. if (libHandle == nullptr)
  1967. {
  1968. if (! bundleLoader.load(filename))
  1969. {
  1970. #ifdef __aarch64__
  1971. return true;
  1972. #else
  1973. DISCOVERY_OUT("error", "Failed to load CLAP bundle executable");
  1974. return false;
  1975. #endif
  1976. }
  1977. entry = bundleLoader.getSymbol<const clap_plugin_entry_t*>(CFSTR("clap_entry"));
  1978. }
  1979. else
  1980. #endif
  1981. {
  1982. entry = lib_symbol<const clap_plugin_entry_t*>(libHandle, "clap_entry");
  1983. }
  1984. // ensure entry points are available
  1985. if (entry == nullptr || entry->init == nullptr || entry->deinit == nullptr || entry->get_factory == nullptr)
  1986. {
  1987. DISCOVERY_OUT("error", "Not a CLAP plugin");
  1988. return false;
  1989. }
  1990. // ensure compatible version
  1991. if (!clap_version_is_compatible(entry->clap_version))
  1992. {
  1993. DISCOVERY_OUT("error", "Incompatible CLAP plugin");
  1994. return false;
  1995. }
  1996. const water::String pluginPath(water::File(filename).getParentDirectory().getFullPathName());
  1997. if (!entry->init(pluginPath.toRawUTF8()))
  1998. {
  1999. DISCOVERY_OUT("error", "CLAP plugin failed to initialize");
  2000. return false;
  2001. }
  2002. const clap_plugin_factory_t* const factory = static_cast<const clap_plugin_factory_t*>(
  2003. entry->get_factory(CLAP_PLUGIN_FACTORY_ID));
  2004. CARLA_SAFE_ASSERT_RETURN(factory != nullptr
  2005. && factory->get_plugin_count != nullptr
  2006. && factory->get_plugin_descriptor != nullptr
  2007. && factory->create_plugin != nullptr, clap_deinit_false(entry));
  2008. if (const uint32_t count = factory->get_plugin_count(factory))
  2009. {
  2010. const carla_clap_host host;
  2011. for (uint32_t i=0; i<count; ++i)
  2012. {
  2013. const clap_plugin_descriptor_t* const desc = factory->get_plugin_descriptor(factory, i);
  2014. CARLA_SAFE_ASSERT_CONTINUE(desc != nullptr);
  2015. const clap_plugin_t* const plugin = factory->create_plugin(factory, &host, desc->id);
  2016. CARLA_SAFE_ASSERT_CONTINUE(plugin != nullptr);
  2017. // FIXME this is not needed per spec, but JUCE-based CLAP plugins crash without it :(
  2018. if (!plugin->init(plugin))
  2019. {
  2020. plugin->destroy(plugin);
  2021. continue;
  2022. }
  2023. uint hints = 0x0;
  2024. uint audioIns = 0;
  2025. uint audioOuts = 0;
  2026. uint midiIns = 0;
  2027. uint midiOuts = 0;
  2028. uint parametersIns = 0;
  2029. uint parametersOuts = 0;
  2030. PluginCategory category = PLUGIN_CATEGORY_NONE;
  2031. const clap_plugin_audio_ports_t* const audioPorts = static_cast<const clap_plugin_audio_ports_t*>(
  2032. plugin->get_extension(plugin, CLAP_EXT_AUDIO_PORTS));
  2033. const clap_plugin_note_ports_t* const notePorts = static_cast<const clap_plugin_note_ports_t*>(
  2034. plugin->get_extension(plugin, CLAP_EXT_NOTE_PORTS));
  2035. const clap_plugin_params_t* const params = static_cast<const clap_plugin_params_t*>(
  2036. plugin->get_extension(plugin, CLAP_EXT_PARAMS));
  2037. #ifdef CLAP_WINDOW_API_NATIVE
  2038. const clap_plugin_gui_t* const gui = static_cast<const clap_plugin_gui_t*>(
  2039. plugin->get_extension(plugin, CLAP_EXT_GUI));
  2040. #endif
  2041. if (audioPorts != nullptr)
  2042. {
  2043. clap_audio_port_info_t info;
  2044. const uint32_t inPorts = audioPorts->count(plugin, true);
  2045. for (uint32_t j=0; j<inPorts; ++j)
  2046. {
  2047. if (!audioPorts->get(plugin, j, true, &info))
  2048. break;
  2049. audioIns += info.channel_count;
  2050. }
  2051. const uint32_t outPorts = audioPorts->count(plugin, false);
  2052. for (uint32_t j=0; j<outPorts; ++j)
  2053. {
  2054. if (!audioPorts->get(plugin, j, false, &info))
  2055. break;
  2056. audioOuts += info.channel_count;
  2057. }
  2058. }
  2059. if (notePorts != nullptr)
  2060. {
  2061. clap_note_port_info_t info;
  2062. const uint32_t inPorts = notePorts->count(plugin, true);
  2063. for (uint32_t j=0; j<inPorts; ++j)
  2064. {
  2065. if (!notePorts->get(plugin, j, true, &info))
  2066. break;
  2067. if (info.supported_dialects & CLAP_NOTE_DIALECT_MIDI)
  2068. ++midiIns;
  2069. }
  2070. const uint32_t outPorts = notePorts->count(plugin, false);
  2071. for (uint32_t j=0; j<outPorts; ++j)
  2072. {
  2073. if (!notePorts->get(plugin, j, false, &info))
  2074. break;
  2075. if (info.supported_dialects & CLAP_NOTE_DIALECT_MIDI)
  2076. ++midiOuts;
  2077. }
  2078. }
  2079. if (params != nullptr)
  2080. {
  2081. clap_param_info_t info;
  2082. const uint32_t numParams = params->count(plugin);
  2083. for (uint32_t j=0; j<numParams; ++j)
  2084. {
  2085. if (!params->get_info(plugin, j, &info))
  2086. break;
  2087. if (info.flags & (CLAP_PARAM_IS_HIDDEN|CLAP_PARAM_IS_BYPASS))
  2088. continue;
  2089. if (info.flags & CLAP_PARAM_IS_READONLY)
  2090. ++parametersOuts;
  2091. else
  2092. ++parametersIns;
  2093. }
  2094. }
  2095. if (desc->features != nullptr)
  2096. category = getPluginCategoryFromClapFeatures(desc->features);
  2097. if (category == PLUGIN_CATEGORY_SYNTH)
  2098. hints |= PLUGIN_IS_SYNTH;
  2099. #ifdef CLAP_WINDOW_API_NATIVE
  2100. if (gui != nullptr)
  2101. {
  2102. hints |= PLUGIN_HAS_CUSTOM_UI;
  2103. #ifndef BUILD_BRIDGE
  2104. if (gui->is_api_supported(plugin, CLAP_WINDOW_API_NATIVE, false))
  2105. hints |= PLUGIN_HAS_CUSTOM_EMBED_UI;
  2106. #endif
  2107. }
  2108. #endif
  2109. if (doInit)
  2110. {
  2111. // -----------------------------------------------------------------------
  2112. // start crash-free plugin test
  2113. // FIXME already initiated before, because broken plugins etc
  2114. // plugin->init(plugin);
  2115. // TODO
  2116. // end crash-free plugin test
  2117. // -----------------------------------------------------------------------
  2118. }
  2119. plugin->destroy(plugin);
  2120. DISCOVERY_OUT("init", "------------");
  2121. DISCOVERY_OUT("build", BINARY_NATIVE);
  2122. DISCOVERY_OUT("hints", hints);
  2123. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  2124. DISCOVERY_OUT("name", desc->name);
  2125. DISCOVERY_OUT("label", desc->id);
  2126. DISCOVERY_OUT("maker", desc->vendor);
  2127. DISCOVERY_OUT("audio.ins", audioIns);
  2128. DISCOVERY_OUT("audio.outs", audioOuts);
  2129. DISCOVERY_OUT("midi.ins", midiIns);
  2130. DISCOVERY_OUT("midi.outs", midiOuts);
  2131. DISCOVERY_OUT("parameters.ins", parametersIns);
  2132. DISCOVERY_OUT("parameters.outs", parametersOuts);
  2133. DISCOVERY_OUT("end", "------------");
  2134. }
  2135. }
  2136. entry->deinit();
  2137. return false;
  2138. }
  2139. // --------------------------------------------------------------------------------------------------------------------
  2140. // fluidsynth (dls, sf2, sfz)
  2141. #ifdef HAVE_FLUIDSYNTH
  2142. static void do_fluidsynth_check(const char* const filename, const PluginType type, const bool doInit)
  2143. {
  2144. const water::File file(filename);
  2145. if (! file.existsAsFile())
  2146. {
  2147. DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
  2148. return;
  2149. }
  2150. if (type == PLUGIN_SF2 && ! fluid_is_soundfont(filename))
  2151. {
  2152. DISCOVERY_OUT("error", "Not a SF2 file");
  2153. return;
  2154. }
  2155. int programs = 0;
  2156. if (doInit)
  2157. {
  2158. fluid_settings_t* const f_settings = new_fluid_settings();
  2159. CARLA_SAFE_ASSERT_RETURN(f_settings != nullptr,);
  2160. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  2161. CARLA_SAFE_ASSERT_RETURN(f_synth != nullptr,);
  2162. const int f_id_test = fluid_synth_sfload(f_synth, filename, 0);
  2163. if (f_id_test < 0)
  2164. {
  2165. DISCOVERY_OUT("error", "Failed to load SF2 file");
  2166. return;
  2167. }
  2168. #if FLUIDSYNTH_VERSION_MAJOR >= 2
  2169. const int f_id = f_id_test;
  2170. #else
  2171. const uint f_id = static_cast<uint>(f_id_test);
  2172. #endif
  2173. if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id))
  2174. {
  2175. #if FLUIDSYNTH_VERSION_MAJOR >= 2
  2176. fluid_sfont_iteration_start(f_sfont);
  2177. for (; fluid_sfont_iteration_next(f_sfont);)
  2178. ++programs;
  2179. #else
  2180. fluid_preset_t f_preset;
  2181. f_sfont->iteration_start(f_sfont);
  2182. for (; f_sfont->iteration_next(f_sfont, &f_preset);)
  2183. ++programs;
  2184. #endif
  2185. }
  2186. delete_fluid_synth(f_synth);
  2187. delete_fluid_settings(f_settings);
  2188. }
  2189. CarlaString name(file.getFileNameWithoutExtension().toRawUTF8());
  2190. CarlaString label(name);
  2191. // 2 channels
  2192. DISCOVERY_OUT("init", "------------");
  2193. DISCOVERY_OUT("build", BINARY_NATIVE);
  2194. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  2195. DISCOVERY_OUT("category", "synth");
  2196. DISCOVERY_OUT("name", name.buffer());
  2197. DISCOVERY_OUT("label", label.buffer());
  2198. DISCOVERY_OUT("audio.outs", 2);
  2199. DISCOVERY_OUT("midi.ins", 1);
  2200. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  2201. DISCOVERY_OUT("parameters.outs", 1);
  2202. DISCOVERY_OUT("end", "------------");
  2203. // 16 channels
  2204. if (doInit && (name.isEmpty() || programs <= 1))
  2205. return;
  2206. name += " (16 outputs)";
  2207. DISCOVERY_OUT("init", "------------");
  2208. DISCOVERY_OUT("build", BINARY_NATIVE);
  2209. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  2210. DISCOVERY_OUT("category", "synth");
  2211. DISCOVERY_OUT("name", name.buffer());
  2212. DISCOVERY_OUT("label", label.buffer());
  2213. DISCOVERY_OUT("audio.outs", 32);
  2214. DISCOVERY_OUT("midi.ins", 1);
  2215. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  2216. DISCOVERY_OUT("parameters.outs", 1);
  2217. DISCOVERY_OUT("end", "------------");
  2218. }
  2219. #endif // HAVE_FLUIDSYNTH
  2220. // --------------------------------------------------------------------------------------------------------------------
  2221. // JSFX
  2222. #ifdef HAVE_YSFX
  2223. static void do_jsfx_check(const char* const filename, bool doInit)
  2224. {
  2225. const water::File file(filename);
  2226. ysfx_config_u config(ysfx_config_new());
  2227. ysfx_register_builtin_audio_formats(config.get());
  2228. ysfx_guess_file_roots(config.get(), filename);
  2229. ysfx_set_log_reporter(config.get(), &CarlaJsfxLogging::logErrorsOnly);
  2230. ysfx_u effect(ysfx_new(config.get()));
  2231. uint hints = 0;
  2232. // do not attempt to compile it, because the import path is not known
  2233. (void)doInit;
  2234. if (! ysfx_load_file(effect.get(), filename, 0))
  2235. {
  2236. DISCOVERY_OUT("error", "Cannot read the JSFX header");
  2237. return;
  2238. }
  2239. const char* const name = ysfx_get_name(effect.get());
  2240. // author and category are extracted from the pseudo-tags
  2241. const char* const author = ysfx_get_author(effect.get());
  2242. const CB::PluginCategory category = CarlaJsfxCategories::getFromEffect(effect.get());
  2243. const uint32_t audioIns = ysfx_get_num_inputs(effect.get());
  2244. const uint32_t audioOuts = ysfx_get_num_outputs(effect.get());
  2245. const uint32_t midiIns = 1;
  2246. const uint32_t midiOuts = 1;
  2247. uint32_t parameters = 0;
  2248. for (uint32_t sliderIndex = 0; sliderIndex < ysfx_max_sliders; ++sliderIndex)
  2249. {
  2250. if (ysfx_slider_exists(effect.get(), sliderIndex))
  2251. ++parameters;
  2252. }
  2253. DISCOVERY_OUT("init", "------------");
  2254. DISCOVERY_OUT("build", BINARY_NATIVE);
  2255. DISCOVERY_OUT("hints", hints);
  2256. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  2257. DISCOVERY_OUT("name", name);
  2258. DISCOVERY_OUT("maker", author);
  2259. DISCOVERY_OUT("label", filename);
  2260. DISCOVERY_OUT("audio.ins", audioIns);
  2261. DISCOVERY_OUT("audio.outs", audioOuts);
  2262. DISCOVERY_OUT("midi.ins", midiIns);
  2263. DISCOVERY_OUT("midi.outs", midiOuts);
  2264. DISCOVERY_OUT("parameters.ins", parameters);
  2265. DISCOVERY_OUT("end", "------------");
  2266. }
  2267. #endif // HAVE_YSFX
  2268. // --------------------------------------------------------------------------------------------------------------------
  2269. // main entry point
  2270. int main(int argc, const char* argv[])
  2271. {
  2272. if (argc != 3 && argc != 7)
  2273. {
  2274. carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
  2275. return 1;
  2276. }
  2277. const char* const stype = argv[1];
  2278. const char* const filename = argv[2];
  2279. const PluginType type = getPluginTypeFromString(stype);
  2280. CarlaString filenameCheck(filename);
  2281. filenameCheck.toLower();
  2282. bool openLib;
  2283. lib_t handle = nullptr;
  2284. switch (type)
  2285. {
  2286. case PLUGIN_LADSPA:
  2287. case PLUGIN_DSSI:
  2288. // only available as single binary
  2289. openLib = true;
  2290. break;
  2291. case PLUGIN_VST2:
  2292. case PLUGIN_CLAP:
  2293. #ifdef CARLA_OS_MAC
  2294. // bundle on macOS
  2295. openLib = false;
  2296. #else
  2297. // single binary on all else
  2298. openLib = true;
  2299. #endif
  2300. break;
  2301. case PLUGIN_VST3:
  2302. #if defined(CARLA_OS_WIN)
  2303. // either file or bundle on Windows
  2304. openLib = water::File(filename).existsAsFile();
  2305. #else
  2306. // bundle on all else
  2307. openLib = false;
  2308. #endif
  2309. break;
  2310. default:
  2311. openLib = false;
  2312. break;
  2313. }
  2314. if (type != PLUGIN_SF2 && filenameCheck.contains("fluidsynth", true))
  2315. {
  2316. DISCOVERY_OUT("info", "skipping fluidsynth based plugin");
  2317. return 0;
  2318. }
  2319. // ----------------------------------------------------------------------------------------------------------------
  2320. // Initialize OS features
  2321. // we want stuff in English so we can parse error messages
  2322. ::setlocale(LC_ALL, "C");
  2323. #ifndef CARLA_OS_WIN
  2324. carla_setenv("LC_ALL", "C");
  2325. #endif
  2326. #ifdef CARLA_OS_WIN
  2327. // init win32 stuff that plugins might use
  2328. OleInitialize(nullptr);
  2329. CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
  2330. #ifndef __WINPTHREADS_VERSION
  2331. // (non-portable) initialization of statically linked pthread library
  2332. pthread_win32_process_attach_np();
  2333. pthread_win32_thread_attach_np();
  2334. #endif
  2335. // do not show error message box on Windows
  2336. SetErrorMode(SEM_NOGPFAULTERRORBOX);
  2337. SetUnhandledExceptionFilter(winExceptionFilter);
  2338. #endif
  2339. // ----------------------------------------------------------------------------------------------------------------
  2340. // Initialize pipe
  2341. if (argc == 7)
  2342. {
  2343. gPipe = new DiscoveryPipe;
  2344. if (! gPipe->initPipeClient(argv))
  2345. return 1;
  2346. }
  2347. // ----------------------------------------------------------------------------------------------------------------
  2348. if (openLib)
  2349. {
  2350. handle = lib_open(filename);
  2351. if (handle == nullptr)
  2352. {
  2353. print_lib_error(filename);
  2354. gPipe = nullptr;
  2355. return 1;
  2356. }
  2357. }
  2358. // never do init for dssi-vst, takes too long and it's crashy
  2359. bool doInit = ! filenameCheck.contains("dssi-vst", true);
  2360. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS") != nullptr)
  2361. doInit = false;
  2362. // ----------------------------------------------------------------------------------------------------------------
  2363. if (doInit && openLib && handle != nullptr)
  2364. {
  2365. // test fast loading & unloading DLL without initializing the plugin(s)
  2366. if (! lib_close(handle))
  2367. {
  2368. print_lib_error(filename);
  2369. gPipe = nullptr;
  2370. return 1;
  2371. }
  2372. handle = lib_open(filename);
  2373. if (handle == nullptr)
  2374. {
  2375. print_lib_error(filename);
  2376. gPipe = nullptr;
  2377. return 1;
  2378. }
  2379. }
  2380. #ifndef BUILD_BRIDGE
  2381. if (std::strcmp(filename, ":all") == 0)
  2382. {
  2383. do_cached_check(type);
  2384. gPipe = nullptr;
  2385. return 0;
  2386. }
  2387. #endif
  2388. #ifdef CARLA_OS_MAC
  2389. // Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
  2390. switch (type)
  2391. {
  2392. case PLUGIN_LADSPA:
  2393. case PLUGIN_DSSI:
  2394. case PLUGIN_VST2:
  2395. case PLUGIN_VST3:
  2396. case PLUGIN_AU:
  2397. case PLUGIN_CLAP:
  2398. removeFileFromQuarantine(filename);
  2399. break;
  2400. default:
  2401. break;
  2402. }
  2403. #endif
  2404. // some macOS plugins have not been yet ported to arm64, re-run them in x86_64 mode if discovery fails
  2405. bool retryAsX64lugin = false;
  2406. switch (type)
  2407. {
  2408. case PLUGIN_LADSPA:
  2409. do_ladspa_check(handle, filename, doInit);
  2410. break;
  2411. case PLUGIN_DSSI:
  2412. do_dssi_check(handle, filename, doInit);
  2413. break;
  2414. #ifndef BUILD_BRIDGE
  2415. case PLUGIN_LV2:
  2416. do_lv2_check(filename, doInit);
  2417. break;
  2418. #endif
  2419. case PLUGIN_VST2:
  2420. retryAsX64lugin = do_vst2_check(handle, filename, doInit);
  2421. break;
  2422. case PLUGIN_VST3:
  2423. retryAsX64lugin = do_vst3_check(handle, filename, doInit);
  2424. break;
  2425. case PLUGIN_AU:
  2426. #ifdef CARLA_OS_MAC
  2427. retryAsX64lugin = do_au_check(filename, doInit);
  2428. #else
  2429. DISCOVERY_OUT("error", "AU support not available");
  2430. #endif
  2431. break;
  2432. case PLUGIN_JSFX:
  2433. #ifdef HAVE_YSFX
  2434. do_jsfx_check(filename, doInit);
  2435. #else
  2436. DISCOVERY_OUT("error", "JSFX support not available");
  2437. #endif
  2438. break;
  2439. case PLUGIN_CLAP:
  2440. retryAsX64lugin = do_clap_check(handle, filename, doInit);
  2441. break;
  2442. case PLUGIN_DLS:
  2443. case PLUGIN_GIG:
  2444. case PLUGIN_SF2:
  2445. #ifdef HAVE_FLUIDSYNTH
  2446. do_fluidsynth_check(filename, type, doInit);
  2447. #else
  2448. DISCOVERY_OUT("error", "SF2 support not available");
  2449. #endif
  2450. break;
  2451. default:
  2452. break;
  2453. }
  2454. if (openLib && handle != nullptr)
  2455. lib_close(handle);
  2456. if (retryAsX64lugin)
  2457. {
  2458. #if defined(CARLA_OS_MAC) && defined(__aarch64__)
  2459. DISCOVERY_OUT("warning", "No plugins found while scanning in arm64 mode, will try x86_64 now");
  2460. cpu_type_t pref = CPU_TYPE_X86_64;
  2461. pid_t pid = -1;
  2462. posix_spawnattr_t attr;
  2463. posix_spawnattr_init(&attr);
  2464. CARLA_SAFE_ASSERT_RETURN(posix_spawnattr_setbinpref_np(&attr, 1, &pref, nullptr) == 0, 1);
  2465. CARLA_SAFE_ASSERT_RETURN(posix_spawn(&pid, argv[0], nullptr, &attr, (char* const*)argv, nullptr) == 0, 1);
  2466. posix_spawnattr_destroy(&attr);
  2467. if (pid > 0)
  2468. {
  2469. int status;
  2470. waitpid(pid, &status, 0);
  2471. }
  2472. #endif
  2473. }
  2474. gPipe = nullptr;
  2475. // ----------------------------------------------------------------------------------------------------------------
  2476. #ifdef CARLA_OS_WIN
  2477. #ifndef __WINPTHREADS_VERSION
  2478. pthread_win32_thread_detach_np();
  2479. pthread_win32_process_detach_np();
  2480. #endif
  2481. CoUninitialize();
  2482. OleUninitialize();
  2483. #endif
  2484. return 0;
  2485. }
  2486. // --------------------------------------------------------------------------------------------------------------------