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 85KB

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