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

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