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.

carla-discovery.cpp 77KB

11 years ago
11 years ago
11 years ago
11 years ago
12 years ago
12 years ago
10 years ago
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
2 years ago
2 years ago
10 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408
  1. /*
  2. * Carla Plugin discovery
  3. * Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaBackendUtils.hpp"
  18. #include "CarlaLibUtils.hpp"
  19. #include "CarlaMathUtils.hpp"
  20. #include "CarlaScopeUtils.hpp"
  21. #include "CarlaMIDI.h"
  22. #include "LinkedList.hpp"
  23. #include "CarlaLadspaUtils.hpp"
  24. #include "CarlaDssiUtils.hpp"
  25. #include "CarlaLv2Utils.hpp"
  26. #include "CarlaVst2Utils.hpp"
  27. #include "CarlaVst3Utils.hpp"
  28. #ifdef CARLA_OS_MAC
  29. # include "CarlaMacUtils.cpp"
  30. # if defined(USING_JUCE) && defined(__aarch64__)
  31. # include <spawn.h>
  32. # endif
  33. #endif
  34. #ifdef CARLA_OS_WIN
  35. # include <pthread.h>
  36. # include <objbase.h>
  37. #endif
  38. #ifdef BUILD_BRIDGE
  39. # undef HAVE_FLUIDSYNTH
  40. #endif
  41. #ifdef HAVE_FLUIDSYNTH
  42. # include <fluidsynth.h>
  43. #endif
  44. #include <iostream>
  45. #include "water/files/File.h"
  46. #ifndef BUILD_BRIDGE
  47. # include "CarlaDssiUtils.cpp"
  48. # include "CarlaJsfxUtils.hpp"
  49. # include "../backend/utils/CachedPlugins.cpp"
  50. #endif
  51. #ifdef USING_JUCE
  52. # include "carla_juce/carla_juce.h"
  53. # pragma GCC diagnostic ignored "-Wdouble-promotion"
  54. # pragma GCC diagnostic ignored "-Wduplicated-branches"
  55. # pragma GCC diagnostic ignored "-Weffc++"
  56. # pragma GCC diagnostic ignored "-Wfloat-equal"
  57. # include "juce_audio_processors/juce_audio_processors.h"
  58. # if JUCE_PLUGINHOST_VST
  59. # define USING_JUCE_FOR_VST2
  60. # endif
  61. # if JUCE_PLUGINHOST_VST3
  62. # define USING_JUCE_FOR_VST3
  63. # endif
  64. # pragma GCC diagnostic pop
  65. #endif
  66. #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
  67. using water::File;
  68. CARLA_BACKEND_USE_NAMESPACE
  69. // -------------------------------------------------------------------------------------------------------------------
  70. // Dummy values to test plugins with
  71. static const uint32_t kBufferSize = 512;
  72. static const double kSampleRate = 44100.0;
  73. static const int32_t kSampleRatei = 44100;
  74. static const float kSampleRatef = 44100.0f;
  75. // -------------------------------------------------------------------------------------------------------------------
  76. // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
  77. static void print_lib_error(const char* const filename)
  78. {
  79. const char* const error(lib_error(filename));
  80. if (error != nullptr &&
  81. std::strstr(error, "wrong ELF class") == nullptr &&
  82. std::strstr(error, "invalid ELF header") == nullptr &&
  83. std::strstr(error, "Bad EXE format") == nullptr &&
  84. std::strstr(error, "no suitable image found") == nullptr &&
  85. std::strstr(error, "not a valid Win32 application") == nullptr)
  86. {
  87. DISCOVERY_OUT("error", error);
  88. }
  89. }
  90. // ------------------------------ Plugin Checks -----------------------------
  91. #ifndef BUILD_BRIDGE
  92. static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
  93. {
  94. if (! pinfo->valid)
  95. return;
  96. DISCOVERY_OUT("init", "-----------");
  97. DISCOVERY_OUT("build", BINARY_NATIVE);
  98. DISCOVERY_OUT("hints", pinfo->hints);
  99. DISCOVERY_OUT("category", getPluginCategoryAsString(pinfo->category));
  100. DISCOVERY_OUT("name", pinfo->name);
  101. DISCOVERY_OUT("maker", pinfo->maker);
  102. DISCOVERY_OUT("label", pinfo->label);
  103. DISCOVERY_OUT("audio.ins", pinfo->audioIns);
  104. DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
  105. DISCOVERY_OUT("cv.ins", pinfo->cvIns);
  106. DISCOVERY_OUT("cv.outs", pinfo->cvOuts);
  107. DISCOVERY_OUT("midi.ins", pinfo->midiIns);
  108. DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
  109. DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
  110. DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
  111. DISCOVERY_OUT("end", "------------");
  112. }
  113. static void do_cached_check(const PluginType type)
  114. {
  115. const char* plugPath;
  116. switch (type)
  117. {
  118. case PLUGIN_LV2:
  119. plugPath = std::getenv("LV2_PATH");
  120. break;
  121. case PLUGIN_SFZ:
  122. plugPath = std::getenv("SFZ_PATH");
  123. break;
  124. default:
  125. plugPath = nullptr;
  126. break;
  127. }
  128. # ifdef USING_JUCE
  129. if (type == PLUGIN_AU)
  130. CarlaJUCE::initialiseJuce_GUI();
  131. # endif
  132. const uint count = carla_get_cached_plugin_count(type, plugPath);
  133. for (uint i=0; i<count; ++i)
  134. {
  135. const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i));
  136. CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);
  137. print_cached_plugin(pinfo);
  138. }
  139. # ifdef USING_JUCE
  140. if (type == PLUGIN_AU)
  141. CarlaJUCE::shutdownJuce_GUI();
  142. # endif
  143. }
  144. #endif
  145. static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit)
  146. {
  147. LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  148. if (descFn == nullptr)
  149. {
  150. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  151. return;
  152. }
  153. const LADSPA_Descriptor* descriptor;
  154. {
  155. descriptor = descFn(0);
  156. if (descriptor == nullptr)
  157. {
  158. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  159. return;
  160. }
  161. if (doInit && descriptor->instantiate != nullptr && descriptor->cleanup != nullptr)
  162. {
  163. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  164. if (handle == nullptr)
  165. {
  166. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  167. return;
  168. }
  169. descriptor->cleanup(handle);
  170. lib_close(libHandle);
  171. libHandle = lib_open(filename);
  172. if (libHandle == nullptr)
  173. {
  174. print_lib_error(filename);
  175. return;
  176. }
  177. descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  178. if (descFn == nullptr)
  179. {
  180. DISCOVERY_OUT("error", "Not a LADSPA plugin (#2)");
  181. return;
  182. }
  183. }
  184. }
  185. unsigned long i = 0;
  186. while ((descriptor = descFn(i++)) != nullptr)
  187. {
  188. if (descriptor->instantiate == nullptr)
  189. {
  190. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
  191. continue;
  192. }
  193. if (descriptor->cleanup == nullptr)
  194. {
  195. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
  196. continue;
  197. }
  198. if (descriptor->run == nullptr)
  199. {
  200. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
  201. continue;
  202. }
  203. if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  204. {
  205. DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
  206. }
  207. uint hints = 0x0;
  208. uint audioIns = 0;
  209. uint audioOuts = 0;
  210. uint audioTotal = 0;
  211. uint parametersIns = 0;
  212. uint parametersOuts = 0;
  213. uint parametersTotal = 0;
  214. if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  215. hints |= PLUGIN_IS_RTSAFE;
  216. for (unsigned long j=0; j < descriptor->PortCount; ++j)
  217. {
  218. CARLA_ASSERT(descriptor->PortNames[j] != nullptr);
  219. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  220. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  221. {
  222. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  223. audioIns += 1;
  224. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  225. audioOuts += 1;
  226. audioTotal += 1;
  227. }
  228. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  229. {
  230. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  231. parametersIns += 1;
  232. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(descriptor->PortNames[j], "latency") != 0 && std::strcmp(descriptor->PortNames[j], "_latency") != 0)
  233. parametersOuts += 1;
  234. parametersTotal += 1;
  235. }
  236. }
  237. if (doInit)
  238. {
  239. // -----------------------------------------------------------------------
  240. // start crash-free plugin test
  241. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  242. if (handle == nullptr)
  243. {
  244. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  245. continue;
  246. }
  247. // Test quick init and cleanup
  248. descriptor->cleanup(handle);
  249. handle = descriptor->instantiate(descriptor, kSampleRatei);
  250. if (handle == nullptr)
  251. {
  252. DISCOVERY_OUT("error", "Failed to init LADSPA plugin (#2)");
  253. continue;
  254. }
  255. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  256. LADSPA_Data bufferParams[parametersTotal];
  257. LADSPA_Data min, max, def;
  258. for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; ++j)
  259. {
  260. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  261. const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
  262. const char* const portName = descriptor->PortNames[j];
  263. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  264. {
  265. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  266. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  267. }
  268. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  269. {
  270. // min value
  271. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  272. min = portRangeHints.LowerBound;
  273. else
  274. min = 0.0f;
  275. // max value
  276. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  277. max = portRangeHints.UpperBound;
  278. else
  279. max = 1.0f;
  280. if (min > max)
  281. {
  282. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  283. max = min + 0.1f;
  284. }
  285. else if (carla_isEqual(min, max))
  286. {
  287. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  288. max = min + 0.1f;
  289. }
  290. // default value
  291. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  292. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  293. {
  294. min *= kSampleRatef;
  295. max *= kSampleRatef;
  296. def *= kSampleRatef;
  297. }
  298. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  299. {
  300. // latency parameter
  301. def = 0.0f;
  302. }
  303. else
  304. {
  305. if (def < min)
  306. def = min;
  307. else if (def > max)
  308. def = max;
  309. }
  310. bufferParams[iC] = def;
  311. descriptor->connect_port(handle, j, &bufferParams[iC++]);
  312. }
  313. }
  314. if (descriptor->activate != nullptr)
  315. descriptor->activate(handle);
  316. descriptor->run(handle, kBufferSize);
  317. if (descriptor->deactivate != nullptr)
  318. descriptor->deactivate(handle);
  319. descriptor->cleanup(handle);
  320. // end crash-free plugin test
  321. // -----------------------------------------------------------------------
  322. }
  323. DISCOVERY_OUT("init", "-----------");
  324. DISCOVERY_OUT("build", BINARY_NATIVE);
  325. DISCOVERY_OUT("hints", hints);
  326. DISCOVERY_OUT("category", getPluginCategoryAsString(getPluginCategoryFromName(descriptor->Name)));
  327. DISCOVERY_OUT("name", descriptor->Name);
  328. DISCOVERY_OUT("label", descriptor->Label);
  329. DISCOVERY_OUT("maker", descriptor->Maker);
  330. DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
  331. DISCOVERY_OUT("audio.ins", audioIns);
  332. DISCOVERY_OUT("audio.outs", audioOuts);
  333. DISCOVERY_OUT("parameters.ins", parametersIns);
  334. DISCOVERY_OUT("parameters.outs", parametersOuts);
  335. DISCOVERY_OUT("end", "------------");
  336. }
  337. }
  338. static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit)
  339. {
  340. DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  341. if (descFn == nullptr)
  342. {
  343. DISCOVERY_OUT("error", "Not a DSSI plugin");
  344. return;
  345. }
  346. const DSSI_Descriptor* descriptor;
  347. {
  348. descriptor = descFn(0);
  349. if (descriptor == nullptr)
  350. {
  351. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  352. return;
  353. }
  354. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  355. if (ldescriptor == nullptr)
  356. {
  357. DISCOVERY_OUT("error", "DSSI plugin doesn't provide the LADSPA interface");
  358. return;
  359. }
  360. if (doInit && ldescriptor->instantiate != nullptr && ldescriptor->cleanup != nullptr)
  361. {
  362. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  363. if (handle == nullptr)
  364. {
  365. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  366. return;
  367. }
  368. ldescriptor->cleanup(handle);
  369. lib_close(libHandle);
  370. libHandle = lib_open(filename);
  371. if (libHandle == nullptr)
  372. {
  373. print_lib_error(filename);
  374. return;
  375. }
  376. descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  377. if (descFn == nullptr)
  378. {
  379. DISCOVERY_OUT("error", "Not a DSSI plugin (#2)");
  380. return;
  381. }
  382. }
  383. }
  384. unsigned long i = 0;
  385. while ((descriptor = descFn(i++)) != nullptr)
  386. {
  387. const LADSPA_Descriptor* const ldescriptor = descriptor->LADSPA_Plugin;
  388. if (ldescriptor == nullptr)
  389. {
  390. DISCOVERY_OUT("error", "Plugin has no LADSPA interface");
  391. continue;
  392. }
  393. if (descriptor->DSSI_API_Version != DSSI_VERSION_MAJOR)
  394. {
  395. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' uses an unsupported DSSI spec version " << descriptor->DSSI_API_Version);
  396. continue;
  397. }
  398. if (ldescriptor->instantiate == nullptr)
  399. {
  400. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
  401. continue;
  402. }
  403. if (ldescriptor->cleanup == nullptr)
  404. {
  405. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
  406. continue;
  407. }
  408. if (ldescriptor->run == nullptr && descriptor->run_synth == nullptr)
  409. {
  410. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run() or run_synth()");
  411. continue;
  412. }
  413. if (descriptor->run_synth == nullptr && descriptor->run_multiple_synths != nullptr)
  414. {
  415. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' requires run_multiple_synths which is not supported");
  416. continue;
  417. }
  418. if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  419. {
  420. DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
  421. }
  422. uint hints = 0x0;
  423. uint audioIns = 0;
  424. uint audioOuts = 0;
  425. uint audioTotal = 0;
  426. uint midiIns = 0;
  427. uint parametersIns = 0;
  428. uint parametersOuts = 0;
  429. uint parametersTotal = 0;
  430. if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  431. hints |= PLUGIN_IS_RTSAFE;
  432. for (unsigned long j=0; j < ldescriptor->PortCount; ++j)
  433. {
  434. CARLA_ASSERT(ldescriptor->PortNames[j] != nullptr);
  435. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  436. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  437. {
  438. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  439. audioIns += 1;
  440. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  441. audioOuts += 1;
  442. audioTotal += 1;
  443. }
  444. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  445. {
  446. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  447. parametersIns += 1;
  448. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(ldescriptor->PortNames[j], "latency") != 0 && std::strcmp(ldescriptor->PortNames[j], "_latency") != 0)
  449. parametersOuts += 1;
  450. parametersTotal += 1;
  451. }
  452. }
  453. if (descriptor->run_synth != nullptr)
  454. midiIns = 1;
  455. if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
  456. hints |= PLUGIN_IS_SYNTH;
  457. #ifndef BUILD_BRIDGE
  458. if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label))
  459. {
  460. hints |= PLUGIN_HAS_CUSTOM_UI;
  461. delete[] ui;
  462. }
  463. #endif
  464. if (doInit)
  465. {
  466. // -----------------------------------------------------------------------
  467. // start crash-free plugin test
  468. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  469. if (handle == nullptr)
  470. {
  471. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  472. continue;
  473. }
  474. // Test quick init and cleanup
  475. ldescriptor->cleanup(handle);
  476. handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  477. if (handle == nullptr)
  478. {
  479. DISCOVERY_OUT("error", "Failed to init DSSI plugin (#2)");
  480. continue;
  481. }
  482. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  483. LADSPA_Data bufferParams[parametersTotal];
  484. LADSPA_Data min, max, def;
  485. for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; ++j)
  486. {
  487. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  488. const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
  489. const char* const portName = ldescriptor->PortNames[j];
  490. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  491. {
  492. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  493. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  494. }
  495. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  496. {
  497. // min value
  498. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  499. min = portRangeHints.LowerBound;
  500. else
  501. min = 0.0f;
  502. // max value
  503. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  504. max = portRangeHints.UpperBound;
  505. else
  506. max = 1.0f;
  507. if (min > max)
  508. {
  509. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  510. max = min + 0.1f;
  511. }
  512. else if (carla_isEqual(min, max))
  513. {
  514. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  515. max = min + 0.1f;
  516. }
  517. // default value
  518. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  519. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  520. {
  521. min *= kSampleRatef;
  522. max *= kSampleRatef;
  523. def *= kSampleRatef;
  524. }
  525. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  526. {
  527. // latency parameter
  528. def = 0.0f;
  529. }
  530. else
  531. {
  532. if (def < min)
  533. def = min;
  534. else if (def > max)
  535. def = max;
  536. }
  537. bufferParams[iC] = def;
  538. ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
  539. }
  540. }
  541. // select first midi-program if available
  542. if (descriptor->get_program != nullptr && descriptor->select_program != nullptr)
  543. {
  544. if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
  545. descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
  546. }
  547. if (ldescriptor->activate != nullptr)
  548. ldescriptor->activate(handle);
  549. if (descriptor->run_synth != nullptr)
  550. {
  551. snd_seq_event_t midiEvents[2];
  552. carla_zeroStructs(midiEvents, 2);
  553. const unsigned long midiEventCount = 2;
  554. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  555. midiEvents[0].data.note.note = 64;
  556. midiEvents[0].data.note.velocity = 100;
  557. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  558. midiEvents[1].data.note.note = 64;
  559. midiEvents[1].data.note.velocity = 0;
  560. midiEvents[1].time.tick = kBufferSize/2;
  561. descriptor->run_synth(handle, kBufferSize, midiEvents, midiEventCount);
  562. }
  563. else
  564. ldescriptor->run(handle, kBufferSize);
  565. if (ldescriptor->deactivate != nullptr)
  566. ldescriptor->deactivate(handle);
  567. ldescriptor->cleanup(handle);
  568. // end crash-free plugin test
  569. // -----------------------------------------------------------------------
  570. }
  571. DISCOVERY_OUT("init", "-----------");
  572. DISCOVERY_OUT("build", BINARY_NATIVE);
  573. DISCOVERY_OUT("category", ((hints & PLUGIN_IS_SYNTH)
  574. ? "synth"
  575. : getPluginCategoryAsString(getPluginCategoryFromName(ldescriptor->Name))));
  576. DISCOVERY_OUT("hints", hints);
  577. DISCOVERY_OUT("name", ldescriptor->Name);
  578. DISCOVERY_OUT("label", ldescriptor->Label);
  579. DISCOVERY_OUT("maker", ldescriptor->Maker);
  580. DISCOVERY_OUT("uniqueId", ldescriptor->UniqueID);
  581. DISCOVERY_OUT("audio.ins", audioIns);
  582. DISCOVERY_OUT("audio.outs", audioOuts);
  583. DISCOVERY_OUT("midi.ins", midiIns);
  584. DISCOVERY_OUT("parameters.ins", parametersIns);
  585. DISCOVERY_OUT("parameters.outs", parametersOuts);
  586. DISCOVERY_OUT("end", "------------");
  587. }
  588. }
  589. #ifndef BUILD_BRIDGE
  590. static void do_lv2_check(const char* const bundle, const bool doInit)
  591. {
  592. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  593. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, bundle));
  594. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(),);
  595. CarlaString sBundle(bundleNode.as_uri());
  596. if (! sBundle.endsWith("/"))
  597. sBundle += "/";
  598. // Load bundle
  599. lv2World.load_bundle(sBundle);
  600. // Load plugins in this bundle
  601. const Lilv::Plugins lilvPlugins(lv2World.get_all_plugins());
  602. // Get all plugin URIs in this bundle
  603. CarlaStringList URIs;
  604. LILV_FOREACH(plugins, it, lilvPlugins)
  605. {
  606. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it));
  607. if (const char* const uri = lilvPlugin.get_uri().as_string())
  608. URIs.appendUnique(uri);
  609. }
  610. if (URIs.isEmpty())
  611. {
  612. DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
  613. return;
  614. }
  615. // Get & check every plugin-instance
  616. for (CarlaStringList::Itenerator it=URIs.begin2(); it.valid(); it.next())
  617. {
  618. const char* const URI = it.getValue(nullptr);
  619. CARLA_SAFE_ASSERT_CONTINUE(URI != nullptr);
  620. CarlaScopedPointer<const LV2_RDF_Descriptor> rdfDescriptor(lv2_rdf_new(URI, false));
  621. if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
  622. {
  623. DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URI << "'");
  624. continue;
  625. }
  626. if (doInit)
  627. {
  628. // test if lib is loadable, twice
  629. const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);
  630. if (libHandle1 == nullptr)
  631. {
  632. print_lib_error(rdfDescriptor->Binary);
  633. delete rdfDescriptor;
  634. continue;
  635. }
  636. lib_close(libHandle1);
  637. const lib_t libHandle2 = lib_open(rdfDescriptor->Binary);
  638. if (libHandle2 == nullptr)
  639. {
  640. print_lib_error(rdfDescriptor->Binary);
  641. delete rdfDescriptor;
  642. continue;
  643. }
  644. lib_close(libHandle2);
  645. }
  646. const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(URI));
  647. CARLA_SAFE_ASSERT_CONTINUE(cPlugin != nullptr);
  648. Lilv::Plugin lilvPlugin(cPlugin);
  649. CARLA_SAFE_ASSERT_CONTINUE(lilvPlugin.get_uri().is_uri());
  650. print_cached_plugin(get_cached_plugin_lv2(lv2World, lilvPlugin));
  651. }
  652. }
  653. #endif
  654. #ifndef USING_JUCE_FOR_VST2
  655. // -------------------------------------------------------------------------------------------------------------------
  656. // VST stuff
  657. // Check if plugin is currently processing
  658. static bool gVstIsProcessing = false;
  659. // Check if plugin needs idle
  660. static bool gVstNeedsIdle = false;
  661. // Check if plugin wants midi
  662. static bool gVstWantsMidi = false;
  663. // Check if plugin wants time
  664. static bool gVstWantsTime = false;
  665. // Current uniqueId for VST shell plugins
  666. static intptr_t gVstCurrentUniqueId = 0;
  667. // Supported Carla features
  668. static intptr_t vstHostCanDo(const char* const feature)
  669. {
  670. carla_debug("vstHostCanDo(\"%s\")", feature);
  671. if (std::strcmp(feature, "supplyIdle") == 0)
  672. return 1;
  673. if (std::strcmp(feature, "sendVstEvents") == 0)
  674. return 1;
  675. if (std::strcmp(feature, "sendVstMidiEvent") == 0)
  676. return 1;
  677. if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  678. return 1;
  679. if (std::strcmp(feature, "sendVstTimeInfo") == 0)
  680. {
  681. gVstWantsTime = true;
  682. return 1;
  683. }
  684. if (std::strcmp(feature, "receiveVstEvents") == 0)
  685. return 1;
  686. if (std::strcmp(feature, "receiveVstMidiEvent") == 0)
  687. return 1;
  688. if (std::strcmp(feature, "receiveVstTimeInfo") == 0)
  689. return -1;
  690. if (std::strcmp(feature, "reportConnectionChanges") == 0)
  691. return -1;
  692. if (std::strcmp(feature, "acceptIOChanges") == 0)
  693. return 1;
  694. if (std::strcmp(feature, "sizeWindow") == 0)
  695. return 1;
  696. if (std::strcmp(feature, "offline") == 0)
  697. return -1;
  698. if (std::strcmp(feature, "openFileSelector") == 0)
  699. return -1;
  700. if (std::strcmp(feature, "closeFileSelector") == 0)
  701. return -1;
  702. if (std::strcmp(feature, "startStopProcess") == 0)
  703. return 1;
  704. if (std::strcmp(feature, "supportShell") == 0)
  705. return 1;
  706. if (std::strcmp(feature, "shellCategory") == 0)
  707. return 1;
  708. if (std::strcmp(feature, "NIMKPIVendorSpecificCallbacks") == 0)
  709. return -1;
  710. // non-official features found in some plugins:
  711. // "asyncProcessing"
  712. // "editFile"
  713. // unimplemented
  714. carla_stderr("vstHostCanDo(\"%s\") - unknown feature", feature);
  715. return 0;
  716. }
  717. // Host-side callback
  718. 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)
  719. {
  720. carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
  721. effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
  722. static VstTimeInfo timeInfo;
  723. intptr_t ret = 0;
  724. switch (opcode)
  725. {
  726. case audioMasterAutomate:
  727. ret = 1;
  728. break;
  729. case audioMasterVersion:
  730. ret = kVstVersion;
  731. break;
  732. case audioMasterCurrentId:
  733. ret = gVstCurrentUniqueId;
  734. break;
  735. case DECLARE_VST_DEPRECATED(audioMasterWantMidi):
  736. if (gVstWantsMidi) { DISCOVERY_OUT("warning", "Plugin requested MIDI more than once"); }
  737. gVstWantsMidi = true;
  738. ret = 1;
  739. break;
  740. case audioMasterGetTime:
  741. if (! gVstIsProcessing) { DISCOVERY_OUT("warning", "Plugin requested timeInfo out of process"); }
  742. if (! gVstWantsTime) { DISCOVERY_OUT("warning", "Plugin requested timeInfo but didn't ask if host could do \"sendVstTimeInfo\""); }
  743. carla_zeroStruct(timeInfo);
  744. timeInfo.sampleRate = kSampleRate;
  745. // Tempo
  746. timeInfo.tempo = 120.0;
  747. timeInfo.flags |= kVstTempoValid;
  748. // Time Signature
  749. timeInfo.timeSigNumerator = 4;
  750. timeInfo.timeSigDenominator = 4;
  751. timeInfo.flags |= kVstTimeSigValid;
  752. ret = (intptr_t)&timeInfo;
  753. break;
  754. case DECLARE_VST_DEPRECATED(audioMasterTempoAt):
  755. ret = 120 * 10000;
  756. break;
  757. case DECLARE_VST_DEPRECATED(audioMasterGetNumAutomatableParameters):
  758. ret = carla_minPositive(effect->numParams, static_cast<int>(MAX_DEFAULT_PARAMETERS));
  759. break;
  760. case DECLARE_VST_DEPRECATED(audioMasterGetParameterQuantization):
  761. ret = 1; // full single float precision
  762. break;
  763. case DECLARE_VST_DEPRECATED(audioMasterNeedIdle):
  764. if (gVstNeedsIdle) { DISCOVERY_OUT("warning", "Plugin requested idle more than once"); }
  765. gVstNeedsIdle = true;
  766. ret = 1;
  767. break;
  768. case audioMasterGetSampleRate:
  769. ret = kSampleRatei;
  770. break;
  771. case audioMasterGetBlockSize:
  772. ret = kBufferSize;
  773. break;
  774. case DECLARE_VST_DEPRECATED(audioMasterWillReplaceOrAccumulate):
  775. ret = 1; // replace
  776. break;
  777. case audioMasterGetCurrentProcessLevel:
  778. ret = gVstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
  779. break;
  780. case audioMasterGetAutomationState:
  781. ret = kVstAutomationOff;
  782. break;
  783. case audioMasterGetVendorString:
  784. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  785. std::strcpy((char*)ptr, "falkTX");
  786. ret = 1;
  787. break;
  788. case audioMasterGetProductString:
  789. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  790. std::strcpy((char*)ptr, "Carla-Discovery");
  791. ret = 1;
  792. break;
  793. case audioMasterGetVendorVersion:
  794. ret = CARLA_VERSION_HEX;
  795. break;
  796. case audioMasterCanDo:
  797. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  798. ret = vstHostCanDo((const char*)ptr);
  799. break;
  800. case audioMasterGetLanguage:
  801. ret = kVstLangEnglish;
  802. break;
  803. default:
  804. carla_stdout("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)",
  805. effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, static_cast<double>(opt));
  806. break;
  807. }
  808. return ret;
  809. }
  810. static void do_vst2_check(lib_t& libHandle, const char* const filename, const bool doInit)
  811. {
  812. VST_Function vstFn = nullptr;
  813. #ifdef CARLA_OS_MAC
  814. BundleLoader bundleLoader;
  815. if (libHandle == nullptr)
  816. {
  817. if (! bundleLoader.load(filename))
  818. {
  819. DISCOVERY_OUT("error", "Failed to load VST2 bundle executable");
  820. return;
  821. }
  822. vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR("main_macho"));
  823. if (vstFn == nullptr)
  824. vstFn = (VST_Function)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR("VSTPluginMain"));
  825. if (vstFn == nullptr)
  826. {
  827. DISCOVERY_OUT("error", "Not a VST2 plugin");
  828. return;
  829. }
  830. }
  831. else
  832. #endif
  833. {
  834. vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain");
  835. if (vstFn == nullptr)
  836. {
  837. vstFn = lib_symbol<VST_Function>(libHandle, "main");
  838. if (vstFn == nullptr)
  839. {
  840. DISCOVERY_OUT("error", "Not a VST plugin");
  841. return;
  842. }
  843. }
  844. }
  845. AEffect* effect = vstFn(vstHostCallback);
  846. if (effect == nullptr || effect->magic != kEffectMagic)
  847. {
  848. DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
  849. return;
  850. }
  851. if (effect->uniqueID == 0)
  852. {
  853. DISCOVERY_OUT("warning", "Plugin doesn't have an Unique ID when first loaded");
  854. }
  855. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  856. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  857. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  858. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  859. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  860. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  861. if (effect->numPrograms > 0)
  862. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  863. const bool isShell = (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f) == kPlugCategShell);
  864. if (effect->uniqueID == 0 && !isShell)
  865. {
  866. DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID after being open");
  867. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  868. return;
  869. }
  870. gVstCurrentUniqueId = effect->uniqueID;
  871. char strBuf[STR_MAX+1];
  872. CarlaString cName;
  873. CarlaString cProduct;
  874. CarlaString cVendor;
  875. PluginCategory category;
  876. LinkedList<intptr_t> uniqueIds;
  877. if (isShell)
  878. {
  879. for (;;)
  880. {
  881. carla_zeroChars(strBuf, STR_MAX+1);
  882. gVstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
  883. if (gVstCurrentUniqueId == 0)
  884. break;
  885. uniqueIds.append(gVstCurrentUniqueId);
  886. }
  887. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  888. effect = nullptr;
  889. }
  890. else
  891. {
  892. uniqueIds.append(gVstCurrentUniqueId);
  893. }
  894. for (LinkedList<intptr_t>::Itenerator it = uniqueIds.begin2(); it.valid(); it.next())
  895. {
  896. gVstCurrentUniqueId = it.getValue(0);
  897. if (effect == nullptr)
  898. {
  899. effect = vstFn(vstHostCallback);
  900. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  901. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  902. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  903. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  904. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  905. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  906. if (effect->numPrograms > 0)
  907. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  908. }
  909. // get name
  910. carla_zeroChars(strBuf, STR_MAX+1);
  911. if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
  912. cName = strBuf;
  913. else
  914. cName.clear();
  915. // get product
  916. carla_zeroChars(strBuf, STR_MAX+1);
  917. if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
  918. cProduct = strBuf;
  919. else
  920. cProduct.clear();
  921. // get vendor
  922. carla_zeroChars(strBuf, STR_MAX+1);
  923. if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
  924. cVendor = strBuf;
  925. else
  926. cVendor.clear();
  927. // get category
  928. switch (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f))
  929. {
  930. case kPlugCategSynth:
  931. category = PLUGIN_CATEGORY_SYNTH;
  932. break;
  933. case kPlugCategAnalysis:
  934. category = PLUGIN_CATEGORY_UTILITY;
  935. break;
  936. case kPlugCategMastering:
  937. category = PLUGIN_CATEGORY_DYNAMICS;
  938. break;
  939. case kPlugCategRoomFx:
  940. category = PLUGIN_CATEGORY_DELAY;
  941. break;
  942. case kPlugCategRestoration:
  943. category = PLUGIN_CATEGORY_UTILITY;
  944. break;
  945. case kPlugCategGenerator:
  946. category = PLUGIN_CATEGORY_SYNTH;
  947. break;
  948. default:
  949. if (effect->flags & effFlagsIsSynth)
  950. category = PLUGIN_CATEGORY_SYNTH;
  951. else
  952. category = PLUGIN_CATEGORY_NONE;
  953. break;
  954. }
  955. // get everything else
  956. uint hints = 0x0;
  957. uint audioIns = static_cast<uint>(std::max(0, effect->numInputs));
  958. uint audioOuts = static_cast<uint>(std::max(0, effect->numOutputs));
  959. uint midiIns = 0;
  960. uint midiOuts = 0;
  961. uint parameters = static_cast<uint>(std::max(0, effect->numParams));
  962. if (effect->flags & effFlagsHasEditor)
  963. hints |= PLUGIN_HAS_CUSTOM_UI;
  964. if (effect->flags & effFlagsIsSynth)
  965. {
  966. hints |= PLUGIN_IS_SYNTH;
  967. midiIns = 1;
  968. }
  969. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) != 0)
  970. midiIns = 1;
  971. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  972. midiOuts = 1;
  973. // -----------------------------------------------------------------------
  974. // start crash-free plugin test
  975. if (doInit)
  976. {
  977. if (gVstNeedsIdle)
  978. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  979. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  980. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  981. if (gVstNeedsIdle)
  982. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  983. // Plugin might call wantMidi() during resume
  984. if (midiIns == 0 && gVstWantsMidi)
  985. {
  986. midiIns = 1;
  987. }
  988. float* bufferAudioIn[std::max(1U, audioIns)];
  989. float* bufferAudioOut[std::max(1U, audioOuts)];
  990. if (audioIns == 0)
  991. {
  992. bufferAudioIn[0] = nullptr;
  993. }
  994. else
  995. {
  996. for (uint j=0; j < audioIns; ++j)
  997. {
  998. bufferAudioIn[j] = new float[kBufferSize];
  999. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  1000. }
  1001. }
  1002. if (audioOuts == 0)
  1003. {
  1004. bufferAudioOut[0] = nullptr;
  1005. }
  1006. else
  1007. {
  1008. for (uint j=0; j < audioOuts; ++j)
  1009. {
  1010. bufferAudioOut[j] = new float[kBufferSize];
  1011. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  1012. }
  1013. }
  1014. struct VstEventsFixed {
  1015. int32_t numEvents;
  1016. intptr_t reserved;
  1017. VstEvent* data[2];
  1018. VstEventsFixed()
  1019. : numEvents(0),
  1020. reserved(0)
  1021. {
  1022. data[0] = data[1] = nullptr;
  1023. }
  1024. } events;
  1025. VstMidiEvent midiEvents[2];
  1026. carla_zeroStructs(midiEvents, 2);
  1027. midiEvents[0].type = kVstMidiType;
  1028. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  1029. midiEvents[0].midiData[0] = char(MIDI_STATUS_NOTE_ON);
  1030. midiEvents[0].midiData[1] = 64;
  1031. midiEvents[0].midiData[2] = 100;
  1032. midiEvents[1].type = kVstMidiType;
  1033. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  1034. midiEvents[1].midiData[0] = char(MIDI_STATUS_NOTE_OFF);
  1035. midiEvents[1].midiData[1] = 64;
  1036. midiEvents[1].deltaFrames = kBufferSize/2;
  1037. events.numEvents = 2;
  1038. events.data[0] = (VstEvent*)&midiEvents[0];
  1039. events.data[1] = (VstEvent*)&midiEvents[1];
  1040. // processing
  1041. gVstIsProcessing = true;
  1042. if (midiIns > 0)
  1043. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  1044. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != nullptr && effect->processReplacing != effect->DECLARE_VST_DEPRECATED(process))
  1045. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1046. else if (effect->DECLARE_VST_DEPRECATED(process) != nullptr)
  1047. effect->DECLARE_VST_DEPRECATED(process)(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1048. else
  1049. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  1050. gVstIsProcessing = false;
  1051. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  1052. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  1053. if (gVstNeedsIdle)
  1054. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1055. for (uint j=0; j < audioIns; ++j)
  1056. delete[] bufferAudioIn[j];
  1057. for (uint j=0; j < audioOuts; ++j)
  1058. delete[] bufferAudioOut[j];
  1059. }
  1060. // end crash-free plugin test
  1061. // -----------------------------------------------------------------------
  1062. DISCOVERY_OUT("init", "-----------");
  1063. DISCOVERY_OUT("build", BINARY_NATIVE);
  1064. DISCOVERY_OUT("hints", hints);
  1065. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  1066. DISCOVERY_OUT("name", cName.buffer());
  1067. DISCOVERY_OUT("label", cProduct.buffer());
  1068. DISCOVERY_OUT("maker", cVendor.buffer());
  1069. DISCOVERY_OUT("uniqueId", gVstCurrentUniqueId);
  1070. DISCOVERY_OUT("audio.ins", audioIns);
  1071. DISCOVERY_OUT("audio.outs", audioOuts);
  1072. DISCOVERY_OUT("midi.ins", midiIns);
  1073. DISCOVERY_OUT("midi.outs", midiOuts);
  1074. DISCOVERY_OUT("parameters.ins", parameters);
  1075. DISCOVERY_OUT("end", "------------");
  1076. gVstWantsMidi = false;
  1077. gVstWantsTime = false;
  1078. if (! isShell)
  1079. break;
  1080. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1081. effect = nullptr;
  1082. }
  1083. uniqueIds.clear();
  1084. if (effect != nullptr)
  1085. {
  1086. if (gVstNeedsIdle)
  1087. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1088. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1089. }
  1090. #ifndef CARLA_OS_MAC
  1091. return;
  1092. // unused
  1093. (void)filename;
  1094. #endif
  1095. }
  1096. #endif // ! USING_JUCE_FOR_VST2
  1097. #ifndef USING_JUCE_FOR_VST3
  1098. static uint32_t V3_API v3_ref_static(void*) { return 1; }
  1099. static uint32_t V3_API v3_unref_static(void*) { return 0; }
  1100. struct carla_v3_host_application : v3_host_application_cpp {
  1101. carla_v3_host_application()
  1102. {
  1103. query_interface = carla_query_interface;
  1104. ref = v3_ref_static;
  1105. unref = v3_unref_static;
  1106. app.get_name = carla_get_name;
  1107. app.create_instance = carla_create_instance;
  1108. }
  1109. static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface)
  1110. {
  1111. if (v3_tuid_match(iid, v3_funknown_iid) ||
  1112. v3_tuid_match(iid, v3_host_application_iid))
  1113. {
  1114. *iface = self;
  1115. return V3_OK;
  1116. }
  1117. *iface = nullptr;
  1118. return V3_NO_INTERFACE;
  1119. }
  1120. static v3_result V3_API carla_get_name(void*, v3_str_128 name)
  1121. {
  1122. static const char hostname[] = "Carla-Discovery\0";
  1123. for (size_t i=0; i<sizeof(hostname); ++i)
  1124. name[i] = hostname[i];
  1125. return V3_OK;
  1126. }
  1127. static v3_result V3_API carla_create_instance(void*, v3_tuid, v3_tuid, void**) { return V3_NOT_IMPLEMENTED; }
  1128. };
  1129. struct carla_v3_param_changes : v3_param_changes_cpp {
  1130. carla_v3_param_changes()
  1131. {
  1132. query_interface = carla_query_interface;
  1133. ref = v3_ref_static;
  1134. unref = v3_unref_static;
  1135. changes.get_param_count = carla_get_param_count;
  1136. changes.get_param_data = carla_get_param_data;
  1137. changes.add_param_data = carla_add_param_data;
  1138. }
  1139. static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface)
  1140. {
  1141. if (v3_tuid_match(iid, v3_funknown_iid) ||
  1142. v3_tuid_match(iid, v3_param_changes_iid))
  1143. {
  1144. *iface = self;
  1145. return V3_OK;
  1146. }
  1147. *iface = nullptr;
  1148. return V3_NO_INTERFACE;
  1149. }
  1150. static int32_t V3_API carla_get_param_count(void*) { return 0; }
  1151. static v3_param_value_queue** V3_API carla_get_param_data(void*, int32_t) { return nullptr; }
  1152. static v3_param_value_queue** V3_API carla_add_param_data(void*, v3_param_id*, int32_t*) { return nullptr; }
  1153. };
  1154. struct carla_v3_event_list : v3_event_list_cpp {
  1155. carla_v3_event_list()
  1156. {
  1157. query_interface = carla_query_interface;
  1158. ref = v3_ref_static;
  1159. unref = v3_unref_static;
  1160. list.get_event_count = carla_get_event_count;
  1161. list.get_event = carla_get_event;
  1162. list.add_event = carla_add_event;
  1163. }
  1164. static v3_result V3_API carla_query_interface(void* const self, const v3_tuid iid, void** const iface)
  1165. {
  1166. if (v3_tuid_match(iid, v3_funknown_iid) ||
  1167. v3_tuid_match(iid, v3_event_list_iid))
  1168. {
  1169. *iface = self;
  1170. return V3_OK;
  1171. }
  1172. *iface = nullptr;
  1173. return V3_NO_INTERFACE;
  1174. }
  1175. static uint32_t V3_API carla_get_event_count(void*) { return 0; }
  1176. static v3_result V3_API carla_get_event(void*, int32_t, v3_event*) { return V3_NOT_IMPLEMENTED; }
  1177. static v3_result V3_API carla_add_event(void*, v3_event*) { return V3_NOT_IMPLEMENTED; }
  1178. };
  1179. static void do_vst3_check(lib_t& libHandle, const char* const filename, const bool doInit)
  1180. {
  1181. V3_ENTRYFN v3_entry = nullptr;
  1182. V3_EXITFN v3_exit = nullptr;
  1183. V3_GETFN v3_get = nullptr;
  1184. #ifdef CARLA_OS_MAC
  1185. BundleLoader bundleLoader;
  1186. #endif
  1187. // if passed filename is not a plugin binary directly, inspect bundle and find one
  1188. if (libHandle == nullptr)
  1189. {
  1190. #ifdef CARLA_OS_MAC
  1191. if (! bundleLoader.load(filename))
  1192. {
  1193. DISCOVERY_OUT("error", "Failed to load VST3 bundle executable");
  1194. return;
  1195. }
  1196. v3_entry = (V3_ENTRYFN)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR(V3_ENTRYFNNAME));
  1197. v3_exit = (V3_EXITFN)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR(V3_EXITFNNAME));
  1198. v3_get = (V3_GETFN)CFBundleGetFunctionPointerForName(bundleLoader.getRef(), CFSTR(V3_GETFNNAME));
  1199. #else
  1200. water::String binaryfilename = filename;
  1201. if (!binaryfilename.endsWithChar(CARLA_OS_SEP))
  1202. binaryfilename += CARLA_OS_SEP_STR;
  1203. binaryfilename += "Contents" CARLA_OS_SEP_STR V3_CONTENT_DIR CARLA_OS_SEP_STR;
  1204. binaryfilename += water::File(filename).getFileNameWithoutExtension();
  1205. # ifdef CARLA_OS_WIN
  1206. binaryfilename += ".vst3";
  1207. # else
  1208. binaryfilename += ".so";
  1209. # endif
  1210. if (! water::File(binaryfilename).existsAsFile())
  1211. {
  1212. DISCOVERY_OUT("error", "Failed to find a suitable VST3 bundle binary");
  1213. return;
  1214. }
  1215. libHandle = lib_open(binaryfilename.toRawUTF8());
  1216. if (libHandle == nullptr)
  1217. {
  1218. print_lib_error(filename);
  1219. return;
  1220. }
  1221. #endif
  1222. }
  1223. #ifndef CARLA_OS_MAC
  1224. v3_entry = lib_symbol<V3_ENTRYFN>(libHandle, V3_ENTRYFNNAME);
  1225. v3_exit = lib_symbol<V3_EXITFN>(libHandle, V3_EXITFNNAME);
  1226. v3_get = lib_symbol<V3_GETFN>(libHandle, V3_GETFNNAME);
  1227. #endif
  1228. // ensure entry and exit points are available
  1229. if (v3_entry == nullptr || v3_exit == nullptr || v3_get == nullptr)
  1230. {
  1231. DISCOVERY_OUT("error", "Not a VST3 plugin");
  1232. return;
  1233. }
  1234. // call entry point
  1235. #if defined(CARLA_OS_MAC)
  1236. v3_entry(bundleLoader.getRef());
  1237. #elif defined(CARLA_OS_WIN)
  1238. v3_entry();
  1239. #else
  1240. v3_entry(libHandle);
  1241. #endif
  1242. carla_v3_host_application hostApplication;
  1243. carla_v3_host_application* hostApplicationPtr = &hostApplication;
  1244. v3_funknown** const hostContext = (v3_funknown**)&hostApplicationPtr;
  1245. // fetch initial factory
  1246. v3_plugin_factory** factory1 = v3_get();
  1247. CARLA_SAFE_ASSERT_RETURN(factory1 != nullptr, v3_exit());
  1248. // get factory info
  1249. v3_factory_info factoryInfo = {};
  1250. CARLA_SAFE_ASSERT_RETURN(v3_cpp_obj(factory1)->get_factory_info(factory1, &factoryInfo) == V3_OK, v3_exit());
  1251. // get num classes
  1252. const int32_t numClasses = v3_cpp_obj(factory1)->num_classes(factory1);
  1253. CARLA_SAFE_ASSERT_RETURN(numClasses > 0, v3_exit());
  1254. // query 2nd factory
  1255. v3_plugin_factory_2** factory2 = nullptr;
  1256. if (v3_cpp_obj_query_interface(factory1, v3_plugin_factory_2_iid, &factory2) == V3_OK)
  1257. {
  1258. CARLA_SAFE_ASSERT_RETURN(factory2 != nullptr, v3_exit());
  1259. }
  1260. else
  1261. {
  1262. CARLA_SAFE_ASSERT(factory2 == nullptr);
  1263. factory2 = nullptr;
  1264. }
  1265. // query 3rd factory
  1266. v3_plugin_factory_3** factory3 = nullptr;
  1267. if (factory2 != nullptr && v3_cpp_obj_query_interface(factory2, v3_plugin_factory_3_iid, &factory3) == V3_OK)
  1268. {
  1269. CARLA_SAFE_ASSERT_RETURN(factory3 != nullptr, v3_exit());
  1270. }
  1271. else
  1272. {
  1273. CARLA_SAFE_ASSERT(factory3 == nullptr);
  1274. factory3 = nullptr;
  1275. }
  1276. // set host context (application) if 3rd factory provided
  1277. if (factory3 != nullptr)
  1278. v3_cpp_obj(factory3)->set_host_context(factory3, hostContext);
  1279. // go through all relevant classes
  1280. for (int32_t i=0; i<numClasses; ++i)
  1281. {
  1282. // v3_class_info_2 is ABI compatible with v3_class_info
  1283. union {
  1284. v3_class_info v1;
  1285. v3_class_info_2 v2;
  1286. } classInfo = {};
  1287. if (factory2 != nullptr)
  1288. v3_cpp_obj(factory2)->get_class_info_2(factory2, i, &classInfo.v2);
  1289. else
  1290. v3_cpp_obj(factory1)->get_class_info(factory1, i, &classInfo.v1);
  1291. // safety check
  1292. CARLA_SAFE_ASSERT_CONTINUE(classInfo.v1.cardinality == 0x7FFFFFFF);
  1293. // only check for audio plugins
  1294. if (std::strcmp(classInfo.v1.category, "Audio Module Class") != 0)
  1295. continue;
  1296. // create instance
  1297. void* instance = nullptr;
  1298. CARLA_SAFE_ASSERT_CONTINUE(v3_cpp_obj(factory1)->create_instance(factory1, classInfo.v1.class_id, v3_component_iid, &instance) == V3_OK);
  1299. CARLA_SAFE_ASSERT_CONTINUE(instance != nullptr);
  1300. // initialize instance
  1301. v3_component** const component = static_cast<v3_component**>(instance);
  1302. CARLA_SAFE_ASSERT_CONTINUE(v3_cpp_obj_initialize(component, hostContext) == V3_OK);
  1303. // create edit controller
  1304. v3_edit_controller** controller = nullptr;
  1305. bool shouldTerminateController;
  1306. if (v3_cpp_obj_query_interface(component, v3_edit_controller_iid, &controller) != V3_OK)
  1307. controller = nullptr;
  1308. if (controller != nullptr)
  1309. {
  1310. // got edit controller from casting component, assume they belong to the same object
  1311. shouldTerminateController = false;
  1312. }
  1313. else
  1314. {
  1315. // try to create edit controller from factory
  1316. v3_tuid uid = {};
  1317. if (v3_cpp_obj(component)->get_controller_class_id(component, uid) == V3_OK)
  1318. {
  1319. instance = nullptr;
  1320. if (v3_cpp_obj(factory1)->create_instance(factory1, uid, v3_edit_controller_iid, &instance) == V3_OK && instance != nullptr)
  1321. controller = static_cast<v3_edit_controller**>(instance);
  1322. }
  1323. if (controller == nullptr)
  1324. {
  1325. DISCOVERY_OUT("warning", "Plugin '" << classInfo.v1.name << "' does not have an edit controller");
  1326. v3_cpp_obj_terminate(component);
  1327. v3_cpp_obj_unref(component);
  1328. continue;
  1329. }
  1330. // component is separate from controller, needs its dedicated initialize and terminate
  1331. shouldTerminateController = true;
  1332. v3_cpp_obj_initialize(controller, hostContext);
  1333. }
  1334. // fill in all the details
  1335. uint hints = 0x0;
  1336. int audioIns = 0;
  1337. int audioOuts = 0;
  1338. int cvIns = 0;
  1339. int cvOuts = 0;
  1340. int parameterIns = 0;
  1341. int parameterOuts = 0;
  1342. const int32_t numAudioInputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_AUDIO, V3_INPUT);
  1343. const int32_t numEventInputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_EVENT, V3_INPUT);
  1344. const int32_t numAudioOutputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_AUDIO, V3_OUTPUT);
  1345. const int32_t numEventOutputBuses = v3_cpp_obj(component)->get_bus_count(component, V3_EVENT, V3_OUTPUT);
  1346. const int32_t numParameters = v3_cpp_obj(controller)->get_parameter_count(controller);
  1347. CARLA_SAFE_ASSERT(numAudioInputBuses >= 0);
  1348. CARLA_SAFE_ASSERT(numEventInputBuses >= 0);
  1349. CARLA_SAFE_ASSERT(numAudioOutputBuses >= 0);
  1350. CARLA_SAFE_ASSERT(numEventOutputBuses >= 0);
  1351. CARLA_SAFE_ASSERT(numParameters >= 0);
  1352. for (int32_t j=0; j<numAudioInputBuses; ++j)
  1353. {
  1354. v3_bus_info busInfo = {};
  1355. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_INPUT, j, &busInfo) == V3_OK);
  1356. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1357. cvIns += busInfo.channel_count;
  1358. else
  1359. audioIns += busInfo.channel_count;
  1360. }
  1361. for (int32_t j=0; j<numAudioOutputBuses; ++j)
  1362. {
  1363. v3_bus_info busInfo = {};
  1364. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_OUTPUT, j, &busInfo) == V3_OK);
  1365. if (busInfo.flags & V3_IS_CONTROL_VOLTAGE)
  1366. cvOuts += busInfo.channel_count;
  1367. else
  1368. audioOuts += busInfo.channel_count;
  1369. }
  1370. for (int32_t j=0; j<numParameters; ++j)
  1371. {
  1372. v3_param_info paramInfo = {};
  1373. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(controller)->get_parameter_info(controller, j, &paramInfo) == V3_OK);
  1374. if (paramInfo.flags & (V3_PARAM_IS_BYPASS|V3_PARAM_IS_HIDDEN|V3_PARAM_PROGRAM_CHANGE))
  1375. continue;
  1376. if (paramInfo.flags & V3_PARAM_READ_ONLY)
  1377. ++parameterOuts;
  1378. else
  1379. ++parameterIns;
  1380. }
  1381. if (v3_plugin_view** const view = v3_cpp_obj(controller)->create_view(controller, "view"))
  1382. {
  1383. if (v3_cpp_obj(view)->is_platform_type_supported(view, V3_VIEW_PLATFORM_TYPE_NATIVE) == V3_TRUE)
  1384. hints |= PLUGIN_HAS_CUSTOM_UI;
  1385. v3_cpp_obj_unref(view);
  1386. }
  1387. if (factory2 != nullptr && std::strstr(classInfo.v2.sub_categories, "Instrument") != nullptr)
  1388. hints |= PLUGIN_IS_SYNTH;
  1389. if (doInit)
  1390. {
  1391. v3_audio_processor** processor = nullptr;
  1392. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj_query_interface(component, v3_audio_processor_iid, &processor) == V3_OK);
  1393. CARLA_SAFE_ASSERT_BREAK(processor != nullptr);
  1394. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(processor)->can_process_sample_size(processor, V3_SAMPLE_32) == V3_OK);
  1395. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->set_active(component, true) == V3_OK);
  1396. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->set_active(component, false) == V3_OK);
  1397. v3_process_setup setup = { V3_REALTIME, V3_SAMPLE_32, kBufferSize, kSampleRate };
  1398. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(processor)->setup_processing(processor, &setup) == V3_OK);
  1399. for (int32_t j=0; j<numAudioInputBuses; ++j)
  1400. {
  1401. v3_bus_info busInfo = {};
  1402. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_INPUT, j, &busInfo) == V3_OK);
  1403. if ((busInfo.flags & V3_DEFAULT_ACTIVE) == 0x0) {
  1404. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->activate_bus(component, V3_AUDIO, V3_INPUT, j, true) == V3_OK);
  1405. }
  1406. }
  1407. for (int32_t j=0; j<numAudioOutputBuses; ++j)
  1408. {
  1409. v3_bus_info busInfo = {};
  1410. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->get_bus_info(component, V3_AUDIO, V3_OUTPUT, j, &busInfo) == V3_OK);
  1411. if ((busInfo.flags & V3_DEFAULT_ACTIVE) == 0x0) {
  1412. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->activate_bus(component, V3_AUDIO, V3_OUTPUT, j, true) == V3_OK);
  1413. }
  1414. }
  1415. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->set_active(component, true) == V3_OK);
  1416. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(processor)->set_processing(processor, true) == V3_OK);
  1417. float* bufferAudioIn[(uint)std::max(1, audioIns + cvIns)];
  1418. float* bufferAudioOut[(uint)std::max(1, audioOuts + cvOuts)];
  1419. if (audioIns + cvIns == 0)
  1420. {
  1421. bufferAudioIn[0] = nullptr;
  1422. }
  1423. else
  1424. {
  1425. for (int j=0; j < audioIns + cvIns; ++j)
  1426. {
  1427. bufferAudioIn[j] = new float[kBufferSize];
  1428. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  1429. }
  1430. }
  1431. if (audioOuts + cvOuts == 0)
  1432. {
  1433. bufferAudioOut[0] = nullptr;
  1434. }
  1435. else
  1436. {
  1437. for (int j=0; j < audioOuts + cvOuts; ++j)
  1438. {
  1439. bufferAudioOut[j] = new float[kBufferSize];
  1440. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  1441. }
  1442. }
  1443. carla_v3_event_list eventList;
  1444. carla_v3_event_list* eventListPtr = &eventList;
  1445. carla_v3_param_changes paramChanges;
  1446. carla_v3_param_changes* paramChangesPtr = &paramChanges;
  1447. v3_audio_bus_buffers processInputs = { audioIns + cvIns, 0, { bufferAudioIn } };
  1448. v3_audio_bus_buffers processOutputs = { audioOuts + cvOuts, 0, { bufferAudioOut } };
  1449. v3_process_context processContext = {};
  1450. processContext.sample_rate = kSampleRate;
  1451. v3_process_data processData = {
  1452. V3_REALTIME,
  1453. V3_SAMPLE_32,
  1454. kBufferSize,
  1455. audioIns + cvIns,
  1456. audioOuts + cvOuts,
  1457. &processInputs,
  1458. &processOutputs,
  1459. (v3_param_changes**)&paramChangesPtr,
  1460. (v3_param_changes**)&paramChangesPtr,
  1461. (v3_event_list**)&eventListPtr,
  1462. (v3_event_list**)&eventListPtr,
  1463. &processContext
  1464. };
  1465. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(processor)->process(processor, &processData) == V3_OK);
  1466. for (int j=0; j < audioIns + cvIns; ++j)
  1467. delete[] bufferAudioIn[j];
  1468. for (int j=0; j < audioOuts + cvOuts; ++j)
  1469. delete[] bufferAudioOut[j];
  1470. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(processor)->set_processing(processor, false) == V3_OK);
  1471. CARLA_SAFE_ASSERT_BREAK(v3_cpp_obj(component)->set_active(component, false) == V3_OK);
  1472. v3_cpp_obj_unref(processor);
  1473. }
  1474. if (shouldTerminateController)
  1475. v3_cpp_obj_terminate(controller);
  1476. v3_cpp_obj_unref(controller);
  1477. v3_cpp_obj_terminate(component);
  1478. v3_cpp_obj_unref(component);
  1479. DISCOVERY_OUT("init", "-----------");
  1480. DISCOVERY_OUT("build", BINARY_NATIVE);
  1481. DISCOVERY_OUT("hints", hints);
  1482. DISCOVERY_OUT("category", getPluginCategoryAsString(factory2 != nullptr ? getPluginCategoryFromV3SubCategories(classInfo.v2.sub_categories)
  1483. : getPluginCategoryFromName(classInfo.v1.name)));
  1484. DISCOVERY_OUT("name", classInfo.v1.name);
  1485. DISCOVERY_OUT("label", tuid2str(classInfo.v1.class_id));
  1486. DISCOVERY_OUT("maker", (factory2 != nullptr ? classInfo.v2.vendor : factoryInfo.vendor));
  1487. DISCOVERY_OUT("audio.ins", audioIns);
  1488. DISCOVERY_OUT("audio.outs", audioOuts);
  1489. DISCOVERY_OUT("cv.ins", cvIns);
  1490. DISCOVERY_OUT("cv.outs", cvOuts);
  1491. DISCOVERY_OUT("midi.ins", numEventInputBuses);
  1492. DISCOVERY_OUT("midi.outs", numEventOutputBuses);
  1493. DISCOVERY_OUT("parameters.ins", parameterIns);
  1494. DISCOVERY_OUT("parameters.outs", parameterOuts);
  1495. DISCOVERY_OUT("end", "------------");
  1496. }
  1497. // unref interfaces
  1498. if (factory3 != nullptr)
  1499. v3_cpp_obj_unref(factory3);
  1500. if (factory2 != nullptr)
  1501. v3_cpp_obj_unref(factory2);
  1502. v3_cpp_obj_unref(factory1);
  1503. v3_exit();
  1504. }
  1505. #endif // ! USING_JUCE_FOR_VST3
  1506. #ifdef USING_JUCE
  1507. // -------------------------------------------------------------------------------------------------------------------
  1508. // find all available plugin audio ports
  1509. static void findMaxTotalChannels(juce::AudioProcessor* const filter, int& maxTotalIns, int& maxTotalOuts)
  1510. {
  1511. filter->enableAllBuses();
  1512. const int numInputBuses = filter->getBusCount(true);
  1513. const int numOutputBuses = filter->getBusCount(false);
  1514. if (numInputBuses > 1 || numOutputBuses > 1)
  1515. {
  1516. maxTotalIns = maxTotalOuts = 0;
  1517. for (int i = 0; i < numInputBuses; ++i)
  1518. maxTotalIns += filter->getChannelCountOfBus(true, i);
  1519. for (int i = 0; i < numOutputBuses; ++i)
  1520. maxTotalOuts += filter->getChannelCountOfBus(false, i);
  1521. }
  1522. else
  1523. {
  1524. maxTotalIns = numInputBuses > 0 ? filter->getBus(true, 0)->getMaxSupportedChannels(64) : 0;
  1525. maxTotalOuts = numOutputBuses > 0 ? filter->getBus(false, 0)->getMaxSupportedChannels(64) : 0;
  1526. }
  1527. }
  1528. // -------------------------------------------------------------------------------------------------------------------
  1529. static bool do_juce_check(const char* const filename_, const char* const stype, const bool doInit)
  1530. {
  1531. CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype[0] != 0, false) // FIXME
  1532. carla_debug("do_juce_check(%s, %s, %s)", filename_, stype, bool2str(doInit));
  1533. CarlaJUCE::initialiseJuce_GUI();
  1534. juce::String filename;
  1535. #ifdef CARLA_OS_WIN
  1536. // Fix for wine usage
  1537. if (juce::File("Z:\\usr\\").isDirectory() && filename_[0] == '/')
  1538. {
  1539. filename = filename_;
  1540. filename.replace("/", "\\");
  1541. filename = "Z:" + filename;
  1542. }
  1543. else
  1544. #endif
  1545. filename = juce::File(filename_).getFullPathName();
  1546. CarlaScopedPointer<juce::AudioPluginFormat> pluginFormat;
  1547. /* */ if (std::strcmp(stype, "VST2") == 0)
  1548. {
  1549. #if JUCE_PLUGINHOST_VST
  1550. pluginFormat = new juce::VSTPluginFormat();
  1551. #else
  1552. DISCOVERY_OUT("error", "VST2 support not available");
  1553. return false;
  1554. #endif
  1555. }
  1556. else if (std::strcmp(stype, "VST3") == 0)
  1557. {
  1558. #if JUCE_PLUGINHOST_VST3
  1559. pluginFormat = new juce::VST3PluginFormat();
  1560. #else
  1561. DISCOVERY_OUT("error", "VST3 support not available");
  1562. return false;
  1563. #endif
  1564. }
  1565. else if (std::strcmp(stype, "AU") == 0)
  1566. {
  1567. #if JUCE_PLUGINHOST_AU
  1568. pluginFormat = new juce::AudioUnitPluginFormat();
  1569. #else
  1570. DISCOVERY_OUT("error", "AU support not available");
  1571. return false;
  1572. #endif
  1573. }
  1574. if (pluginFormat == nullptr)
  1575. {
  1576. DISCOVERY_OUT("error", stype << " support not available");
  1577. return false;
  1578. }
  1579. #ifdef CARLA_OS_WIN
  1580. CARLA_CUSTOM_SAFE_ASSERT_RETURN("Plugin file/folder does not exist", juce::File(filename).exists(), false);
  1581. #endif
  1582. CARLA_SAFE_ASSERT_RETURN(pluginFormat->fileMightContainThisPluginType(filename), false);
  1583. juce::OwnedArray<juce::PluginDescription> results;
  1584. pluginFormat->findAllTypesForFile(results, filename);
  1585. if (results.size() == 0)
  1586. {
  1587. #if defined(CARLA_OS_MAC) && defined(__aarch64__)
  1588. if (std::strcmp(stype, "VST2") == 0 || std::strcmp(stype, "VST3") == 0)
  1589. return true;
  1590. #endif
  1591. DISCOVERY_OUT("error", "No plugins found");
  1592. return false;
  1593. }
  1594. for (juce::PluginDescription **it = results.begin(), **end = results.end(); it != end; ++it)
  1595. {
  1596. juce::PluginDescription* const desc(*it);
  1597. uint hints = 0x0;
  1598. int audioIns = desc->numInputChannels;
  1599. int audioOuts = desc->numOutputChannels;
  1600. int midiIns = 0;
  1601. int midiOuts = 0;
  1602. int parameters = 0;
  1603. if (desc->isInstrument)
  1604. {
  1605. hints |= PLUGIN_IS_SYNTH;
  1606. midiIns = 1;
  1607. }
  1608. if (doInit)
  1609. {
  1610. if (std::unique_ptr<juce::AudioPluginInstance> instance
  1611. = pluginFormat->createInstanceFromDescription(*desc, kSampleRate, kBufferSize))
  1612. {
  1613. CarlaJUCE::idleJuce_GUI();
  1614. findMaxTotalChannels(instance.get(), audioIns, audioOuts);
  1615. instance->refreshParameterList();
  1616. parameters = instance->getParameters().size();
  1617. if (instance->hasEditor())
  1618. hints |= PLUGIN_HAS_CUSTOM_UI;
  1619. if (instance->acceptsMidi())
  1620. midiIns = 1;
  1621. if (instance->producesMidi())
  1622. midiOuts = 1;
  1623. }
  1624. }
  1625. DISCOVERY_OUT("init", "-----------");
  1626. DISCOVERY_OUT("build", BINARY_NATIVE);
  1627. DISCOVERY_OUT("hints", hints);
  1628. DISCOVERY_OUT("category", getPluginCategoryAsString(getPluginCategoryFromName(desc->category.toRawUTF8())));
  1629. DISCOVERY_OUT("name", desc->descriptiveName);
  1630. DISCOVERY_OUT("label", desc->name);
  1631. DISCOVERY_OUT("maker", desc->manufacturerName);
  1632. DISCOVERY_OUT("uniqueId", desc->uniqueId);
  1633. DISCOVERY_OUT("audio.ins", audioIns);
  1634. DISCOVERY_OUT("audio.outs", audioOuts);
  1635. DISCOVERY_OUT("midi.ins", midiIns);
  1636. DISCOVERY_OUT("midi.outs", midiOuts);
  1637. DISCOVERY_OUT("parameters.ins", parameters);
  1638. DISCOVERY_OUT("end", "------------");
  1639. }
  1640. CarlaJUCE::idleJuce_GUI();
  1641. CarlaJUCE::shutdownJuce_GUI();
  1642. return false;
  1643. }
  1644. #endif // USING_JUCE_FOR_VST2
  1645. static void do_fluidsynth_check(const char* const filename, const PluginType type, const bool doInit)
  1646. {
  1647. #ifdef HAVE_FLUIDSYNTH
  1648. const water::File file(filename);
  1649. if (! file.existsAsFile())
  1650. {
  1651. DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
  1652. return;
  1653. }
  1654. if (type == PLUGIN_SF2 && ! fluid_is_soundfont(filename))
  1655. {
  1656. DISCOVERY_OUT("error", "Not a SF2 file");
  1657. return;
  1658. }
  1659. int programs = 0;
  1660. if (doInit)
  1661. {
  1662. fluid_settings_t* const f_settings = new_fluid_settings();
  1663. CARLA_SAFE_ASSERT_RETURN(f_settings != nullptr,);
  1664. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  1665. CARLA_SAFE_ASSERT_RETURN(f_synth != nullptr,);
  1666. const int f_id_test = fluid_synth_sfload(f_synth, filename, 0);
  1667. if (f_id_test < 0)
  1668. {
  1669. DISCOVERY_OUT("error", "Failed to load SF2 file");
  1670. return;
  1671. }
  1672. #if FLUIDSYNTH_VERSION_MAJOR >= 2
  1673. const int f_id = f_id_test;
  1674. #else
  1675. const uint f_id = static_cast<uint>(f_id_test);
  1676. #endif
  1677. if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id))
  1678. {
  1679. #if FLUIDSYNTH_VERSION_MAJOR >= 2
  1680. fluid_sfont_iteration_start(f_sfont);
  1681. for (; fluid_sfont_iteration_next(f_sfont);)
  1682. ++programs;
  1683. #else
  1684. fluid_preset_t f_preset;
  1685. f_sfont->iteration_start(f_sfont);
  1686. for (; f_sfont->iteration_next(f_sfont, &f_preset);)
  1687. ++programs;
  1688. #endif
  1689. }
  1690. delete_fluid_synth(f_synth);
  1691. delete_fluid_settings(f_settings);
  1692. }
  1693. CarlaString name(file.getFileNameWithoutExtension().toRawUTF8());
  1694. CarlaString label(name);
  1695. // 2 channels
  1696. DISCOVERY_OUT("init", "-----------");
  1697. DISCOVERY_OUT("build", BINARY_NATIVE);
  1698. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1699. DISCOVERY_OUT("category", "synth");
  1700. DISCOVERY_OUT("name", name.buffer());
  1701. DISCOVERY_OUT("label", label.buffer());
  1702. DISCOVERY_OUT("audio.outs", 2);
  1703. DISCOVERY_OUT("midi.ins", 1);
  1704. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1705. DISCOVERY_OUT("parameters.outs", 1);
  1706. DISCOVERY_OUT("end", "------------");
  1707. // 16 channels
  1708. if (doInit && (name.isEmpty() || programs <= 1))
  1709. return;
  1710. name += " (16 outputs)";
  1711. DISCOVERY_OUT("init", "-----------");
  1712. DISCOVERY_OUT("build", BINARY_NATIVE);
  1713. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1714. DISCOVERY_OUT("category", "synth");
  1715. DISCOVERY_OUT("name", name.buffer());
  1716. DISCOVERY_OUT("label", label.buffer());
  1717. DISCOVERY_OUT("audio.outs", 32);
  1718. DISCOVERY_OUT("midi.ins", 1);
  1719. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1720. DISCOVERY_OUT("parameters.outs", 1);
  1721. DISCOVERY_OUT("end", "------------");
  1722. #else // HAVE_FLUIDSYNTH
  1723. DISCOVERY_OUT("error", "SF2 support not available");
  1724. return;
  1725. // unused
  1726. (void)filename;
  1727. (void)type;
  1728. (void)doInit;
  1729. #endif
  1730. }
  1731. // -------------------------------------------------------------------------------------------------------------------
  1732. #ifndef BUILD_BRIDGE
  1733. static void do_jsfx_check(const char* const filename, bool doInit)
  1734. {
  1735. const water::File file(filename);
  1736. ysfx_config_u config(ysfx_config_new());
  1737. ysfx_register_builtin_audio_formats(config.get());
  1738. ysfx_guess_file_roots(config.get(), filename);
  1739. ysfx_set_log_reporter(config.get(), &CarlaJsfxLogging::logErrorsOnly);
  1740. ysfx_u effect(ysfx_new(config.get()));
  1741. uint hints = 0;
  1742. // do not attempt to compile it, because the import path is not known
  1743. (void)doInit;
  1744. if (! ysfx_load_file(effect.get(), filename, 0))
  1745. {
  1746. DISCOVERY_OUT("error", "Cannot read the JSFX header");
  1747. return;
  1748. }
  1749. const char* const name = ysfx_get_name(effect.get());
  1750. // author and category are extracted from the pseudo-tags
  1751. const char* const author = ysfx_get_author(effect.get());
  1752. const CB::PluginCategory category = CarlaJsfxCategories::getFromEffect(effect.get());
  1753. const uint32_t audioIns = ysfx_get_num_inputs(effect.get());
  1754. const uint32_t audioOuts = ysfx_get_num_outputs(effect.get());
  1755. const uint32_t midiIns = 1;
  1756. const uint32_t midiOuts = 1;
  1757. uint32_t parameters = 0;
  1758. for (uint32_t sliderIndex = 0; sliderIndex < ysfx_max_sliders; ++sliderIndex)
  1759. {
  1760. if (ysfx_slider_exists(effect.get(), sliderIndex))
  1761. ++parameters;
  1762. }
  1763. DISCOVERY_OUT("init", "-----------");
  1764. DISCOVERY_OUT("build", BINARY_NATIVE);
  1765. DISCOVERY_OUT("hints", hints);
  1766. DISCOVERY_OUT("category", getPluginCategoryAsString(category));
  1767. DISCOVERY_OUT("name", name);
  1768. DISCOVERY_OUT("maker", author);
  1769. DISCOVERY_OUT("label", filename);
  1770. DISCOVERY_OUT("audio.ins", audioIns);
  1771. DISCOVERY_OUT("audio.outs", audioOuts);
  1772. DISCOVERY_OUT("midi.ins", midiIns);
  1773. DISCOVERY_OUT("midi.outs", midiOuts);
  1774. DISCOVERY_OUT("parameters.ins", parameters);
  1775. DISCOVERY_OUT("end", "------------");
  1776. }
  1777. #endif
  1778. // ------------------------------ main entry point ------------------------------
  1779. int main(int argc, char* argv[])
  1780. {
  1781. if (argc != 3)
  1782. {
  1783. carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
  1784. return 1;
  1785. }
  1786. const char* const stype = argv[1];
  1787. const char* const filename = argv[2];
  1788. const PluginType type = getPluginTypeFromString(stype);
  1789. CarlaString filenameCheck(filename);
  1790. filenameCheck.toLower();
  1791. bool openLib = false;
  1792. lib_t handle = nullptr;
  1793. switch (type)
  1794. {
  1795. case PLUGIN_LADSPA:
  1796. case PLUGIN_DSSI:
  1797. case PLUGIN_VST2:
  1798. openLib = true;
  1799. break;
  1800. case PLUGIN_VST3:
  1801. openLib = water::File(filename).existsAsFile();
  1802. break;
  1803. default:
  1804. break;
  1805. }
  1806. if (type != PLUGIN_SF2 && filenameCheck.contains("fluidsynth", true))
  1807. {
  1808. DISCOVERY_OUT("info", "skipping fluidsynth based plugin");
  1809. return 0;
  1810. }
  1811. #ifdef CARLA_OS_MAC
  1812. if (type == PLUGIN_VST2 && (filenameCheck.endsWith(".vst") || filenameCheck.endsWith(".vst/")))
  1813. openLib = false;
  1814. #endif
  1815. // ---------------------------------------------------------------------------------------------------------------
  1816. // Initialize OS features
  1817. // we want stuff in English so we can parse error messages
  1818. ::setlocale(LC_ALL, "C");
  1819. #ifndef CARLA_OS_WIN
  1820. carla_setenv("LC_ALL", "C");
  1821. #endif
  1822. #ifdef CARLA_OS_WIN
  1823. OleInitialize(nullptr);
  1824. CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
  1825. # ifndef __WINPTHREADS_VERSION
  1826. // (non-portable) initialization of statically linked pthread library
  1827. pthread_win32_process_attach_np();
  1828. pthread_win32_thread_attach_np();
  1829. # endif
  1830. #endif
  1831. // ---------------------------------------------------------------------------------------------------------------
  1832. if (openLib)
  1833. {
  1834. handle = lib_open(filename);
  1835. if (handle == nullptr)
  1836. {
  1837. print_lib_error(filename);
  1838. return 1;
  1839. }
  1840. }
  1841. // never do init for dssi-vst, takes too long and it's crashy
  1842. bool doInit = ! filenameCheck.contains("dssi-vst", true);
  1843. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS") != nullptr)
  1844. doInit = false;
  1845. // ---------------------------------------------------------------------------------------------------------------
  1846. if (doInit && openLib && handle != nullptr)
  1847. {
  1848. // test fast loading & unloading DLL without initializing the plugin(s)
  1849. if (! lib_close(handle))
  1850. {
  1851. print_lib_error(filename);
  1852. return 1;
  1853. }
  1854. handle = lib_open(filename);
  1855. if (handle == nullptr)
  1856. {
  1857. print_lib_error(filename);
  1858. return 1;
  1859. }
  1860. }
  1861. #ifndef BUILD_BRIDGE
  1862. if (std::strcmp(filename, ":all") == 0)
  1863. {
  1864. do_cached_check(type);
  1865. return 0;
  1866. }
  1867. #endif
  1868. #ifdef CARLA_OS_MAC
  1869. // Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
  1870. switch (type)
  1871. {
  1872. case PLUGIN_LADSPA:
  1873. case PLUGIN_DSSI:
  1874. case PLUGIN_VST2:
  1875. case PLUGIN_VST3:
  1876. removeFileFromQuarantine(filename);
  1877. break;
  1878. default:
  1879. break;
  1880. }
  1881. #endif
  1882. #ifdef USING_JUCE
  1883. // some macOS plugins have not been yet ported to arm64, re-run them in x86_64 mode if discovery fails
  1884. bool retryJucePlugin = false;
  1885. #endif
  1886. switch (type)
  1887. {
  1888. case PLUGIN_LADSPA:
  1889. do_ladspa_check(handle, filename, doInit);
  1890. break;
  1891. case PLUGIN_DSSI:
  1892. do_dssi_check(handle, filename, doInit);
  1893. break;
  1894. #ifndef BUILD_BRIDGE
  1895. case PLUGIN_LV2:
  1896. do_lv2_check(filename, doInit);
  1897. break;
  1898. #endif
  1899. case PLUGIN_VST2:
  1900. #if defined(USING_JUCE) && JUCE_PLUGINHOST_VST
  1901. retryJucePlugin = do_juce_check(filename, "VST2", doInit);
  1902. #else
  1903. do_vst2_check(handle, filename, doInit);
  1904. #endif
  1905. break;
  1906. case PLUGIN_VST3:
  1907. #if defined(USING_JUCE) && JUCE_PLUGINHOST_VST3
  1908. retryJucePlugin = do_juce_check(filename, "VST3", doInit);
  1909. #else
  1910. do_vst3_check(handle, filename, doInit);
  1911. #endif
  1912. break;
  1913. case PLUGIN_AU:
  1914. #if defined(USING_JUCE) && JUCE_PLUGINHOST_AU
  1915. do_juce_check(filename, "AU", doInit);
  1916. #else
  1917. DISCOVERY_OUT("error", "AU support not available");
  1918. #endif
  1919. break;
  1920. #ifndef BUILD_BRIDGE
  1921. case PLUGIN_JSFX:
  1922. do_jsfx_check(filename, doInit);
  1923. break;
  1924. #endif
  1925. case PLUGIN_DLS:
  1926. case PLUGIN_GIG:
  1927. case PLUGIN_SF2:
  1928. do_fluidsynth_check(filename, type, doInit);
  1929. break;
  1930. default:
  1931. break;
  1932. }
  1933. #if defined(CARLA_OS_MAC) && defined(USING_JUCE) && defined(__aarch64__)
  1934. if (retryJucePlugin)
  1935. {
  1936. DISCOVERY_OUT("warning", "No plugins found while scanning in arm64 mode, will try x86_64 now");
  1937. cpu_type_t pref = CPU_TYPE_X86_64;
  1938. pid_t pid = -1;
  1939. posix_spawnattr_t attr;
  1940. posix_spawnattr_init(&attr);
  1941. CARLA_SAFE_ASSERT_RETURN(posix_spawnattr_setbinpref_np(&attr, 1, &pref, nullptr) == 0, 1);
  1942. CARLA_SAFE_ASSERT_RETURN(posix_spawn(&pid, argv[0], nullptr, &attr, argv, nullptr) == 0, 1);
  1943. posix_spawnattr_destroy(&attr);
  1944. if (pid > 0)
  1945. {
  1946. int status;
  1947. waitpid(pid, &status, 0);
  1948. }
  1949. }
  1950. #endif
  1951. if (openLib && handle != nullptr)
  1952. lib_close(handle);
  1953. // ---------------------------------------------------------------------------------------------------------------
  1954. #ifdef CARLA_OS_WIN
  1955. #ifndef __WINPTHREADS_VERSION
  1956. pthread_win32_thread_detach_np();
  1957. pthread_win32_process_detach_np();
  1958. #endif
  1959. CoUninitialize();
  1960. OleUninitialize();
  1961. #endif
  1962. return 0;
  1963. #ifdef USING_JUCE
  1964. // might be unused
  1965. (void)retryJucePlugin;
  1966. #endif
  1967. }
  1968. // -------------------------------------------------------------------------------------------------------------------