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

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