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

11 years ago
11 years ago
11 years ago
11 years ago
12 years ago
12 years ago
10 years ago
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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
10 years ago
10 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
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
11 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
12 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
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
12 years ago
10 years ago
11 years ago
12 years ago
11 years ago
12 years ago
10 years ago
12 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 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
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814
  1. /*
  2. * Carla Plugin discovery
  3. * Copyright (C) 2011-2017 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 "CarlaMIDI.h"
  21. #include "LinkedList.hpp"
  22. #include "AppConfig.h"
  23. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  24. # define USE_JUCE_PROCESSORS
  25. # include "juce_audio_processors/juce_audio_processors.h"
  26. #endif
  27. #ifdef BUILD_BRIDGE
  28. # undef HAVE_FLUIDSYNTH
  29. # undef HAVE_LINUXSAMPLER
  30. #endif
  31. #include "CarlaLadspaUtils.hpp"
  32. #include "CarlaDssiUtils.cpp"
  33. #include "CarlaLv2Utils.hpp"
  34. #include "CarlaVstUtils.hpp"
  35. // need to include this before linuxsampler
  36. #define CARLA_UTILS_CACHED_PLUGINS_ONLY
  37. #include "CarlaUtils.cpp"
  38. #ifdef HAVE_FLUIDSYNTH
  39. # include <fluidsynth.h>
  40. #endif
  41. #ifdef HAVE_LINUXSAMPLER
  42. # include "linuxsampler/EngineFactory.h"
  43. #endif
  44. #include <iostream>
  45. #include "juce_core/juce_core.h"
  46. #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;
  47. using juce::CharPointer_UTF8;
  48. using juce::File;
  49. using juce::StringArray;
  50. CARLA_BACKEND_USE_NAMESPACE
  51. // --------------------------------------------------------------------------
  52. // Dummy values to test plugins with
  53. static const uint32_t kBufferSize = 512;
  54. static const double kSampleRate = 44100.0;
  55. static const int32_t kSampleRatei = 44100;
  56. static const float kSampleRatef = 44100.0f;
  57. // --------------------------------------------------------------------------
  58. // Don't print ELF/EXE related errors since discovery can find multi-architecture binaries
  59. static void print_lib_error(const char* const filename)
  60. {
  61. const char* const error(lib_error(filename));
  62. if (error != nullptr && std::strstr(error, "wrong ELF class") == nullptr && std::strstr(error, "Bad EXE format") == nullptr)
  63. DISCOVERY_OUT("error", error);
  64. }
  65. #ifndef CARLA_OS_MAC
  66. // --------------------------------------------------------------------------
  67. // VST stuff
  68. // Check if plugin is currently processing
  69. static bool gVstIsProcessing = false;
  70. // Check if plugin needs idle
  71. static bool gVstNeedsIdle = false;
  72. // Check if plugin wants midi
  73. static bool gVstWantsMidi = false;
  74. // Check if plugin wants time
  75. static bool gVstWantsTime = false;
  76. // Current uniqueId for VST shell plugins
  77. static intptr_t gVstCurrentUniqueId = 0;
  78. // Supported Carla features
  79. static intptr_t vstHostCanDo(const char* const feature)
  80. {
  81. carla_debug("vstHostCanDo(\"%s\")", feature);
  82. if (std::strcmp(feature, "supplyIdle") == 0)
  83. return 1;
  84. if (std::strcmp(feature, "sendVstEvents") == 0)
  85. return 1;
  86. if (std::strcmp(feature, "sendVstMidiEvent") == 0)
  87. return 1;
  88. if (std::strcmp(feature, "sendVstMidiEventFlagIsRealtime") == 0)
  89. return 1;
  90. if (std::strcmp(feature, "sendVstTimeInfo") == 0)
  91. {
  92. gVstWantsTime = true;
  93. return 1;
  94. }
  95. if (std::strcmp(feature, "receiveVstEvents") == 0)
  96. return 1;
  97. if (std::strcmp(feature, "receiveVstMidiEvent") == 0)
  98. return 1;
  99. if (std::strcmp(feature, "receiveVstTimeInfo") == 0)
  100. return -1;
  101. if (std::strcmp(feature, "reportConnectionChanges") == 0)
  102. return -1;
  103. if (std::strcmp(feature, "acceptIOChanges") == 0)
  104. return 1;
  105. if (std::strcmp(feature, "sizeWindow") == 0)
  106. return 1;
  107. if (std::strcmp(feature, "offline") == 0)
  108. return -1;
  109. if (std::strcmp(feature, "openFileSelector") == 0)
  110. return -1;
  111. if (std::strcmp(feature, "closeFileSelector") == 0)
  112. return -1;
  113. if (std::strcmp(feature, "startStopProcess") == 0)
  114. return 1;
  115. if (std::strcmp(feature, "supportShell") == 0)
  116. return 1;
  117. if (std::strcmp(feature, "shellCategory") == 0)
  118. return 1;
  119. // non-official features found in some plugins:
  120. // "asyncProcessing"
  121. // "editFile"
  122. // unimplemented
  123. carla_stderr("vstHostCanDo(\"%s\") - unknown feature", feature);
  124. return 0;
  125. }
  126. // Host-side callback
  127. 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)
  128. {
  129. carla_debug("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  130. static VstTimeInfo timeInfo;
  131. intptr_t ret = 0;
  132. switch (opcode)
  133. {
  134. case audioMasterAutomate:
  135. ret = 1;
  136. break;
  137. case audioMasterVersion:
  138. ret = kVstVersion;
  139. break;
  140. case audioMasterCurrentId:
  141. ret = gVstCurrentUniqueId;
  142. break;
  143. case DECLARE_VST_DEPRECATED(audioMasterWantMidi):
  144. if (gVstWantsMidi) { DISCOVERY_OUT("warning", "Plugin requested MIDI more than once"); }
  145. gVstWantsMidi = true;
  146. ret = 1;
  147. break;
  148. case audioMasterGetTime:
  149. if (! gVstIsProcessing) { DISCOVERY_OUT("warning", "Plugin requested timeInfo out of process"); }
  150. if (! gVstWantsTime) { DISCOVERY_OUT("warning", "Plugin requested timeInfo but didn't ask if host could do \"sendVstTimeInfo\""); }
  151. carla_zeroStruct(timeInfo);
  152. timeInfo.sampleRate = kSampleRate;
  153. // Tempo
  154. timeInfo.tempo = 120.0;
  155. timeInfo.flags |= kVstTempoValid;
  156. // Time Signature
  157. timeInfo.timeSigNumerator = 4;
  158. timeInfo.timeSigDenominator = 4;
  159. timeInfo.flags |= kVstTimeSigValid;
  160. ret = (intptr_t)&timeInfo;
  161. break;
  162. case DECLARE_VST_DEPRECATED(audioMasterTempoAt):
  163. ret = 120 * 10000;
  164. break;
  165. case DECLARE_VST_DEPRECATED(audioMasterGetNumAutomatableParameters):
  166. ret = carla_minPositive(effect->numParams, static_cast<int>(MAX_DEFAULT_PARAMETERS));
  167. break;
  168. case DECLARE_VST_DEPRECATED(audioMasterGetParameterQuantization):
  169. ret = 1; // full single float precision
  170. break;
  171. case DECLARE_VST_DEPRECATED(audioMasterNeedIdle):
  172. if (gVstNeedsIdle) { DISCOVERY_OUT("warning", "Plugin requested idle more than once"); }
  173. gVstNeedsIdle = true;
  174. ret = 1;
  175. break;
  176. case audioMasterGetSampleRate:
  177. ret = kSampleRatei;
  178. break;
  179. case audioMasterGetBlockSize:
  180. ret = kBufferSize;
  181. break;
  182. case DECLARE_VST_DEPRECATED(audioMasterWillReplaceOrAccumulate):
  183. ret = 1; // replace
  184. break;
  185. case audioMasterGetCurrentProcessLevel:
  186. ret = gVstIsProcessing ? kVstProcessLevelRealtime : kVstProcessLevelUser;
  187. break;
  188. case audioMasterGetAutomationState:
  189. ret = kVstAutomationOff;
  190. break;
  191. case audioMasterGetVendorString:
  192. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  193. std::strcpy((char*)ptr, "falkTX");
  194. ret = 1;
  195. break;
  196. case audioMasterGetProductString:
  197. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  198. std::strcpy((char*)ptr, "Carla-Discovery");
  199. ret = 1;
  200. break;
  201. case audioMasterGetVendorVersion:
  202. ret = CARLA_VERSION_HEX;
  203. break;
  204. case audioMasterCanDo:
  205. CARLA_SAFE_ASSERT_BREAK(ptr != nullptr);
  206. ret = vstHostCanDo((const char*)ptr);
  207. break;
  208. case audioMasterGetLanguage:
  209. ret = kVstLangEnglish;
  210. break;
  211. default:
  212. carla_stdout("vstHostCallback(%p, %i:%s, %i, " P_INTPTR ", %p, %f)", effect, opcode, vstMasterOpcode2str(opcode), index, value, ptr, opt);
  213. break;
  214. }
  215. return ret;
  216. }
  217. #endif // ! CARLA_OS_MAC
  218. #ifdef HAVE_LINUXSAMPLER
  219. // --------------------------------------------------------------------------
  220. // LinuxSampler stuff
  221. class LinuxSamplerScopedEngine
  222. {
  223. public:
  224. LinuxSamplerScopedEngine(const char* const filename, const char* const stype)
  225. : fEngine(nullptr)
  226. {
  227. using namespace LinuxSampler;
  228. try {
  229. fEngine = EngineFactory::Create(stype);
  230. }
  231. catch (const Exception& e)
  232. {
  233. DISCOVERY_OUT("error", e.what());
  234. return;
  235. }
  236. if (fEngine == nullptr)
  237. return;
  238. InstrumentManager* const insMan(fEngine->GetInstrumentManager());
  239. if (insMan == nullptr)
  240. {
  241. DISCOVERY_OUT("error", "Failed to get LinuxSampler instrument manager");
  242. return;
  243. }
  244. std::vector<InstrumentManager::instrument_id_t> ids;
  245. try {
  246. ids = insMan->GetInstrumentFileContent(filename);
  247. }
  248. catch (const InstrumentManagerException& e)
  249. {
  250. DISCOVERY_OUT("error", e.what());
  251. return;
  252. }
  253. if (ids.size() == 0)
  254. {
  255. DISCOVERY_OUT("error", "Failed to find any instruments");
  256. return;
  257. }
  258. InstrumentManager::instrument_info_t info;
  259. try {
  260. info = insMan->GetInstrumentInfo(ids[0]);
  261. }
  262. catch (const InstrumentManagerException& e)
  263. {
  264. DISCOVERY_OUT("error", e.what());
  265. return;
  266. }
  267. outputInfo(&info, nullptr, ids.size() > 1);
  268. }
  269. ~LinuxSamplerScopedEngine()
  270. {
  271. if (fEngine != nullptr)
  272. {
  273. LinuxSampler::EngineFactory::Destroy(fEngine);
  274. fEngine = nullptr;
  275. }
  276. }
  277. static void outputInfo(const LinuxSampler::InstrumentManager::instrument_info_t* const info, const char* const basename, const bool has16Outs)
  278. {
  279. CarlaString name;
  280. const char* label;
  281. if (info != nullptr)
  282. {
  283. name = info->InstrumentName.c_str();
  284. label = info->Product.c_str();
  285. }
  286. else
  287. {
  288. name = basename;
  289. label = basename;
  290. }
  291. // 2 channels
  292. DISCOVERY_OUT("init", "-----------");
  293. DISCOVERY_OUT("build", BINARY_NATIVE);
  294. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  295. DISCOVERY_OUT("name", name.buffer());
  296. DISCOVERY_OUT("label", label);
  297. if (info != nullptr)
  298. DISCOVERY_OUT("maker", info->Artists);
  299. DISCOVERY_OUT("audio.outs", 2);
  300. DISCOVERY_OUT("midi.ins", 1);
  301. DISCOVERY_OUT("end", "------------");
  302. // 16 channels
  303. if (name.isEmpty() || ! has16Outs)
  304. return;
  305. name += " (16 outputs)";
  306. DISCOVERY_OUT("init", "-----------");
  307. DISCOVERY_OUT("build", BINARY_NATIVE);
  308. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  309. DISCOVERY_OUT("name", name.buffer());
  310. DISCOVERY_OUT("label", label);
  311. if (info != nullptr)
  312. DISCOVERY_OUT("maker", info->Artists);
  313. DISCOVERY_OUT("audio.outs", 32);
  314. DISCOVERY_OUT("midi.ins", 1);
  315. DISCOVERY_OUT("end", "------------");
  316. }
  317. private:
  318. LinuxSampler::Engine* fEngine;
  319. CARLA_PREVENT_HEAP_ALLOCATION
  320. CARLA_DECLARE_NON_COPY_CLASS(LinuxSamplerScopedEngine)
  321. };
  322. #endif // HAVE_LINUXSAMPLER
  323. // ------------------------------ Plugin Checks -----------------------------
  324. static void do_cached_check(const PluginType type)
  325. {
  326. const char* const plugPath = (type == PLUGIN_LV2) ? std::getenv("LV2_PATH") : nullptr;
  327. const uint count = carla_get_cached_plugin_count(type, plugPath);
  328. for (uint i=0; i<count; ++i)
  329. {
  330. const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i));
  331. CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);
  332. DISCOVERY_OUT("init", "-----------");
  333. DISCOVERY_OUT("build", BINARY_NATIVE);
  334. DISCOVERY_OUT("hints", pinfo->hints);
  335. DISCOVERY_OUT("name", pinfo->name);
  336. DISCOVERY_OUT("maker", pinfo->maker);
  337. DISCOVERY_OUT("label", pinfo->label);
  338. DISCOVERY_OUT("audio.ins", pinfo->audioIns);
  339. DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
  340. DISCOVERY_OUT("midi.ins", pinfo->midiIns);
  341. DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
  342. DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
  343. DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
  344. DISCOVERY_OUT("end", "------------");
  345. }
  346. }
  347. static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit)
  348. {
  349. LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  350. if (descFn == nullptr)
  351. {
  352. DISCOVERY_OUT("error", "Not a LADSPA plugin");
  353. return;
  354. }
  355. const LADSPA_Descriptor* descriptor;
  356. {
  357. descriptor = descFn(0);
  358. if (descriptor == nullptr)
  359. {
  360. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  361. return;
  362. }
  363. if (doInit && descriptor->instantiate != nullptr && descriptor->cleanup != nullptr)
  364. {
  365. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  366. if (handle == nullptr)
  367. {
  368. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  369. return;
  370. }
  371. descriptor->cleanup(handle);
  372. lib_close(libHandle);
  373. libHandle = lib_open(filename);
  374. if (libHandle == nullptr)
  375. {
  376. print_lib_error(filename);
  377. return;
  378. }
  379. descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor");
  380. if (descFn == nullptr)
  381. {
  382. DISCOVERY_OUT("error", "Not a LADSPA plugin (#2)");
  383. return;
  384. }
  385. }
  386. }
  387. unsigned long i = 0;
  388. while ((descriptor = descFn(i++)) != nullptr)
  389. {
  390. if (descriptor->instantiate == nullptr)
  391. {
  392. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no instantiate()");
  393. continue;
  394. }
  395. if (descriptor->cleanup == nullptr)
  396. {
  397. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no cleanup()");
  398. continue;
  399. }
  400. if (descriptor->run == nullptr)
  401. {
  402. DISCOVERY_OUT("error", "Plugin '" << descriptor->Name << "' has no run()");
  403. continue;
  404. }
  405. if (! LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  406. {
  407. DISCOVERY_OUT("warning", "Plugin '" << descriptor->Name << "' is not hard real-time capable");
  408. }
  409. uint hints = 0x0;
  410. int audioIns = 0;
  411. int audioOuts = 0;
  412. int audioTotal = 0;
  413. int parametersIns = 0;
  414. int parametersOuts = 0;
  415. int parametersTotal = 0;
  416. if (LADSPA_IS_HARD_RT_CAPABLE(descriptor->Properties))
  417. hints |= PLUGIN_IS_RTSAFE;
  418. for (unsigned long j=0; j < descriptor->PortCount; ++j)
  419. {
  420. CARLA_ASSERT(descriptor->PortNames[j] != nullptr);
  421. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  422. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  423. {
  424. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  425. audioIns += 1;
  426. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  427. audioOuts += 1;
  428. audioTotal += 1;
  429. }
  430. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  431. {
  432. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  433. parametersIns += 1;
  434. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(descriptor->PortNames[j], "latency") != 0 && std::strcmp(descriptor->PortNames[j], "_latency") != 0)
  435. parametersOuts += 1;
  436. parametersTotal += 1;
  437. }
  438. }
  439. if (doInit)
  440. {
  441. // -----------------------------------------------------------------------
  442. // start crash-free plugin test
  443. LADSPA_Handle handle = descriptor->instantiate(descriptor, kSampleRatei);
  444. if (handle == nullptr)
  445. {
  446. DISCOVERY_OUT("error", "Failed to init LADSPA plugin");
  447. continue;
  448. }
  449. // Test quick init and cleanup
  450. descriptor->cleanup(handle);
  451. handle = descriptor->instantiate(descriptor, kSampleRatei);
  452. if (handle == nullptr)
  453. {
  454. DISCOVERY_OUT("error", "Failed to init LADSPA plugin (#2)");
  455. continue;
  456. }
  457. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  458. LADSPA_Data bufferParams[parametersTotal];
  459. LADSPA_Data min, max, def;
  460. for (unsigned long j=0, iA=0, iC=0; j < descriptor->PortCount; ++j)
  461. {
  462. const LADSPA_PortDescriptor portDescriptor = descriptor->PortDescriptors[j];
  463. const LADSPA_PortRangeHint portRangeHints = descriptor->PortRangeHints[j];
  464. const char* const portName = descriptor->PortNames[j];
  465. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  466. {
  467. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  468. descriptor->connect_port(handle, j, bufferAudio[iA++]);
  469. }
  470. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  471. {
  472. // min value
  473. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  474. min = portRangeHints.LowerBound;
  475. else
  476. min = 0.0f;
  477. // max value
  478. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  479. max = portRangeHints.UpperBound;
  480. else
  481. max = 1.0f;
  482. if (min > max)
  483. {
  484. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  485. max = min + 0.1f;
  486. }
  487. else if (carla_isEqual(min, max))
  488. {
  489. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  490. max = min + 0.1f;
  491. }
  492. // default value
  493. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  494. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  495. {
  496. min *= kSampleRatef;
  497. max *= kSampleRatef;
  498. def *= kSampleRatef;
  499. }
  500. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  501. {
  502. // latency parameter
  503. def = 0.0f;
  504. }
  505. else
  506. {
  507. if (def < min)
  508. def = min;
  509. else if (def > max)
  510. def = max;
  511. }
  512. bufferParams[iC] = def;
  513. descriptor->connect_port(handle, j, &bufferParams[iC++]);
  514. }
  515. }
  516. if (descriptor->activate != nullptr)
  517. descriptor->activate(handle);
  518. descriptor->run(handle, kBufferSize);
  519. if (descriptor->deactivate != nullptr)
  520. descriptor->deactivate(handle);
  521. descriptor->cleanup(handle);
  522. // end crash-free plugin test
  523. // -----------------------------------------------------------------------
  524. }
  525. DISCOVERY_OUT("init", "-----------");
  526. DISCOVERY_OUT("build", BINARY_NATIVE);
  527. DISCOVERY_OUT("hints", hints);
  528. DISCOVERY_OUT("name", descriptor->Name);
  529. DISCOVERY_OUT("label", descriptor->Label);
  530. DISCOVERY_OUT("maker", descriptor->Maker);
  531. DISCOVERY_OUT("uniqueId", descriptor->UniqueID);
  532. DISCOVERY_OUT("audio.ins", audioIns);
  533. DISCOVERY_OUT("audio.outs", audioOuts);
  534. DISCOVERY_OUT("parameters.ins", parametersIns);
  535. DISCOVERY_OUT("parameters.outs", parametersOuts);
  536. DISCOVERY_OUT("end", "------------");
  537. }
  538. }
  539. static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit)
  540. {
  541. DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  542. if (descFn == nullptr)
  543. {
  544. DISCOVERY_OUT("error", "Not a DSSI plugin");
  545. return;
  546. }
  547. const DSSI_Descriptor* descriptor;
  548. {
  549. descriptor = descFn(0);
  550. if (descriptor == nullptr)
  551. {
  552. DISCOVERY_OUT("error", "Binary doesn't contain any plugins");
  553. return;
  554. }
  555. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  556. if (ldescriptor == nullptr)
  557. {
  558. DISCOVERY_OUT("error", "DSSI plugin doesn't provide the LADSPA interface");
  559. return;
  560. }
  561. if (doInit && ldescriptor->instantiate != nullptr && ldescriptor->cleanup != nullptr)
  562. {
  563. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  564. if (handle == nullptr)
  565. {
  566. DISCOVERY_OUT("error", "Failed to init first LADSPA plugin");
  567. return;
  568. }
  569. ldescriptor->cleanup(handle);
  570. lib_close(libHandle);
  571. libHandle = lib_open(filename);
  572. if (libHandle == nullptr)
  573. {
  574. print_lib_error(filename);
  575. return;
  576. }
  577. descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor");
  578. if (descFn == nullptr)
  579. {
  580. DISCOVERY_OUT("error", "Not a DSSI plugin (#2)");
  581. return;
  582. }
  583. }
  584. }
  585. unsigned long i = 0;
  586. while ((descriptor = descFn(i++)) != nullptr)
  587. {
  588. const LADSPA_Descriptor* const ldescriptor(descriptor->LADSPA_Plugin);
  589. if (ldescriptor == nullptr)
  590. {
  591. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no LADSPA interface");
  592. continue;
  593. }
  594. if (descriptor->DSSI_API_Version != DSSI_VERSION_MAJOR)
  595. {
  596. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' uses an unsupported DSSI spec version " << descriptor->DSSI_API_Version);
  597. continue;
  598. }
  599. if (ldescriptor->instantiate == nullptr)
  600. {
  601. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no instantiate()");
  602. continue;
  603. }
  604. if (ldescriptor->cleanup == nullptr)
  605. {
  606. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no cleanup()");
  607. continue;
  608. }
  609. if (ldescriptor->run == nullptr && descriptor->run_synth == nullptr)
  610. {
  611. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' has no run() or run_synth()");
  612. continue;
  613. }
  614. if (descriptor->run_synth == nullptr && descriptor->run_multiple_synths != nullptr)
  615. {
  616. DISCOVERY_OUT("error", "Plugin '" << ldescriptor->Name << "' requires run_multiple_synths which is not supported");
  617. continue;
  618. }
  619. if (! LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  620. {
  621. DISCOVERY_OUT("warning", "Plugin '" << ldescriptor->Name << "' is not hard real-time capable");
  622. }
  623. uint hints = 0x0;
  624. int audioIns = 0;
  625. int audioOuts = 0;
  626. int audioTotal = 0;
  627. int midiIns = 0;
  628. int parametersIns = 0;
  629. int parametersOuts = 0;
  630. int parametersTotal = 0;
  631. if (LADSPA_IS_HARD_RT_CAPABLE(ldescriptor->Properties))
  632. hints |= PLUGIN_IS_RTSAFE;
  633. for (unsigned long j=0; j < ldescriptor->PortCount; ++j)
  634. {
  635. CARLA_ASSERT(ldescriptor->PortNames[j] != nullptr);
  636. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  637. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  638. {
  639. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  640. audioIns += 1;
  641. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor))
  642. audioOuts += 1;
  643. audioTotal += 1;
  644. }
  645. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  646. {
  647. if (LADSPA_IS_PORT_INPUT(portDescriptor))
  648. parametersIns += 1;
  649. else if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && std::strcmp(ldescriptor->PortNames[j], "latency") != 0 && std::strcmp(ldescriptor->PortNames[j], "_latency") != 0)
  650. parametersOuts += 1;
  651. parametersTotal += 1;
  652. }
  653. }
  654. if (descriptor->run_synth != nullptr)
  655. midiIns = 1;
  656. if (midiIns > 0 && audioIns == 0 && audioOuts > 0)
  657. hints |= PLUGIN_IS_SYNTH;
  658. if (const char* const ui = find_dssi_ui(filename, ldescriptor->Label))
  659. {
  660. hints |= PLUGIN_HAS_CUSTOM_UI;
  661. delete[] ui;
  662. }
  663. if (doInit)
  664. {
  665. // -----------------------------------------------------------------------
  666. // start crash-free plugin test
  667. LADSPA_Handle handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  668. if (handle == nullptr)
  669. {
  670. DISCOVERY_OUT("error", "Failed to init DSSI plugin");
  671. continue;
  672. }
  673. // Test quick init and cleanup
  674. ldescriptor->cleanup(handle);
  675. handle = ldescriptor->instantiate(ldescriptor, kSampleRatei);
  676. if (handle == nullptr)
  677. {
  678. DISCOVERY_OUT("error", "Failed to init DSSI plugin (#2)");
  679. continue;
  680. }
  681. LADSPA_Data bufferAudio[kBufferSize][audioTotal];
  682. LADSPA_Data bufferParams[parametersTotal];
  683. LADSPA_Data min, max, def;
  684. for (unsigned long j=0, iA=0, iC=0; j < ldescriptor->PortCount; ++j)
  685. {
  686. const LADSPA_PortDescriptor portDescriptor = ldescriptor->PortDescriptors[j];
  687. const LADSPA_PortRangeHint portRangeHints = ldescriptor->PortRangeHints[j];
  688. const char* const portName = ldescriptor->PortNames[j];
  689. if (LADSPA_IS_PORT_AUDIO(portDescriptor))
  690. {
  691. carla_zeroFloats(bufferAudio[iA], kBufferSize);
  692. ldescriptor->connect_port(handle, j, bufferAudio[iA++]);
  693. }
  694. else if (LADSPA_IS_PORT_CONTROL(portDescriptor))
  695. {
  696. // min value
  697. if (LADSPA_IS_HINT_BOUNDED_BELOW(portRangeHints.HintDescriptor))
  698. min = portRangeHints.LowerBound;
  699. else
  700. min = 0.0f;
  701. // max value
  702. if (LADSPA_IS_HINT_BOUNDED_ABOVE(portRangeHints.HintDescriptor))
  703. max = portRangeHints.UpperBound;
  704. else
  705. max = 1.0f;
  706. if (min > max)
  707. {
  708. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: min > max");
  709. max = min + 0.1f;
  710. }
  711. else if (carla_isEqual(min, max))
  712. {
  713. DISCOVERY_OUT("warning", "Parameter '" << portName << "' is broken: max == min");
  714. max = min + 0.1f;
  715. }
  716. // default value
  717. def = get_default_ladspa_port_value(portRangeHints.HintDescriptor, min, max);
  718. if (LADSPA_IS_HINT_SAMPLE_RATE(portRangeHints.HintDescriptor))
  719. {
  720. min *= kSampleRatef;
  721. max *= kSampleRatef;
  722. def *= kSampleRatef;
  723. }
  724. if (LADSPA_IS_PORT_OUTPUT(portDescriptor) && (std::strcmp(portName, "latency") == 0 || std::strcmp(portName, "_latency") == 0))
  725. {
  726. // latency parameter
  727. def = 0.0f;
  728. }
  729. else
  730. {
  731. if (def < min)
  732. def = min;
  733. else if (def > max)
  734. def = max;
  735. }
  736. bufferParams[iC] = def;
  737. ldescriptor->connect_port(handle, j, &bufferParams[iC++]);
  738. }
  739. }
  740. // select first midi-program if available
  741. if (descriptor->get_program != nullptr && descriptor->select_program != nullptr)
  742. {
  743. if (const DSSI_Program_Descriptor* const pDesc = descriptor->get_program(handle, 0))
  744. descriptor->select_program(handle, pDesc->Bank, pDesc->Program);
  745. }
  746. if (ldescriptor->activate != nullptr)
  747. ldescriptor->activate(handle);
  748. if (descriptor->run_synth != nullptr)
  749. {
  750. snd_seq_event_t midiEvents[2];
  751. carla_zeroStructs(midiEvents, 2);
  752. const unsigned long midiEventCount = 2;
  753. midiEvents[0].type = SND_SEQ_EVENT_NOTEON;
  754. midiEvents[0].data.note.note = 64;
  755. midiEvents[0].data.note.velocity = 100;
  756. midiEvents[1].type = SND_SEQ_EVENT_NOTEOFF;
  757. midiEvents[1].data.note.note = 64;
  758. midiEvents[1].data.note.velocity = 0;
  759. midiEvents[1].time.tick = kBufferSize/2;
  760. descriptor->run_synth(handle, kBufferSize, midiEvents, midiEventCount);
  761. }
  762. else
  763. ldescriptor->run(handle, kBufferSize);
  764. if (ldescriptor->deactivate != nullptr)
  765. ldescriptor->deactivate(handle);
  766. ldescriptor->cleanup(handle);
  767. // end crash-free plugin test
  768. // -----------------------------------------------------------------------
  769. }
  770. DISCOVERY_OUT("init", "-----------");
  771. DISCOVERY_OUT("build", BINARY_NATIVE);
  772. DISCOVERY_OUT("hints", hints);
  773. DISCOVERY_OUT("name", ldescriptor->Name);
  774. DISCOVERY_OUT("label", ldescriptor->Label);
  775. DISCOVERY_OUT("maker", ldescriptor->Maker);
  776. DISCOVERY_OUT("uniqueId", ldescriptor->UniqueID);
  777. DISCOVERY_OUT("audio.ins", audioIns);
  778. DISCOVERY_OUT("audio.outs", audioOuts);
  779. DISCOVERY_OUT("midi.ins", midiIns);
  780. DISCOVERY_OUT("parameters.ins", parametersIns);
  781. DISCOVERY_OUT("parameters.outs", parametersOuts);
  782. DISCOVERY_OUT("end", "------------");
  783. }
  784. }
  785. static void do_lv2_check(const char* const bundle, const bool doInit)
  786. {
  787. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  788. Lilv::Node bundleNode(lv2World.new_file_uri(nullptr, bundle));
  789. CARLA_SAFE_ASSERT_RETURN(bundleNode.is_uri(),);
  790. CarlaString sBundle(bundleNode.as_uri());
  791. if (! sBundle.endsWith("/"))
  792. sBundle += "/";
  793. // Load bundle
  794. lv2World.load_bundle(sBundle);
  795. // Load plugins in this bundle
  796. const Lilv::Plugins lilvPlugins(lv2World.get_all_plugins());
  797. // Get all plugin URIs in this bundle
  798. StringArray URIs;
  799. LILV_FOREACH(plugins, it, lilvPlugins)
  800. {
  801. Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it));
  802. if (const char* const uri = lilvPlugin.get_uri().as_string())
  803. URIs.addIfNotAlreadyThere(juce::String(uri));
  804. }
  805. if (URIs.size() == 0)
  806. {
  807. DISCOVERY_OUT("warning", "LV2 Bundle doesn't provide any plugins");
  808. return;
  809. }
  810. // Get & check every plugin-instance
  811. for (int i=0, count=URIs.size(); i < count; ++i)
  812. {
  813. const LV2_RDF_Descriptor* const rdfDescriptor(lv2_rdf_new(URIs[i].toRawUTF8(), false));
  814. if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
  815. {
  816. DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URIs[i].toRawUTF8() << "'");
  817. continue;
  818. }
  819. if (doInit)
  820. {
  821. // test if DLL is loadable, twice
  822. const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);
  823. if (libHandle1 == nullptr)
  824. {
  825. print_lib_error(rdfDescriptor->Binary);
  826. delete rdfDescriptor;
  827. continue;
  828. }
  829. lib_close(libHandle1);
  830. const lib_t libHandle2 = lib_open(rdfDescriptor->Binary);
  831. if (libHandle2 == nullptr)
  832. {
  833. print_lib_error(rdfDescriptor->Binary);
  834. delete rdfDescriptor;
  835. continue;
  836. }
  837. lib_close(libHandle2);
  838. }
  839. // test if we support all required ports and features
  840. {
  841. bool supported = true;
  842. for (uint32_t j=0; j < rdfDescriptor->PortCount && supported; ++j)
  843. {
  844. const LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[j]);
  845. if (is_lv2_port_supported(rdfPort->Types))
  846. {
  847. pass();
  848. }
  849. else if (! LV2_IS_PORT_OPTIONAL(rdfPort->Properties))
  850. {
  851. DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported port type (portName: '" << rdfPort->Name << "')");
  852. supported = false;
  853. break;
  854. }
  855. }
  856. for (uint32_t j=0; j < rdfDescriptor->FeatureCount && supported; ++j)
  857. {
  858. const LV2_RDF_Feature& feature(rdfDescriptor->Features[j]);
  859. if (std::strcmp(feature.URI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(feature.URI, LV2_INSTANCE_ACCESS_URI) == 0)
  860. {
  861. DISCOVERY_OUT("warning", "Plugin '" << rdfDescriptor->URI << "' DSP wants UI feature '" << feature.URI << "', ignoring this");
  862. }
  863. else if (feature.Required && ! is_lv2_feature_supported(feature.URI))
  864. {
  865. DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported feature '" << feature.URI << "'");
  866. supported = false;
  867. break;
  868. }
  869. }
  870. if (! supported)
  871. {
  872. delete rdfDescriptor;
  873. continue;
  874. }
  875. }
  876. uint hints = 0x0;
  877. int audioIns = 0;
  878. int audioOuts = 0;
  879. int midiIns = 0;
  880. int midiOuts = 0;
  881. int parametersIns = 0;
  882. int parametersOuts = 0;
  883. for (uint32_t j=0; j < rdfDescriptor->FeatureCount; ++j)
  884. {
  885. const LV2_RDF_Feature* const rdfFeature(&rdfDescriptor->Features[j]);
  886. if (std::strcmp(rdfFeature->URI, LV2_CORE__hardRTCapable) == 0)
  887. hints |= PLUGIN_IS_RTSAFE;
  888. }
  889. for (uint32_t j=0; j < rdfDescriptor->PortCount; ++j)
  890. {
  891. const LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[j]);
  892. if (LV2_IS_PORT_AUDIO(rdfPort->Types))
  893. {
  894. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  895. audioIns += 1;
  896. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  897. audioOuts += 1;
  898. }
  899. else if (LV2_IS_PORT_CONTROL(rdfPort->Types))
  900. {
  901. if (LV2_IS_PORT_DESIGNATION_LATENCY(rdfPort->Designation))
  902. {
  903. pass();
  904. }
  905. else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(rdfPort->Designation))
  906. {
  907. pass();
  908. }
  909. else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(rdfPort->Designation))
  910. {
  911. pass();
  912. }
  913. else if (LV2_IS_PORT_DESIGNATION_TIME(rdfPort->Designation))
  914. {
  915. pass();
  916. }
  917. else
  918. {
  919. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  920. parametersIns += 1;
  921. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  922. parametersOuts += 1;
  923. }
  924. }
  925. else if (LV2_PORT_SUPPORTS_MIDI_EVENT(rdfPort->Types))
  926. {
  927. if (LV2_IS_PORT_INPUT(rdfPort->Types))
  928. midiIns += 1;
  929. else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
  930. midiOuts += 1;
  931. }
  932. }
  933. if (LV2_IS_INSTRUMENT(rdfDescriptor->Type[0], rdfDescriptor->Type[1]))
  934. hints |= PLUGIN_IS_SYNTH;
  935. if (rdfDescriptor->UICount > 0)
  936. hints |= PLUGIN_HAS_CUSTOM_UI;
  937. DISCOVERY_OUT("init", "-----------");
  938. DISCOVERY_OUT("build", BINARY_NATIVE);
  939. DISCOVERY_OUT("hints", hints);
  940. if (rdfDescriptor->Name != nullptr)
  941. DISCOVERY_OUT("name", rdfDescriptor->Name);
  942. if (rdfDescriptor->Author != nullptr)
  943. DISCOVERY_OUT("maker", rdfDescriptor->Author);
  944. DISCOVERY_OUT("uri", rdfDescriptor->URI);
  945. DISCOVERY_OUT("uniqueId", rdfDescriptor->UniqueID);
  946. DISCOVERY_OUT("audio.ins", audioIns);
  947. DISCOVERY_OUT("audio.outs", audioOuts);
  948. DISCOVERY_OUT("midi.ins", midiIns);
  949. DISCOVERY_OUT("midi.outs", midiOuts);
  950. DISCOVERY_OUT("parameters.ins", parametersIns);
  951. DISCOVERY_OUT("parameters.outs", parametersOuts);
  952. DISCOVERY_OUT("end", "------------");
  953. delete rdfDescriptor;
  954. }
  955. }
  956. #ifndef CARLA_OS_MAC
  957. static void do_vst_check(lib_t& libHandle, const bool doInit)
  958. {
  959. VST_Function vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain");
  960. if (vstFn == nullptr)
  961. {
  962. vstFn = lib_symbol<VST_Function>(libHandle, "main");
  963. if (vstFn == nullptr)
  964. {
  965. DISCOVERY_OUT("error", "Not a VST plugin");
  966. return;
  967. }
  968. }
  969. AEffect* effect = vstFn(vstHostCallback);
  970. if (effect == nullptr || effect->magic != kEffectMagic)
  971. {
  972. DISCOVERY_OUT("error", "Failed to init VST plugin, or VST magic failed");
  973. return;
  974. }
  975. if (effect->uniqueID == 0)
  976. {
  977. DISCOVERY_OUT("error", "Plugin doesn't have an Unique ID");
  978. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  979. return;
  980. }
  981. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  982. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  983. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  984. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  985. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  986. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  987. if (effect->numPrograms > 0)
  988. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  989. const bool isShell = (effect->dispatcher(effect, effGetPlugCategory, 0, 0, nullptr, 0.0f) == kPlugCategShell);
  990. gVstCurrentUniqueId = effect->uniqueID;
  991. char strBuf[STR_MAX+1];
  992. CarlaString cName;
  993. CarlaString cProduct;
  994. CarlaString cVendor;
  995. LinkedList<intptr_t> uniqueIds;
  996. if (isShell)
  997. {
  998. for (;;)
  999. {
  1000. carla_zeroChars(strBuf, STR_MAX+1);
  1001. gVstCurrentUniqueId = effect->dispatcher(effect, effShellGetNextPlugin, 0, 0, strBuf, 0.0f);
  1002. if (gVstCurrentUniqueId == 0)
  1003. break;
  1004. uniqueIds.append(gVstCurrentUniqueId);
  1005. }
  1006. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1007. effect = nullptr;
  1008. }
  1009. else
  1010. {
  1011. uniqueIds.append(gVstCurrentUniqueId);
  1012. }
  1013. for (LinkedList<intptr_t>::Itenerator it = uniqueIds.begin2(); it.valid(); it.next())
  1014. {
  1015. gVstCurrentUniqueId = it.getValue(0);
  1016. if (effect == nullptr)
  1017. {
  1018. effect = vstFn(vstHostCallback);
  1019. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdentify), 0, 0, nullptr, 0.0f);
  1020. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effSetBlockSizeAndSampleRate), 0, kBufferSize, nullptr, kSampleRatef);
  1021. effect->dispatcher(effect, effSetSampleRate, 0, 0, nullptr, kSampleRatef);
  1022. effect->dispatcher(effect, effSetBlockSize, 0, kBufferSize, nullptr, 0.0f);
  1023. effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
  1024. effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
  1025. if (effect->numPrograms > 0)
  1026. effect->dispatcher(effect, effSetProgram, 0, 0, nullptr, 0.0f);
  1027. }
  1028. // get name
  1029. carla_zeroChars(strBuf, STR_MAX+1);
  1030. if (effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f) == 1)
  1031. cName = strBuf;
  1032. else
  1033. cName.clear();
  1034. // get product
  1035. carla_zeroChars(strBuf, STR_MAX+1);
  1036. if (effect->dispatcher(effect, effGetProductString, 0, 0, strBuf, 0.0f) == 1)
  1037. cProduct = strBuf;
  1038. else
  1039. cProduct.clear();
  1040. // get vendor
  1041. carla_zeroChars(strBuf, STR_MAX+1);
  1042. if (effect->dispatcher(effect, effGetVendorString, 0, 0, strBuf, 0.0f) == 1)
  1043. cVendor = strBuf;
  1044. else
  1045. cVendor.clear();
  1046. // get everything else
  1047. uint hints = 0x0;
  1048. int audioIns = effect->numInputs;
  1049. int audioOuts = effect->numOutputs;
  1050. int midiIns = 0;
  1051. int midiOuts = 0;
  1052. int parameters = effect->numParams;
  1053. if (effect->flags & effFlagsHasEditor)
  1054. hints |= PLUGIN_HAS_CUSTOM_UI;
  1055. if (effect->flags & effFlagsIsSynth)
  1056. hints |= PLUGIN_IS_SYNTH;
  1057. if (vstPluginCanDo(effect, "receiveVstEvents") || vstPluginCanDo(effect, "receiveVstMidiEvent") || (effect->flags & effFlagsIsSynth) != 0)
  1058. midiIns = 1;
  1059. if (vstPluginCanDo(effect, "sendVstEvents") || vstPluginCanDo(effect, "sendVstMidiEvent"))
  1060. midiOuts = 1;
  1061. // -----------------------------------------------------------------------
  1062. // start crash-free plugin test
  1063. if (doInit)
  1064. {
  1065. if (gVstNeedsIdle)
  1066. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1067. effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
  1068. effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
  1069. if (gVstNeedsIdle)
  1070. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1071. // Plugin might call wantMidi() during resume
  1072. if (midiIns == 0 && gVstWantsMidi)
  1073. {
  1074. midiIns = 1;
  1075. }
  1076. float* bufferAudioIn[audioIns];
  1077. for (int j=0; j < audioIns; ++j)
  1078. {
  1079. bufferAudioIn[j] = new float[kBufferSize];
  1080. carla_zeroFloats(bufferAudioIn[j], kBufferSize);
  1081. }
  1082. float* bufferAudioOut[audioOuts];
  1083. for (int j=0; j < audioOuts; ++j)
  1084. {
  1085. bufferAudioOut[j] = new float[kBufferSize];
  1086. carla_zeroFloats(bufferAudioOut[j], kBufferSize);
  1087. }
  1088. struct VstEventsFixed {
  1089. int32_t numEvents;
  1090. intptr_t reserved;
  1091. VstEvent* data[2];
  1092. VstEventsFixed()
  1093. : numEvents(0),
  1094. reserved(0)
  1095. {
  1096. data[0] = data[1] = nullptr;
  1097. }
  1098. } events;
  1099. VstMidiEvent midiEvents[2];
  1100. carla_zeroStructs(midiEvents, 2);
  1101. midiEvents[0].type = kVstMidiType;
  1102. midiEvents[0].byteSize = sizeof(VstMidiEvent);
  1103. midiEvents[0].midiData[0] = char(MIDI_STATUS_NOTE_ON);
  1104. midiEvents[0].midiData[1] = 64;
  1105. midiEvents[0].midiData[2] = 100;
  1106. midiEvents[1].type = kVstMidiType;
  1107. midiEvents[1].byteSize = sizeof(VstMidiEvent);
  1108. midiEvents[1].midiData[0] = char(MIDI_STATUS_NOTE_OFF);
  1109. midiEvents[1].midiData[1] = 64;
  1110. midiEvents[1].deltaFrames = kBufferSize/2;
  1111. events.numEvents = 2;
  1112. events.data[0] = (VstEvent*)&midiEvents[0];
  1113. events.data[1] = (VstEvent*)&midiEvents[1];
  1114. // processing
  1115. gVstIsProcessing = true;
  1116. if (midiIns > 0)
  1117. effect->dispatcher(effect, effProcessEvents, 0, 0, &events, 0.0f);
  1118. if ((effect->flags & effFlagsCanReplacing) > 0 && effect->processReplacing != nullptr && effect->processReplacing != effect->DECLARE_VST_DEPRECATED(process))
  1119. effect->processReplacing(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1120. else if (effect->DECLARE_VST_DEPRECATED(process) != nullptr)
  1121. effect->DECLARE_VST_DEPRECATED(process)(effect, bufferAudioIn, bufferAudioOut, kBufferSize);
  1122. else
  1123. DISCOVERY_OUT("error", "Plugin doesn't have a process function");
  1124. gVstIsProcessing = false;
  1125. effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
  1126. effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
  1127. if (gVstNeedsIdle)
  1128. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1129. for (int j=0; j < audioIns; ++j)
  1130. delete[] bufferAudioIn[j];
  1131. for (int j=0; j < audioOuts; ++j)
  1132. delete[] bufferAudioOut[j];
  1133. }
  1134. // end crash-free plugin test
  1135. // -----------------------------------------------------------------------
  1136. DISCOVERY_OUT("init", "-----------");
  1137. DISCOVERY_OUT("build", BINARY_NATIVE);
  1138. DISCOVERY_OUT("hints", hints);
  1139. DISCOVERY_OUT("name", cName.buffer());
  1140. DISCOVERY_OUT("label", cProduct.buffer());
  1141. DISCOVERY_OUT("maker", cVendor.buffer());
  1142. DISCOVERY_OUT("uniqueId", gVstCurrentUniqueId);
  1143. DISCOVERY_OUT("audio.ins", audioIns);
  1144. DISCOVERY_OUT("audio.outs", audioOuts);
  1145. DISCOVERY_OUT("midi.ins", midiIns);
  1146. DISCOVERY_OUT("midi.outs", midiOuts);
  1147. DISCOVERY_OUT("parameters.ins", parameters);
  1148. DISCOVERY_OUT("end", "------------");
  1149. gVstWantsMidi = false;
  1150. gVstWantsTime = false;
  1151. if (! isShell)
  1152. break;
  1153. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1154. effect = nullptr;
  1155. }
  1156. uniqueIds.clear();
  1157. if (effect == nullptr)
  1158. return;
  1159. if (gVstNeedsIdle)
  1160. effect->dispatcher(effect, DECLARE_VST_DEPRECATED(effIdle), 0, 0, nullptr, 0.0f);
  1161. effect->dispatcher(effect, effClose, 0, 0, nullptr, 0.0f);
  1162. }
  1163. #endif // ! CARLA_OS_MAC
  1164. #ifdef USE_JUCE_PROCESSORS
  1165. static void do_juce_check(const char* const filename_, const char* const stype, const bool doInit)
  1166. {
  1167. CARLA_SAFE_ASSERT_RETURN(stype != nullptr && stype[0] != 0,) // FIXME
  1168. carla_debug("do_juce_check(%s, %s, %s)", filename_, stype, bool2str(doInit));
  1169. using namespace juce;
  1170. juce::String filename;
  1171. #ifdef CARLA_OS_WIN
  1172. // Fix for wine usage
  1173. if (juce_isRunningInWine() && filename_[0] == '/')
  1174. {
  1175. filename = filename_;
  1176. filename.replace("/", "\\");
  1177. filename = "Z:" + filename;
  1178. }
  1179. else
  1180. #endif
  1181. filename = File(filename_).getFullPathName();
  1182. juce::ScopedPointer<AudioPluginFormat> pluginFormat;
  1183. /* */ if (std::strcmp(stype, "VST2") == 0)
  1184. {
  1185. #if JUCE_PLUGINHOST_VST
  1186. pluginFormat = new VSTPluginFormat();
  1187. #else
  1188. DISCOVERY_OUT("error", "VST support not available");
  1189. #endif
  1190. }
  1191. else if (std::strcmp(stype, "VST3") == 0)
  1192. {
  1193. #if JUCE_PLUGINHOST_VST3
  1194. pluginFormat = new VST3PluginFormat();
  1195. #else
  1196. DISCOVERY_OUT("error", "VST3 support not available");
  1197. #endif
  1198. }
  1199. else if (std::strcmp(stype, "AU") == 0)
  1200. {
  1201. #if JUCE_PLUGINHOST_AU
  1202. pluginFormat = new AudioUnitPluginFormat();
  1203. #else
  1204. DISCOVERY_OUT("error", "AU support not available");
  1205. #endif
  1206. }
  1207. if (pluginFormat == nullptr)
  1208. {
  1209. DISCOVERY_OUT("error", stype << " support not available");
  1210. return;
  1211. }
  1212. #ifdef CARLA_OS_WIN
  1213. CARLA_SAFE_ASSERT_RETURN(File(filename).existsAsFile(),);
  1214. #endif
  1215. CARLA_SAFE_ASSERT_RETURN(pluginFormat->fileMightContainThisPluginType(filename),);
  1216. OwnedArray<PluginDescription> results;
  1217. pluginFormat->findAllTypesForFile(results, filename);
  1218. if (results.size() == 0)
  1219. {
  1220. DISCOVERY_OUT("error", "No plugins found");
  1221. return;
  1222. }
  1223. for (PluginDescription **it = results.begin(), **end = results.end(); it != end; ++it)
  1224. {
  1225. PluginDescription* const desc(*it);
  1226. uint hints = 0x0;
  1227. int audioIns = desc->numInputChannels;
  1228. int audioOuts = desc->numOutputChannels;
  1229. int midiIns = 0;
  1230. int midiOuts = 0;
  1231. int parameters = 0;
  1232. if (desc->isInstrument)
  1233. hints |= PLUGIN_IS_SYNTH;
  1234. if (doInit)
  1235. {
  1236. if (AudioPluginInstance* const instance = pluginFormat->createInstanceFromDescription(*desc, kSampleRate, kBufferSize))
  1237. {
  1238. instance->refreshParameterList();
  1239. parameters = instance->getNumParameters();
  1240. if (instance->hasEditor())
  1241. hints |= PLUGIN_HAS_CUSTOM_UI;
  1242. if (instance->acceptsMidi())
  1243. midiIns = 1;
  1244. if (instance->producesMidi())
  1245. midiOuts = 1;
  1246. delete instance;
  1247. }
  1248. }
  1249. DISCOVERY_OUT("init", "-----------");
  1250. DISCOVERY_OUT("build", BINARY_NATIVE);
  1251. DISCOVERY_OUT("hints", hints);
  1252. DISCOVERY_OUT("name", desc->descriptiveName);
  1253. DISCOVERY_OUT("label", desc->name);
  1254. DISCOVERY_OUT("maker", desc->manufacturerName);
  1255. DISCOVERY_OUT("uniqueId", desc->uid);
  1256. DISCOVERY_OUT("audio.ins", audioIns);
  1257. DISCOVERY_OUT("audio.outs", audioOuts);
  1258. DISCOVERY_OUT("midi.ins", midiIns);
  1259. DISCOVERY_OUT("midi.outs", midiOuts);
  1260. DISCOVERY_OUT("parameters.ins", parameters);
  1261. DISCOVERY_OUT("end", "------------");
  1262. }
  1263. }
  1264. #endif
  1265. static void do_fluidsynth_check(const char* const filename, const bool doInit)
  1266. {
  1267. #ifdef HAVE_FLUIDSYNTH
  1268. const juce::String jfilename = juce::String(CharPointer_UTF8(filename));
  1269. const File file(jfilename);
  1270. if (! file.existsAsFile())
  1271. {
  1272. DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
  1273. return;
  1274. }
  1275. if (! fluid_is_soundfont(filename))
  1276. {
  1277. DISCOVERY_OUT("error", "Not a SF2 file");
  1278. return;
  1279. }
  1280. int programs = 0;
  1281. if (doInit)
  1282. {
  1283. fluid_settings_t* const f_settings = new_fluid_settings();
  1284. CARLA_SAFE_ASSERT_RETURN(f_settings != nullptr,);
  1285. fluid_synth_t* const f_synth = new_fluid_synth(f_settings);
  1286. CARLA_SAFE_ASSERT_RETURN(f_synth != nullptr,);
  1287. const int f_id = fluid_synth_sfload(f_synth, filename, 0);
  1288. if (f_id < 0)
  1289. {
  1290. DISCOVERY_OUT("error", "Failed to load SF2 file");
  1291. return;
  1292. }
  1293. if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(f_synth, static_cast<uint>(f_id)))
  1294. {
  1295. fluid_preset_t f_preset;
  1296. f_sfont->iteration_start(f_sfont);
  1297. for (; f_sfont->iteration_next(f_sfont, &f_preset);)
  1298. ++programs;
  1299. }
  1300. delete_fluid_synth(f_synth);
  1301. delete_fluid_settings(f_settings);
  1302. }
  1303. CarlaString name(file.getFileNameWithoutExtension().toRawUTF8());
  1304. CarlaString label(name);
  1305. // 2 channels
  1306. DISCOVERY_OUT("init", "-----------");
  1307. DISCOVERY_OUT("build", BINARY_NATIVE);
  1308. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1309. DISCOVERY_OUT("name", name.buffer());
  1310. DISCOVERY_OUT("label", label.buffer());
  1311. DISCOVERY_OUT("audio.outs", 2);
  1312. DISCOVERY_OUT("midi.ins", 1);
  1313. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1314. DISCOVERY_OUT("parameters.outs", 1);
  1315. DISCOVERY_OUT("end", "------------");
  1316. // 16 channels
  1317. if (doInit && (name.isEmpty() || programs <= 1))
  1318. return;
  1319. name += " (16 outputs)";
  1320. DISCOVERY_OUT("init", "-----------");
  1321. DISCOVERY_OUT("build", BINARY_NATIVE);
  1322. DISCOVERY_OUT("hints", PLUGIN_IS_SYNTH);
  1323. DISCOVERY_OUT("name", name.buffer());
  1324. DISCOVERY_OUT("label", label.buffer());
  1325. DISCOVERY_OUT("audio.outs", 32);
  1326. DISCOVERY_OUT("midi.ins", 1);
  1327. DISCOVERY_OUT("parameters.ins", 13); // defined in Carla
  1328. DISCOVERY_OUT("parameters.outs", 1);
  1329. DISCOVERY_OUT("end", "------------");
  1330. #else // HAVE_FLUIDSYNTH
  1331. DISCOVERY_OUT("error", "SF2 support not available");
  1332. return;
  1333. // unused
  1334. (void)filename;
  1335. (void)doInit;
  1336. #endif
  1337. }
  1338. static void do_linuxsampler_check(const char* const filename, const char* const stype, const bool doInit)
  1339. {
  1340. #ifdef HAVE_LINUXSAMPLER
  1341. const juce::String jfilename = juce::String(CharPointer_UTF8(filename));
  1342. const File file(jfilename);
  1343. if (! file.existsAsFile())
  1344. {
  1345. DISCOVERY_OUT("error", "Requested file is not valid or does not exist");
  1346. return;
  1347. }
  1348. if (doInit)
  1349. const LinuxSamplerScopedEngine engine(filename, stype);
  1350. else
  1351. LinuxSamplerScopedEngine::outputInfo(nullptr, file.getFileNameWithoutExtension().toRawUTF8(), std::strcmp(stype, "gig") == 0);
  1352. #else // HAVE_LINUXSAMPLER
  1353. DISCOVERY_OUT("error", stype << " support not available");
  1354. return;
  1355. // unused
  1356. (void)filename;
  1357. (void)doInit;
  1358. #endif
  1359. }
  1360. // ------------------------------ main entry point ------------------------------
  1361. int main(int argc, char* argv[])
  1362. {
  1363. if (argc != 3)
  1364. {
  1365. carla_stdout("usage: %s <type> </path/to/plugin>", argv[0]);
  1366. return 1;
  1367. }
  1368. const char* const stype = argv[1];
  1369. const char* const filename = argv[2];
  1370. const PluginType type = getPluginTypeFromString(stype);
  1371. CarlaString filenameCheck(filename);
  1372. filenameCheck.toLower();
  1373. if (type != PLUGIN_GIG && type != PLUGIN_SF2 && type != PLUGIN_SFZ)
  1374. {
  1375. if (filenameCheck.contains("fluidsynth", true))
  1376. {
  1377. DISCOVERY_OUT("info", "skipping fluidsynth based plugin");
  1378. return 0;
  1379. }
  1380. if (filenameCheck.contains("linuxsampler", true) || filenameCheck.endsWith("ls16.so"))
  1381. {
  1382. DISCOVERY_OUT("info", "skipping linuxsampler based plugin");
  1383. return 0;
  1384. }
  1385. }
  1386. bool openLib = false;
  1387. lib_t handle = nullptr;
  1388. switch (type)
  1389. {
  1390. case PLUGIN_LADSPA:
  1391. case PLUGIN_DSSI:
  1392. #ifndef CARLA_OS_MAC
  1393. case PLUGIN_VST2:
  1394. openLib = true;
  1395. #endif
  1396. default:
  1397. break;
  1398. }
  1399. if (openLib)
  1400. {
  1401. handle = lib_open(filename);
  1402. if (handle == nullptr)
  1403. {
  1404. print_lib_error(filename);
  1405. return 1;
  1406. }
  1407. }
  1408. // never do init for dssi-vst, takes too long and it's crashy
  1409. bool doInit = ! filenameCheck.contains("dssi-vst", true);
  1410. if (doInit && getenv("CARLA_DISCOVERY_NO_PROCESSING_CHECKS") != nullptr)
  1411. doInit = false;
  1412. if (doInit && handle != nullptr)
  1413. {
  1414. // test fast loading & unloading DLL without initializing the plugin(s)
  1415. if (! lib_close(handle))
  1416. {
  1417. print_lib_error(filename);
  1418. return 1;
  1419. }
  1420. handle = lib_open(filename);
  1421. if (handle == nullptr)
  1422. {
  1423. print_lib_error(filename);
  1424. return 1;
  1425. }
  1426. }
  1427. if (std::strcmp(filename, ":all") == 0)
  1428. {
  1429. do_cached_check(type);
  1430. return 0;
  1431. }
  1432. switch (type)
  1433. {
  1434. case PLUGIN_LADSPA:
  1435. do_ladspa_check(handle, filename, doInit);
  1436. break;
  1437. case PLUGIN_DSSI:
  1438. do_dssi_check(handle, filename, doInit);
  1439. break;
  1440. case PLUGIN_LV2:
  1441. do_lv2_check(filename, doInit);
  1442. break;
  1443. case PLUGIN_VST2:
  1444. #ifdef CARLA_OS_MAC
  1445. do_juce_check(filename, "VST2", doInit);
  1446. #else
  1447. do_vst_check(handle, doInit);
  1448. #endif
  1449. break;
  1450. case PLUGIN_VST3:
  1451. #ifdef USE_JUCE_PROCESSORS
  1452. do_juce_check(filename, "VST3", doInit);
  1453. #else
  1454. DISCOVERY_OUT("error", "VST3 support not available");
  1455. #endif
  1456. break;
  1457. case PLUGIN_AU:
  1458. #ifdef USE_JUCE_PROCESSORS
  1459. do_juce_check(filename, "AU", doInit);
  1460. #else
  1461. DISCOVERY_OUT("error", "AU support not available");
  1462. #endif
  1463. break;
  1464. case PLUGIN_GIG:
  1465. do_linuxsampler_check(filename, "gig", doInit);
  1466. break;
  1467. case PLUGIN_SF2:
  1468. do_fluidsynth_check(filename, doInit);
  1469. break;
  1470. case PLUGIN_SFZ:
  1471. do_linuxsampler_check(filename, "sfz", doInit);
  1472. break;
  1473. default:
  1474. break;
  1475. }
  1476. if (openLib && handle != nullptr)
  1477. lib_close(handle);
  1478. return 0;
  1479. }
  1480. // --------------------------------------------------------------------------