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.

740 lines
25KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2014 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 "CarlaHost.h"
  18. #include "CarlaNative.h"
  19. #include "CarlaLv2Utils.hpp"
  20. #include "CarlaPlugin.hpp"
  21. #include "CarlaString.hpp"
  22. #include "juce_audio_formats.h"
  23. #ifdef CARLA_OS_MAC
  24. # include "juce_audio_processors.h"
  25. using juce::AudioUnitPluginFormat;
  26. using juce::StringArray;
  27. #endif
  28. namespace CB = CarlaBackend;
  29. // -------------------------------------------------------------------------------------------------------------------
  30. // Always return a valid string ptr
  31. static const char* const gNullCharPtr = "";
  32. #ifdef CARLA_COMMON_NEED_CHECKSTRINGPTR
  33. static void checkStringPtr(const char*& charPtr) noexcept
  34. {
  35. if (charPtr == nullptr)
  36. charPtr = gNullCharPtr;
  37. }
  38. #endif
  39. // -------------------------------------------------------------------------------------------------------------------
  40. // Constructors
  41. _CarlaPluginInfo::_CarlaPluginInfo() noexcept
  42. : type(CB::PLUGIN_NONE),
  43. category(CB::PLUGIN_CATEGORY_NONE),
  44. hints(0x0),
  45. optionsAvailable(0x0),
  46. optionsEnabled(0x0),
  47. filename(gNullCharPtr),
  48. name(gNullCharPtr),
  49. label(gNullCharPtr),
  50. maker(gNullCharPtr),
  51. copyright(gNullCharPtr),
  52. iconName(gNullCharPtr),
  53. uniqueId(0) {}
  54. _CarlaPluginInfo::~_CarlaPluginInfo() noexcept
  55. {
  56. if (label != gNullCharPtr)
  57. delete[] label;
  58. if (maker != gNullCharPtr)
  59. delete[] maker;
  60. if (copyright != gNullCharPtr)
  61. delete[] copyright;
  62. }
  63. _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
  64. : category(CB::PLUGIN_CATEGORY_NONE),
  65. hints(0x0),
  66. audioIns(0),
  67. audioOuts(0),
  68. midiIns(0),
  69. midiOuts(0),
  70. parameterIns(0),
  71. parameterOuts(0),
  72. name(gNullCharPtr),
  73. label(gNullCharPtr),
  74. maker(gNullCharPtr),
  75. copyright(gNullCharPtr) {}
  76. _CarlaParameterInfo::_CarlaParameterInfo() noexcept
  77. : name(gNullCharPtr),
  78. symbol(gNullCharPtr),
  79. unit(gNullCharPtr),
  80. scalePointCount(0) {}
  81. _CarlaParameterInfo::~_CarlaParameterInfo() noexcept
  82. {
  83. if (name != gNullCharPtr)
  84. delete[] name;
  85. if (symbol != gNullCharPtr)
  86. delete[] symbol;
  87. if (unit != gNullCharPtr)
  88. delete[] unit;
  89. }
  90. _CarlaScalePointInfo::_CarlaScalePointInfo() noexcept
  91. : value(0.0f),
  92. label(gNullCharPtr) {}
  93. _CarlaScalePointInfo::~_CarlaScalePointInfo() noexcept
  94. {
  95. if (label != gNullCharPtr)
  96. delete[] label;
  97. }
  98. _CarlaTransportInfo::_CarlaTransportInfo() noexcept
  99. : playing(false),
  100. frame(0),
  101. bar(0),
  102. beat(0),
  103. tick(0),
  104. bpm(0.0) {}
  105. // -------------------------------------------------------------------------------------------------------------------
  106. const char* carla_get_complete_license_text()
  107. {
  108. carla_debug("carla_get_complete_license_text()");
  109. static CarlaString retText;
  110. if (retText.isEmpty())
  111. {
  112. retText =
  113. "<p>This current Carla build is using the following features and 3rd-party code:</p>"
  114. "<ul>"
  115. // Plugin formats
  116. "<li>LADSPA plugin support</li>"
  117. "<li>DSSI plugin support</li>"
  118. "<li>LV2 plugin support</li>"
  119. #ifdef VESTIGE_HEADER
  120. "<li>VST2 plugin support using VeSTige header by Javier Serrano Polo</li>"
  121. #else
  122. "<li>VST2 plugin support using official VST SDK 2.4 [1]</li>"
  123. #endif
  124. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
  125. "<li>VST3 plugin support using official VST SDK 3.6 [1]</li>"
  126. #endif
  127. #ifdef CARLA_OS_MAC
  128. "<li>AU plugin support</li>"
  129. #endif
  130. // Sample kit libraries
  131. #ifdef HAVE_FLUIDSYNTH
  132. "<li>FluidSynth library for SF2 support</li>"
  133. #endif
  134. #ifdef HAVE_LINUXSAMPLER
  135. "<li>LinuxSampler library for GIG and SFZ support [2]</li>"
  136. #endif
  137. // Internal plugins
  138. "<li>NekoFilter plugin code based on lv2fil by Nedko Arnaudov and Fons Adriaensen</li>"
  139. #ifdef WANT_ZYNADDSUBFX
  140. "<li>ZynAddSubFX plugin code</li>"
  141. #endif
  142. // misc libs
  143. "<li>base64 utilities based on code by Ren\u00E9 Nyffenegger</li>"
  144. #ifdef CARLA_OS_MAC
  145. "<li>sem_timedwait for Mac OS by Keith Shortridge</li>"
  146. #endif
  147. "<li>liblo library for OSC support</li>"
  148. "<li>rtmempool library by Nedko Arnaudov"
  149. "<li>serd, sord, sratom and lilv libraries for LV2 discovery</li>"
  150. #if ! (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
  151. "<li>RtAudio and RtMidi libraries for extra Audio and MIDI support</li>"
  152. #endif
  153. // end
  154. "</ul>"
  155. "<p>"
  156. #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) || ! defined(VESTIGE_HEADER)
  157. // Required by VST SDK
  158. "&nbsp;[1] Trademark of Steinberg Media Technologies GmbH.<br/>"
  159. #endif
  160. #ifdef HAVE_LINUXSAMPLER
  161. // LinuxSampler GPL exception
  162. "&nbsp;[2] Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors."
  163. #endif
  164. "</p>"
  165. ;
  166. }
  167. return retText;
  168. }
  169. const char* carla_get_juce_version()
  170. {
  171. carla_debug("carla_get_juce_version()");
  172. static CarlaString retVersion;
  173. if (retVersion.isEmpty())
  174. {
  175. if (const char* const version = juce::SystemStats::getJUCEVersion().toRawUTF8())
  176. retVersion = version+6;
  177. else
  178. retVersion = "3.0";
  179. }
  180. return retVersion;
  181. }
  182. const char* carla_get_supported_file_extensions()
  183. {
  184. carla_debug("carla_get_supported_file_extensions()");
  185. static CarlaString retText;
  186. if (retText.isEmpty())
  187. {
  188. retText =
  189. // Base types
  190. "*.carxp;*.carxs"
  191. // MIDI files
  192. ";*.mid;*.midi"
  193. #ifdef HAVE_FLUIDSYNTH
  194. // fluidsynth (sf2)
  195. ";*.sf2"
  196. #endif
  197. #ifdef HAVE_LINUXSAMPLER
  198. // linuxsampler (gig and sfz)
  199. ";*.gig;*.sfz"
  200. #endif
  201. #ifdef WANT_ZYNADDSUBFX
  202. // zynaddsubfx presets
  203. ";*.xmz;*.xiz"
  204. #endif
  205. ;
  206. #ifndef BUILD_BRIDGE
  207. // Audio files
  208. {
  209. using namespace juce;
  210. AudioFormatManager afm;
  211. afm.registerBasicFormats();
  212. String juceFormats;
  213. for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it)
  214. {
  215. const StringArray& exts((*it)->getFileExtensions());
  216. for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit)
  217. juceFormats += String(";*" + (*eit)).toRawUTF8();
  218. }
  219. retText += juceFormats.toRawUTF8();
  220. }
  221. #endif
  222. }
  223. return retText;
  224. }
  225. // -------------------------------------------------------------------------------------------------------------------
  226. #ifdef CARLA_OS_MAC
  227. static StringArray gCachedAuPluginResults;
  228. #endif
  229. uint carla_get_cached_plugin_count(PluginType ptype, const char* pluginPath)
  230. {
  231. CARLA_SAFE_ASSERT_RETURN(ptype == CB::PLUGIN_INTERNAL || ptype == CB::PLUGIN_LV2 || ptype == CB::PLUGIN_AU, 0);
  232. carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));
  233. switch (ptype)
  234. {
  235. case CB::PLUGIN_INTERNAL: {
  236. #ifndef BUILD_BRIDGE
  237. return static_cast<uint>(CarlaPlugin::getNativePluginCount());
  238. #else
  239. return 0;
  240. #endif
  241. }
  242. case CB::PLUGIN_LV2: {
  243. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  244. lv2World.initIfNeeded(pluginPath);
  245. return lv2World.getPluginCount();
  246. }
  247. case CB::PLUGIN_AU: {
  248. #ifdef CARLA_OS_MAC
  249. static bool initiated = false;
  250. if (initiated)
  251. return static_cast<uint>(gCachedAuPluginResults.size());
  252. initiated = true;
  253. AudioUnitPluginFormat auFormat;
  254. gCachedAuPluginResults = auFormat.searchPathsForPlugins(juce::FileSearchPath(), false);
  255. return static_cast<uint>(gCachedAuPluginResults.size());
  256. #else
  257. return 0;
  258. #endif
  259. }
  260. default:
  261. return 0;
  262. }
  263. }
  264. const CarlaCachedPluginInfo* carla_get_cached_plugin_info(PluginType ptype, uint index)
  265. {
  266. carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);
  267. static CarlaCachedPluginInfo info;
  268. switch (ptype)
  269. {
  270. case CB::PLUGIN_INTERNAL: {
  271. #ifndef BUILD_BRIDGE
  272. const NativePluginDescriptor* const desc(CarlaPlugin::getNativePluginDescriptor(index));
  273. CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
  274. info.category = static_cast<CB::PluginCategory>(desc->category);
  275. info.hints = 0x0;
  276. if (desc->hints & NATIVE_PLUGIN_IS_RTSAFE)
  277. info.hints |= CB::PLUGIN_IS_RTSAFE;
  278. if (desc->hints & NATIVE_PLUGIN_IS_SYNTH)
  279. info.hints |= CB::PLUGIN_IS_SYNTH;
  280. if (desc->hints & NATIVE_PLUGIN_HAS_UI)
  281. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  282. if (desc->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
  283. info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
  284. if (desc->hints & NATIVE_PLUGIN_NEEDS_SINGLE_THREAD)
  285. info.hints |= CB::PLUGIN_NEEDS_SINGLE_THREAD;
  286. info.audioIns = desc->audioIns;
  287. info.audioOuts = desc->audioOuts;
  288. info.midiIns = desc->midiIns;
  289. info.midiOuts = desc->midiOuts;
  290. info.parameterIns = desc->paramIns;
  291. info.parameterOuts = desc->paramOuts;
  292. info.name = desc->name;
  293. info.label = desc->label;
  294. info.maker = desc->maker;
  295. info.copyright = desc->copyright;
  296. return &info;
  297. #else
  298. break;
  299. #endif
  300. }
  301. case CB::PLUGIN_LV2: {
  302. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  303. const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
  304. CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
  305. Lilv::Plugin lilvPlugin(cPlugin);
  306. CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
  307. // features
  308. info.hints = 0x0;
  309. if (lilvPlugin.get_uis().size() > 0 || lilvPlugin.get_modgui_resources_directory().as_uri() != nullptr)
  310. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  311. {
  312. Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
  313. LILV_FOREACH(nodes, it, lilvFeatureNodes)
  314. {
  315. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
  316. const char* const featureURI(lilvFeatureNode.as_uri());
  317. CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
  318. if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
  319. info.hints |= CB::PLUGIN_IS_RTSAFE;
  320. }
  321. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  322. }
  323. // category
  324. info.category = CB::PLUGIN_CATEGORY_NONE;
  325. {
  326. Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
  327. if (typeNodes.size() > 0)
  328. {
  329. if (typeNodes.contains(lv2World.class_allpass))
  330. info.category = CB::PLUGIN_CATEGORY_FILTER;
  331. if (typeNodes.contains(lv2World.class_amplifier))
  332. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  333. if (typeNodes.contains(lv2World.class_analyzer))
  334. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  335. if (typeNodes.contains(lv2World.class_bandpass))
  336. info.category = CB::PLUGIN_CATEGORY_FILTER;
  337. if (typeNodes.contains(lv2World.class_chorus))
  338. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  339. if (typeNodes.contains(lv2World.class_comb))
  340. info.category = CB::PLUGIN_CATEGORY_FILTER;
  341. if (typeNodes.contains(lv2World.class_compressor))
  342. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  343. if (typeNodes.contains(lv2World.class_constant))
  344. info.category = CB::PLUGIN_CATEGORY_OTHER;
  345. if (typeNodes.contains(lv2World.class_converter))
  346. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  347. if (typeNodes.contains(lv2World.class_delay))
  348. info.category = CB::PLUGIN_CATEGORY_DELAY;
  349. if (typeNodes.contains(lv2World.class_distortion))
  350. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  351. if (typeNodes.contains(lv2World.class_dynamics))
  352. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  353. if (typeNodes.contains(lv2World.class_eq))
  354. info.category = CB::PLUGIN_CATEGORY_EQ;
  355. if (typeNodes.contains(lv2World.class_envelope))
  356. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  357. if (typeNodes.contains(lv2World.class_expander))
  358. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  359. if (typeNodes.contains(lv2World.class_filter))
  360. info.category = CB::PLUGIN_CATEGORY_FILTER;
  361. if (typeNodes.contains(lv2World.class_flanger))
  362. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  363. if (typeNodes.contains(lv2World.class_function))
  364. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  365. if (typeNodes.contains(lv2World.class_gate))
  366. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  367. if (typeNodes.contains(lv2World.class_generator))
  368. info.category = CB::PLUGIN_CATEGORY_OTHER;
  369. if (typeNodes.contains(lv2World.class_highpass))
  370. info.category = CB::PLUGIN_CATEGORY_FILTER;
  371. if (typeNodes.contains(lv2World.class_limiter))
  372. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  373. if (typeNodes.contains(lv2World.class_lowpass))
  374. info.category = CB::PLUGIN_CATEGORY_FILTER;
  375. if (typeNodes.contains(lv2World.class_mixer))
  376. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  377. if (typeNodes.contains(lv2World.class_modulator))
  378. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  379. if (typeNodes.contains(lv2World.class_multiEQ))
  380. info.category = CB::PLUGIN_CATEGORY_EQ;
  381. if (typeNodes.contains(lv2World.class_oscillator))
  382. info.category = CB::PLUGIN_CATEGORY_OTHER;
  383. if (typeNodes.contains(lv2World.class_paraEQ))
  384. info.category = CB::PLUGIN_CATEGORY_EQ;
  385. if (typeNodes.contains(lv2World.class_phaser))
  386. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  387. if (typeNodes.contains(lv2World.class_pitch))
  388. info.category = CB::PLUGIN_CATEGORY_OTHER;
  389. if (typeNodes.contains(lv2World.class_reverb))
  390. info.category = CB::PLUGIN_CATEGORY_DELAY;
  391. if (typeNodes.contains(lv2World.class_simulator))
  392. info.category = CB::PLUGIN_CATEGORY_OTHER;
  393. if (typeNodes.contains(lv2World.class_spatial))
  394. info.category = CB::PLUGIN_CATEGORY_OTHER;
  395. if (typeNodes.contains(lv2World.class_spectral))
  396. info.category = CB::PLUGIN_CATEGORY_OTHER;
  397. if (typeNodes.contains(lv2World.class_utility))
  398. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  399. if (typeNodes.contains(lv2World.class_waveshaper))
  400. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  401. if (typeNodes.contains(lv2World.class_instrument))
  402. {
  403. info.category = CB::PLUGIN_CATEGORY_SYNTH;
  404. info.hints |= CB::PLUGIN_IS_SYNTH;
  405. }
  406. }
  407. lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
  408. }
  409. // number data
  410. info.audioIns = 0;
  411. info.audioOuts = 0;
  412. info.midiIns = 0;
  413. info.midiOuts = 0;
  414. info.parameterIns = 0;
  415. info.parameterOuts = 0;
  416. for (uint i=0, count=lilvPlugin.get_num_ports(); i<count; ++i)
  417. {
  418. Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
  419. bool isInput;
  420. /**/ if (lilvPort.is_a(lv2World.port_input))
  421. isInput = true;
  422. else if (lilvPort.is_a(lv2World.port_output))
  423. isInput = false;
  424. else
  425. continue;
  426. /**/ if (lilvPort.is_a(lv2World.port_control))
  427. {
  428. // skip some control ports
  429. if (lilvPort.has_property(lv2World.reportsLatency))
  430. continue;
  431. if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
  432. {
  433. bool skip = false;
  434. if (const char* const designation = lilv_node_as_string(designationNode))
  435. {
  436. /**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
  437. skip = true;
  438. else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
  439. skip = true;
  440. else if (std::strcmp(designation, LV2_CORE__latency) == 0)
  441. skip = true;
  442. else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
  443. skip = true;
  444. else if (std::strcmp(designation, LV2_TIME__bar) == 0)
  445. skip = true;
  446. else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
  447. skip = true;
  448. else if (std::strcmp(designation, LV2_TIME__beat) == 0)
  449. skip = true;
  450. else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
  451. skip = true;
  452. else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
  453. skip = true;
  454. else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
  455. skip = true;
  456. else if (std::strcmp(designation, LV2_TIME__frame) == 0)
  457. skip = true;
  458. else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
  459. skip = true;
  460. else if (std::strcmp(designation, LV2_TIME__speed) == 0)
  461. skip = true;
  462. else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  463. skip = true;
  464. }
  465. lilv_node_free(designationNode);
  466. if (skip)
  467. continue;
  468. }
  469. if (isInput)
  470. ++(info.parameterIns);
  471. else
  472. ++(info.parameterOuts);
  473. }
  474. else if (lilvPort.is_a(lv2World.port_audio))
  475. {
  476. if (isInput)
  477. ++(info.audioIns);
  478. else
  479. ++(info.audioOuts);
  480. }
  481. else if (lilvPort.is_a(lv2World.port_cv))
  482. {
  483. }
  484. else if (lilvPort.is_a(lv2World.port_atom))
  485. {
  486. Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));
  487. for (LilvIter *it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
  488. {
  489. const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
  490. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  491. if (node.equals(lv2World.midi_event))
  492. {
  493. if (isInput)
  494. ++(info.midiIns);
  495. else
  496. ++(info.midiOuts);
  497. }
  498. }
  499. lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
  500. }
  501. else if (lilvPort.is_a(lv2World.port_event))
  502. {
  503. if (lilvPort.supports_event(lv2World.midi_event))
  504. {
  505. if (isInput)
  506. ++(info.midiIns);
  507. else
  508. ++(info.midiOuts);
  509. }
  510. }
  511. else if (lilvPort.is_a(lv2World.port_midi))
  512. {
  513. if (isInput)
  514. ++(info.midiIns);
  515. else
  516. ++(info.midiOuts);
  517. }
  518. }
  519. // text data
  520. static CarlaString suri, sname, smaker, slicense;
  521. suri.clear(); sname.clear(); smaker.clear(); slicense.clear();
  522. suri = lilvPlugin.get_uri().as_uri();
  523. if (const char* const name = lilvPlugin.get_name().as_string())
  524. sname = name;
  525. else
  526. sname.clear();
  527. if (const char* const author = lilvPlugin.get_author_name().as_string())
  528. smaker = author;
  529. else
  530. smaker.clear();
  531. Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
  532. if (licenseNodes.size() > 0)
  533. {
  534. if (const char* const license = licenseNodes.get_first().as_string())
  535. slicense = license;
  536. }
  537. lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
  538. info.name = sname;
  539. info.label = suri;
  540. info.maker = smaker;
  541. info.copyright = slicense;
  542. return &info;
  543. }
  544. case CB::PLUGIN_AU: {
  545. #ifdef CARLA_OS_MAC
  546. const int indexi(static_cast<int>(index));
  547. CARLA_SAFE_ASSERT_BREAK(indexi < gCachedAuPluginResults.size());
  548. using namespace juce;
  549. String pluginId(gCachedAuPluginResults[indexi]);
  550. OwnedArray<PluginDescription> results;
  551. AudioUnitPluginFormat auFormat;
  552. auFormat.findAllTypesForFile(results, pluginId);
  553. CARLA_SAFE_ASSERT_BREAK(results.size() > 0);
  554. CARLA_SAFE_ASSERT(results.size() == 1);
  555. PluginDescription* const desc(results[0]);
  556. CARLA_SAFE_ASSERT_BREAK(desc != nullptr);
  557. info.category = CB::getPluginCategoryFromName(desc->category.toRawUTF8());
  558. info.hints = 0x0;
  559. if (desc->isInstrument)
  560. info.hints |= CB::PLUGIN_IS_SYNTH;
  561. if (true)
  562. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  563. info.audioIns = static_cast<uint32_t>(desc->numInputChannels);
  564. info.audioOuts = static_cast<uint32_t>(desc->numOutputChannels);
  565. info.midiIns = desc->isInstrument ? 1 : 0;
  566. info.midiOuts = 0;
  567. info.parameterIns = 0;
  568. info.parameterOuts = 0;
  569. static CarlaString sname, slabel, smaker;
  570. sname = desc->name.toRawUTF8();
  571. slabel = desc->fileOrIdentifier.toRawUTF8();
  572. smaker = desc->manufacturerName.toRawUTF8();
  573. info.name = sname;
  574. info.label = slabel;
  575. info.maker = smaker;
  576. info.copyright = gNullCharPtr;
  577. return &info;
  578. #else
  579. break;
  580. #endif
  581. }
  582. default:
  583. break;
  584. }
  585. info.category = CB::PLUGIN_CATEGORY_NONE;
  586. info.hints = 0x0;
  587. info.audioIns = 0;
  588. info.audioOuts = 0;
  589. info.midiIns = 0;
  590. info.midiOuts = 0;
  591. info.parameterIns = 0;
  592. info.parameterOuts = 0;
  593. info.name = gNullCharPtr;
  594. info.label = gNullCharPtr;
  595. info.maker = gNullCharPtr;
  596. info.copyright = gNullCharPtr;
  597. return &info;
  598. }
  599. // -------------------------------------------------------------------------------------------------------------------
  600. const char* carla_get_library_filename()
  601. {
  602. carla_debug("carla_get_library_filename()");
  603. static CarlaString ret;
  604. if (ret.isEmpty())
  605. {
  606. using juce::File;
  607. ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8();
  608. }
  609. return ret;
  610. }
  611. const char* carla_get_library_folder()
  612. {
  613. carla_debug("carla_get_library_folder()");
  614. static CarlaString ret;
  615. if (ret.isEmpty())
  616. {
  617. using juce::File;
  618. ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8();
  619. }
  620. return ret;
  621. }
  622. // -------------------------------------------------------------------------------------------------------------------