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

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