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