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.

731 lines
24KB

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