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.

581 lines
20KB

  1. /*
  2. * Carla Plugin Host
  3. * Copyright (C) 2011-2018 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 "CarlaUtils.h"
  18. #include "CarlaNative.h"
  19. #include "CarlaString.hpp"
  20. #include "CarlaLv2Utils.hpp"
  21. #ifdef DEBUG
  22. # include "CarlaBackendUtils.hpp"
  23. #endif
  24. #include "water/containers/Array.h"
  25. #include "water/files/File.h"
  26. namespace CB = CarlaBackend;
  27. using water::Array;
  28. using water::File;
  29. using water::String;
  30. using water::StringArray;
  31. static const char* const gNullCharPtr = "";
  32. static bool isCachedPluginType(const CB::PluginType ptype)
  33. {
  34. switch (ptype)
  35. {
  36. case CB::PLUGIN_INTERNAL:
  37. case CB::PLUGIN_LV2:
  38. case CB::PLUGIN_SFZ:
  39. return true;
  40. default:
  41. return false;
  42. }
  43. }
  44. // -------------------------------------------------------------------------------------------------------------------
  45. _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
  46. : valid(false),
  47. category(CB::PLUGIN_CATEGORY_NONE),
  48. hints(0x0),
  49. audioIns(0),
  50. audioOuts(0),
  51. midiIns(0),
  52. midiOuts(0),
  53. parameterIns(0),
  54. parameterOuts(0),
  55. name(gNullCharPtr),
  56. label(gNullCharPtr),
  57. maker(gNullCharPtr),
  58. copyright(gNullCharPtr) {}
  59. // -------------------------------------------------------------------------------------------------------------------
  60. static Array<File> gSFZs;
  61. void findSFZs(const char* const sfzPaths)
  62. {
  63. CARLA_SAFE_ASSERT_RETURN(sfzPaths != nullptr,);
  64. if (sfzPaths[0] == '\0')
  65. return;
  66. const StringArray splitPaths(StringArray::fromTokens(sfzPaths, CARLA_OS_SPLIT_STR, ""));
  67. for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it)
  68. {
  69. Array<File> results;
  70. if (File(*it).findChildFiles(results, File::findFiles|File::ignoreHiddenFiles, true, "*.sfz") > 0)
  71. gSFZs.addArray(results);
  72. }
  73. }
  74. // -------------------------------------------------------------------------------------------------------------------
  75. const CarlaCachedPluginInfo* get_cached_plugin_internal(const NativePluginDescriptor& desc)
  76. {
  77. static CarlaCachedPluginInfo info;
  78. info.category = static_cast<CB::PluginCategory>(desc.category);
  79. info.hints = 0x0;
  80. if (desc.hints & NATIVE_PLUGIN_IS_RTSAFE)
  81. info.hints |= CB::PLUGIN_IS_RTSAFE;
  82. if (desc.hints & NATIVE_PLUGIN_IS_SYNTH)
  83. info.hints |= CB::PLUGIN_IS_SYNTH;
  84. if (desc.hints & NATIVE_PLUGIN_HAS_UI)
  85. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  86. if (desc.hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
  87. info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
  88. if (desc.hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD)
  89. info.hints |= CB::PLUGIN_NEEDS_UI_MAIN_THREAD;
  90. if (desc.hints & NATIVE_PLUGIN_USES_MULTI_PROGS)
  91. info.hints |= CB::PLUGIN_USES_MULTI_PROGS;
  92. info.valid = true;
  93. info.audioIns = desc.audioIns;
  94. info.audioOuts = desc.audioOuts;
  95. info.midiIns = desc.midiIns;
  96. info.midiOuts = desc.midiOuts;
  97. info.parameterIns = desc.paramIns;
  98. info.parameterOuts = desc.paramOuts;
  99. info.name = desc.name;
  100. info.label = desc.label;
  101. info.maker = desc.maker;
  102. info.copyright = desc.copyright;
  103. return &info;
  104. }
  105. const CarlaCachedPluginInfo* get_cached_plugin_lv2(Lv2WorldClass& lv2World, Lilv::Plugin& lilvPlugin)
  106. {
  107. static CarlaCachedPluginInfo info;
  108. info.valid = false;
  109. bool supported = true;
  110. // ----------------------------------------------------------------------------------------------------------------
  111. // text data
  112. {
  113. static CarlaString suri, sname, smaker, slicense;
  114. suri.clear(); sname.clear(); smaker.clear(); slicense.clear();
  115. suri = lilvPlugin.get_uri().as_uri();
  116. if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
  117. {
  118. if (const char* const name = lilv_node_as_string(nameNode))
  119. sname = name;
  120. lilv_node_free(nameNode);
  121. }
  122. if (const char* const author = lilvPlugin.get_author_name().as_string())
  123. smaker = author;
  124. Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
  125. if (licenseNodes.size() > 0)
  126. {
  127. if (const char* const license = licenseNodes.get_first().as_string())
  128. slicense = license;
  129. }
  130. lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
  131. info.name = sname.buffer();
  132. info.label = suri.buffer();
  133. info.maker = smaker.buffer();
  134. info.copyright = slicense.buffer();
  135. }
  136. // ----------------------------------------------------------------------------------------------------------------
  137. // features
  138. info.hints = 0x0;
  139. if (lilvPlugin.get_uis().size() > 0)
  140. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  141. {
  142. Lilv::Nodes lilvRequiredFeatureNodes(lilvPlugin.get_required_features());
  143. LILV_FOREACH(nodes, it, lilvRequiredFeatureNodes)
  144. {
  145. Lilv::Node lilvFeatureNode(lilvRequiredFeatureNodes.get(it));
  146. const char* const featureURI(lilvFeatureNode.as_uri());
  147. CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
  148. if (! is_lv2_feature_supported(featureURI))
  149. {
  150. if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0
  151. || std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0)
  152. {
  153. // we give a warning about this below
  154. continue;
  155. }
  156. supported = false;
  157. carla_stderr("LV2 plugin '%s' requires unsupported feature '%s'", info.label, featureURI);
  158. }
  159. }
  160. lilv_nodes_free(const_cast<LilvNodes*>(lilvRequiredFeatureNodes.me));
  161. }
  162. {
  163. Lilv::Nodes lilvSupportedFeatureNodes(lilvPlugin.get_supported_features());
  164. LILV_FOREACH(nodes, it, lilvSupportedFeatureNodes)
  165. {
  166. Lilv::Node lilvFeatureNode(lilvSupportedFeatureNodes.get(it));
  167. const char* const featureURI(lilvFeatureNode.as_uri());
  168. CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
  169. if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
  170. {
  171. info.hints |= CB::PLUGIN_IS_RTSAFE;
  172. }
  173. else if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0
  174. || std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0)
  175. {
  176. carla_stderr("LV2 plugin '%s' DSP wants UI feature '%s', ignoring this", info.label, featureURI);
  177. }
  178. }
  179. lilv_nodes_free(const_cast<LilvNodes*>(lilvSupportedFeatureNodes.me));
  180. }
  181. // ----------------------------------------------------------------------------------------------------------------
  182. // category
  183. info.category = CB::PLUGIN_CATEGORY_NONE;
  184. {
  185. Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
  186. if (typeNodes.size() > 0)
  187. {
  188. if (typeNodes.contains(lv2World.class_allpass))
  189. info.category = CB::PLUGIN_CATEGORY_FILTER;
  190. if (typeNodes.contains(lv2World.class_amplifier))
  191. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  192. if (typeNodes.contains(lv2World.class_analyzer))
  193. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  194. if (typeNodes.contains(lv2World.class_bandpass))
  195. info.category = CB::PLUGIN_CATEGORY_FILTER;
  196. if (typeNodes.contains(lv2World.class_chorus))
  197. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  198. if (typeNodes.contains(lv2World.class_comb))
  199. info.category = CB::PLUGIN_CATEGORY_FILTER;
  200. if (typeNodes.contains(lv2World.class_compressor))
  201. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  202. if (typeNodes.contains(lv2World.class_constant))
  203. info.category = CB::PLUGIN_CATEGORY_OTHER;
  204. if (typeNodes.contains(lv2World.class_converter))
  205. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  206. if (typeNodes.contains(lv2World.class_delay))
  207. info.category = CB::PLUGIN_CATEGORY_DELAY;
  208. if (typeNodes.contains(lv2World.class_distortion))
  209. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  210. if (typeNodes.contains(lv2World.class_dynamics))
  211. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  212. if (typeNodes.contains(lv2World.class_eq))
  213. info.category = CB::PLUGIN_CATEGORY_EQ;
  214. if (typeNodes.contains(lv2World.class_envelope))
  215. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  216. if (typeNodes.contains(lv2World.class_expander))
  217. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  218. if (typeNodes.contains(lv2World.class_filter))
  219. info.category = CB::PLUGIN_CATEGORY_FILTER;
  220. if (typeNodes.contains(lv2World.class_flanger))
  221. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  222. if (typeNodes.contains(lv2World.class_function))
  223. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  224. if (typeNodes.contains(lv2World.class_gate))
  225. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  226. if (typeNodes.contains(lv2World.class_generator))
  227. info.category = CB::PLUGIN_CATEGORY_OTHER;
  228. if (typeNodes.contains(lv2World.class_highpass))
  229. info.category = CB::PLUGIN_CATEGORY_FILTER;
  230. if (typeNodes.contains(lv2World.class_limiter))
  231. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  232. if (typeNodes.contains(lv2World.class_lowpass))
  233. info.category = CB::PLUGIN_CATEGORY_FILTER;
  234. if (typeNodes.contains(lv2World.class_mixer))
  235. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  236. if (typeNodes.contains(lv2World.class_modulator))
  237. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  238. if (typeNodes.contains(lv2World.class_multiEQ))
  239. info.category = CB::PLUGIN_CATEGORY_EQ;
  240. if (typeNodes.contains(lv2World.class_oscillator))
  241. info.category = CB::PLUGIN_CATEGORY_OTHER;
  242. if (typeNodes.contains(lv2World.class_paraEQ))
  243. info.category = CB::PLUGIN_CATEGORY_EQ;
  244. if (typeNodes.contains(lv2World.class_phaser))
  245. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  246. if (typeNodes.contains(lv2World.class_pitch))
  247. info.category = CB::PLUGIN_CATEGORY_OTHER;
  248. if (typeNodes.contains(lv2World.class_reverb))
  249. info.category = CB::PLUGIN_CATEGORY_DELAY;
  250. if (typeNodes.contains(lv2World.class_simulator))
  251. info.category = CB::PLUGIN_CATEGORY_OTHER;
  252. if (typeNodes.contains(lv2World.class_spatial))
  253. info.category = CB::PLUGIN_CATEGORY_OTHER;
  254. if (typeNodes.contains(lv2World.class_spectral))
  255. info.category = CB::PLUGIN_CATEGORY_OTHER;
  256. if (typeNodes.contains(lv2World.class_utility))
  257. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  258. if (typeNodes.contains(lv2World.class_waveshaper))
  259. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  260. if (typeNodes.contains(lv2World.class_instrument))
  261. {
  262. info.category = CB::PLUGIN_CATEGORY_SYNTH;
  263. info.hints |= CB::PLUGIN_IS_SYNTH;
  264. }
  265. }
  266. lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
  267. }
  268. // ----------------------------------------------------------------------------------------------------------------
  269. // number data
  270. info.audioIns = 0;
  271. info.audioOuts = 0;
  272. info.midiIns = 0;
  273. info.midiOuts = 0;
  274. info.parameterIns = 0;
  275. info.parameterOuts = 0;
  276. for (uint i=0, count=lilvPlugin.get_num_ports(); i<count; ++i)
  277. {
  278. Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
  279. bool isInput;
  280. /**/ if (lilvPort.is_a(lv2World.port_input))
  281. {
  282. isInput = true;
  283. }
  284. else if (lilvPort.is_a(lv2World.port_output))
  285. {
  286. isInput = false;
  287. }
  288. else
  289. {
  290. const LilvNode* const symbolNode = lilvPort.get_symbol();
  291. CARLA_SAFE_ASSERT_CONTINUE(symbolNode != nullptr && lilv_node_is_string(symbolNode));
  292. const char* const symbol = lilv_node_as_string(symbolNode);
  293. CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr);
  294. carla_stderr("LV2 plugin '%s' port '%s' is neither input or output", info.label, symbol);
  295. continue;
  296. }
  297. /**/ if (lilvPort.is_a(lv2World.port_control))
  298. {
  299. // skip some control ports
  300. if (lilvPort.has_property(lv2World.reportsLatency))
  301. continue;
  302. if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
  303. {
  304. bool skip = false;
  305. if (const char* const designation = lilv_node_as_string(designationNode))
  306. {
  307. /**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
  308. skip = true;
  309. else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
  310. skip = true;
  311. else if (std::strcmp(designation, LV2_CORE__latency) == 0)
  312. skip = true;
  313. else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
  314. skip = true;
  315. else if (std::strcmp(designation, LV2_TIME__bar) == 0)
  316. skip = true;
  317. else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
  318. skip = true;
  319. else if (std::strcmp(designation, LV2_TIME__beat) == 0)
  320. skip = true;
  321. else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
  322. skip = true;
  323. else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
  324. skip = true;
  325. else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
  326. skip = true;
  327. else if (std::strcmp(designation, LV2_TIME__frame) == 0)
  328. skip = true;
  329. else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
  330. skip = true;
  331. else if (std::strcmp(designation, LV2_TIME__speed) == 0)
  332. skip = true;
  333. else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  334. skip = true;
  335. }
  336. lilv_node_free(designationNode);
  337. if (skip)
  338. continue;
  339. }
  340. if (isInput)
  341. ++(info.parameterIns);
  342. else
  343. ++(info.parameterOuts);
  344. }
  345. else if (lilvPort.is_a(lv2World.port_audio))
  346. {
  347. if (isInput)
  348. ++(info.audioIns);
  349. else
  350. ++(info.audioOuts);
  351. }
  352. else if (lilvPort.is_a(lv2World.port_cv))
  353. {
  354. }
  355. else if (lilvPort.is_a(lv2World.port_atom))
  356. {
  357. Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));
  358. for (LilvIter *it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
  359. {
  360. const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
  361. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  362. if (node.equals(lv2World.midi_event))
  363. {
  364. if (isInput)
  365. ++(info.midiIns);
  366. else
  367. ++(info.midiOuts);
  368. }
  369. }
  370. lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
  371. }
  372. else if (lilvPort.is_a(lv2World.port_event))
  373. {
  374. if (lilvPort.supports_event(lv2World.midi_event))
  375. {
  376. if (isInput)
  377. ++(info.midiIns);
  378. else
  379. ++(info.midiOuts);
  380. }
  381. }
  382. else if (lilvPort.is_a(lv2World.port_midi))
  383. {
  384. if (isInput)
  385. ++(info.midiIns);
  386. else
  387. ++(info.midiOuts);
  388. }
  389. else
  390. {
  391. const LilvNode* const symbolNode = lilvPort.get_symbol();
  392. CARLA_SAFE_ASSERT_CONTINUE(symbolNode != nullptr && lilv_node_is_string(symbolNode));
  393. const char* const symbol = lilv_node_as_string(symbolNode);
  394. CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr);
  395. supported = false;
  396. carla_stderr("LV2 plugin '%s' port '%s' is required but has unsupported type", info.label, symbol);
  397. }
  398. }
  399. if (supported)
  400. info.valid = true;
  401. return &info;
  402. }
  403. const CarlaCachedPluginInfo* get_cached_plugin_sfz(const File file)
  404. {
  405. static CarlaCachedPluginInfo info;
  406. static CarlaString name, filename;
  407. name = file.getFileNameWithoutExtension().toRawUTF8();
  408. name.replace('_',' ');
  409. filename = file.getFullPathName().toRawUTF8();
  410. info.category = CB::PLUGIN_CATEGORY_SYNTH;
  411. info.hints = CB::PLUGIN_IS_SYNTH;
  412. // CB::PLUGIN_IS_RTSAFE
  413. info.valid = true;
  414. info.audioIns = 0;
  415. info.audioOuts = 2;
  416. info.midiIns = 1;
  417. info.midiOuts = 0;
  418. info.parameterIns = 0;
  419. info.parameterOuts = 1;
  420. info.name = name.buffer();
  421. info.label = filename.buffer();
  422. info.maker = gNullCharPtr;
  423. info.copyright = gNullCharPtr;
  424. return &info;
  425. }
  426. // -------------------------------------------------------------------------------------------------------------------
  427. uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath)
  428. {
  429. CARLA_SAFE_ASSERT_RETURN(isCachedPluginType(ptype), 0);
  430. carla_debug("carla_get_cached_plugin_count(%i:%s, %s)", ptype, CB::PluginType2Str(ptype), pluginPath);
  431. switch (ptype)
  432. {
  433. case CB::PLUGIN_INTERNAL: {
  434. uint32_t count = 0;
  435. carla_get_native_plugins_data(&count);
  436. return count;
  437. }
  438. case CB::PLUGIN_LV2: {
  439. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  440. lv2World.initIfNeeded(pluginPath);
  441. return lv2World.getPluginCount();
  442. }
  443. case CB::PLUGIN_SFZ: {
  444. findSFZs(pluginPath);
  445. return gSFZs.size();
  446. }
  447. default:
  448. return 0;
  449. }
  450. }
  451. const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index)
  452. {
  453. carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);
  454. switch (ptype)
  455. {
  456. case CB::PLUGIN_INTERNAL: {
  457. uint32_t count = 0;
  458. const NativePluginDescriptor* const descs(carla_get_native_plugins_data(&count));
  459. CARLA_SAFE_ASSERT_BREAK(index < count);
  460. CARLA_SAFE_ASSERT_BREAK(descs != nullptr);
  461. const NativePluginDescriptor& desc(descs[index]);
  462. return get_cached_plugin_internal(desc);
  463. }
  464. case CB::PLUGIN_LV2: {
  465. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  466. const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
  467. CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
  468. Lilv::Plugin lilvPlugin(cPlugin);
  469. CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
  470. return get_cached_plugin_lv2(lv2World, lilvPlugin);
  471. }
  472. case CB::PLUGIN_SFZ: {
  473. CARLA_SAFE_ASSERT_BREAK(index < static_cast<uint>(gSFZs.size()));
  474. return get_cached_plugin_sfz(gSFZs.getUnchecked(index));
  475. }
  476. default:
  477. break;
  478. }
  479. static CarlaCachedPluginInfo info;
  480. return &info;
  481. }
  482. // -------------------------------------------------------------------------------------------------------------------
  483. #include "../native-plugins/_data.cpp"
  484. // -------------------------------------------------------------------------------------------------------------------