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.

433 lines
17KB

  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. namespace CB = CarlaBackend;
  22. static const char* const gNullCharPtr = "";
  23. static bool isCachedPluginType(const CB::PluginType ptype)
  24. {
  25. switch (ptype)
  26. {
  27. case CB::PLUGIN_INTERNAL:
  28. case CB::PLUGIN_LV2:
  29. return false;
  30. default:
  31. return true;
  32. }
  33. }
  34. // -------------------------------------------------------------------------------------------------------------------
  35. _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
  36. : valid(false),
  37. category(CB::PLUGIN_CATEGORY_NONE),
  38. hints(0x0),
  39. audioIns(0),
  40. audioOuts(0),
  41. midiIns(0),
  42. midiOuts(0),
  43. parameterIns(0),
  44. parameterOuts(0),
  45. name(gNullCharPtr),
  46. label(gNullCharPtr),
  47. maker(gNullCharPtr),
  48. copyright(gNullCharPtr) {}
  49. // -------------------------------------------------------------------------------------------------------------------
  50. uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath)
  51. {
  52. CARLA_SAFE_ASSERT_RETURN(isCachedPluginType(ptype), 0);
  53. carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));
  54. switch (ptype)
  55. {
  56. case CB::PLUGIN_INTERNAL: {
  57. uint32_t count = 0;
  58. carla_get_native_plugins_data(&count);
  59. return count;
  60. }
  61. case CB::PLUGIN_LV2: {
  62. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  63. lv2World.initIfNeeded(pluginPath);
  64. return lv2World.getPluginCount();
  65. }
  66. default:
  67. return 0;
  68. }
  69. }
  70. const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index)
  71. {
  72. carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);
  73. static CarlaCachedPluginInfo info;
  74. switch (ptype)
  75. {
  76. case CB::PLUGIN_INTERNAL: {
  77. uint32_t count = 0;
  78. const NativePluginDescriptor* const descs(carla_get_native_plugins_data(&count));
  79. CARLA_SAFE_ASSERT_BREAK(index < count);
  80. CARLA_SAFE_ASSERT_BREAK(descs != nullptr);
  81. const NativePluginDescriptor& desc(descs[index]);
  82. info.category = static_cast<CB::PluginCategory>(desc.category);
  83. info.hints = 0x0;
  84. if (desc.hints & NATIVE_PLUGIN_IS_RTSAFE)
  85. info.hints |= CB::PLUGIN_IS_RTSAFE;
  86. if (desc.hints & NATIVE_PLUGIN_IS_SYNTH)
  87. info.hints |= CB::PLUGIN_IS_SYNTH;
  88. if (desc.hints & NATIVE_PLUGIN_HAS_UI)
  89. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  90. if (desc.hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
  91. info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
  92. if (desc.hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD)
  93. info.hints |= CB::PLUGIN_NEEDS_UI_MAIN_THREAD;
  94. if (desc.hints & NATIVE_PLUGIN_USES_MULTI_PROGS)
  95. info.hints |= CB::PLUGIN_USES_MULTI_PROGS;
  96. info.valid = true;
  97. info.audioIns = desc.audioIns;
  98. info.audioOuts = desc.audioOuts;
  99. info.midiIns = desc.midiIns;
  100. info.midiOuts = desc.midiOuts;
  101. info.parameterIns = desc.paramIns;
  102. info.parameterOuts = desc.paramOuts;
  103. info.name = desc.name;
  104. info.label = desc.label;
  105. info.maker = desc.maker;
  106. info.copyright = desc.copyright;
  107. return &info;
  108. }
  109. case CB::PLUGIN_LV2: {
  110. Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
  111. const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
  112. CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
  113. Lilv::Plugin lilvPlugin(cPlugin);
  114. CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
  115. // features
  116. info.hints = 0x0;
  117. if (lilvPlugin.get_uis().size() > 0)
  118. info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
  119. {
  120. Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
  121. LILV_FOREACH(nodes, it, lilvFeatureNodes)
  122. {
  123. Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
  124. const char* const featureURI(lilvFeatureNode.as_uri());
  125. CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
  126. if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
  127. info.hints |= CB::PLUGIN_IS_RTSAFE;
  128. }
  129. lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
  130. }
  131. // category
  132. info.category = CB::PLUGIN_CATEGORY_NONE;
  133. {
  134. Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
  135. if (typeNodes.size() > 0)
  136. {
  137. if (typeNodes.contains(lv2World.class_allpass))
  138. info.category = CB::PLUGIN_CATEGORY_FILTER;
  139. if (typeNodes.contains(lv2World.class_amplifier))
  140. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  141. if (typeNodes.contains(lv2World.class_analyzer))
  142. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  143. if (typeNodes.contains(lv2World.class_bandpass))
  144. info.category = CB::PLUGIN_CATEGORY_FILTER;
  145. if (typeNodes.contains(lv2World.class_chorus))
  146. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  147. if (typeNodes.contains(lv2World.class_comb))
  148. info.category = CB::PLUGIN_CATEGORY_FILTER;
  149. if (typeNodes.contains(lv2World.class_compressor))
  150. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  151. if (typeNodes.contains(lv2World.class_constant))
  152. info.category = CB::PLUGIN_CATEGORY_OTHER;
  153. if (typeNodes.contains(lv2World.class_converter))
  154. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  155. if (typeNodes.contains(lv2World.class_delay))
  156. info.category = CB::PLUGIN_CATEGORY_DELAY;
  157. if (typeNodes.contains(lv2World.class_distortion))
  158. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  159. if (typeNodes.contains(lv2World.class_dynamics))
  160. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  161. if (typeNodes.contains(lv2World.class_eq))
  162. info.category = CB::PLUGIN_CATEGORY_EQ;
  163. if (typeNodes.contains(lv2World.class_envelope))
  164. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  165. if (typeNodes.contains(lv2World.class_expander))
  166. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  167. if (typeNodes.contains(lv2World.class_filter))
  168. info.category = CB::PLUGIN_CATEGORY_FILTER;
  169. if (typeNodes.contains(lv2World.class_flanger))
  170. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  171. if (typeNodes.contains(lv2World.class_function))
  172. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  173. if (typeNodes.contains(lv2World.class_gate))
  174. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  175. if (typeNodes.contains(lv2World.class_generator))
  176. info.category = CB::PLUGIN_CATEGORY_OTHER;
  177. if (typeNodes.contains(lv2World.class_highpass))
  178. info.category = CB::PLUGIN_CATEGORY_FILTER;
  179. if (typeNodes.contains(lv2World.class_limiter))
  180. info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
  181. if (typeNodes.contains(lv2World.class_lowpass))
  182. info.category = CB::PLUGIN_CATEGORY_FILTER;
  183. if (typeNodes.contains(lv2World.class_mixer))
  184. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  185. if (typeNodes.contains(lv2World.class_modulator))
  186. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  187. if (typeNodes.contains(lv2World.class_multiEQ))
  188. info.category = CB::PLUGIN_CATEGORY_EQ;
  189. if (typeNodes.contains(lv2World.class_oscillator))
  190. info.category = CB::PLUGIN_CATEGORY_OTHER;
  191. if (typeNodes.contains(lv2World.class_paraEQ))
  192. info.category = CB::PLUGIN_CATEGORY_EQ;
  193. if (typeNodes.contains(lv2World.class_phaser))
  194. info.category = CB::PLUGIN_CATEGORY_MODULATOR;
  195. if (typeNodes.contains(lv2World.class_pitch))
  196. info.category = CB::PLUGIN_CATEGORY_OTHER;
  197. if (typeNodes.contains(lv2World.class_reverb))
  198. info.category = CB::PLUGIN_CATEGORY_DELAY;
  199. if (typeNodes.contains(lv2World.class_simulator))
  200. info.category = CB::PLUGIN_CATEGORY_OTHER;
  201. if (typeNodes.contains(lv2World.class_spatial))
  202. info.category = CB::PLUGIN_CATEGORY_OTHER;
  203. if (typeNodes.contains(lv2World.class_spectral))
  204. info.category = CB::PLUGIN_CATEGORY_OTHER;
  205. if (typeNodes.contains(lv2World.class_utility))
  206. info.category = CB::PLUGIN_CATEGORY_UTILITY;
  207. if (typeNodes.contains(lv2World.class_waveshaper))
  208. info.category = CB::PLUGIN_CATEGORY_DISTORTION;
  209. if (typeNodes.contains(lv2World.class_instrument))
  210. {
  211. info.category = CB::PLUGIN_CATEGORY_SYNTH;
  212. info.hints |= CB::PLUGIN_IS_SYNTH;
  213. }
  214. }
  215. lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
  216. }
  217. // number data
  218. info.audioIns = 0;
  219. info.audioOuts = 0;
  220. info.midiIns = 0;
  221. info.midiOuts = 0;
  222. info.parameterIns = 0;
  223. info.parameterOuts = 0;
  224. for (uint i=0, count=lilvPlugin.get_num_ports(); i<count; ++i)
  225. {
  226. Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
  227. bool isInput;
  228. /**/ if (lilvPort.is_a(lv2World.port_input))
  229. isInput = true;
  230. else if (lilvPort.is_a(lv2World.port_output))
  231. isInput = false;
  232. else
  233. continue;
  234. /**/ if (lilvPort.is_a(lv2World.port_control))
  235. {
  236. // skip some control ports
  237. if (lilvPort.has_property(lv2World.reportsLatency))
  238. continue;
  239. if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
  240. {
  241. bool skip = false;
  242. if (const char* const designation = lilv_node_as_string(designationNode))
  243. {
  244. /**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
  245. skip = true;
  246. else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
  247. skip = true;
  248. else if (std::strcmp(designation, LV2_CORE__latency) == 0)
  249. skip = true;
  250. else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
  251. skip = true;
  252. else if (std::strcmp(designation, LV2_TIME__bar) == 0)
  253. skip = true;
  254. else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
  255. skip = true;
  256. else if (std::strcmp(designation, LV2_TIME__beat) == 0)
  257. skip = true;
  258. else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
  259. skip = true;
  260. else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
  261. skip = true;
  262. else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
  263. skip = true;
  264. else if (std::strcmp(designation, LV2_TIME__frame) == 0)
  265. skip = true;
  266. else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
  267. skip = true;
  268. else if (std::strcmp(designation, LV2_TIME__speed) == 0)
  269. skip = true;
  270. else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
  271. skip = true;
  272. }
  273. lilv_node_free(designationNode);
  274. if (skip)
  275. continue;
  276. }
  277. if (isInput)
  278. ++(info.parameterIns);
  279. else
  280. ++(info.parameterOuts);
  281. }
  282. else if (lilvPort.is_a(lv2World.port_audio))
  283. {
  284. if (isInput)
  285. ++(info.audioIns);
  286. else
  287. ++(info.audioOuts);
  288. }
  289. else if (lilvPort.is_a(lv2World.port_cv))
  290. {
  291. }
  292. else if (lilvPort.is_a(lv2World.port_atom))
  293. {
  294. Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));
  295. for (LilvIter *it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
  296. {
  297. const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
  298. CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());
  299. if (node.equals(lv2World.midi_event))
  300. {
  301. if (isInput)
  302. ++(info.midiIns);
  303. else
  304. ++(info.midiOuts);
  305. }
  306. }
  307. lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
  308. }
  309. else if (lilvPort.is_a(lv2World.port_event))
  310. {
  311. if (lilvPort.supports_event(lv2World.midi_event))
  312. {
  313. if (isInput)
  314. ++(info.midiIns);
  315. else
  316. ++(info.midiOuts);
  317. }
  318. }
  319. else if (lilvPort.is_a(lv2World.port_midi))
  320. {
  321. if (isInput)
  322. ++(info.midiIns);
  323. else
  324. ++(info.midiOuts);
  325. }
  326. }
  327. // text data
  328. static CarlaString suri, sname, smaker, slicense;
  329. suri.clear(); sname.clear(); smaker.clear(); slicense.clear();
  330. suri = lilvPlugin.get_uri().as_uri();
  331. if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
  332. {
  333. if (const char* const name = lilv_node_as_string(nameNode))
  334. sname = name;
  335. lilv_node_free(nameNode);
  336. }
  337. if (const char* const author = lilvPlugin.get_author_name().as_string())
  338. smaker = author;
  339. Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
  340. if (licenseNodes.size() > 0)
  341. {
  342. if (const char* const license = licenseNodes.get_first().as_string())
  343. slicense = license;
  344. }
  345. lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
  346. info.valid = true;
  347. info.name = sname;
  348. info.label = suri;
  349. info.maker = smaker;
  350. info.copyright = slicense;
  351. return &info;
  352. }
  353. default:
  354. break;
  355. }
  356. info.valid = true;
  357. info.category = CB::PLUGIN_CATEGORY_NONE;
  358. info.hints = 0x0;
  359. info.audioIns = 0;
  360. info.audioOuts = 0;
  361. info.midiIns = 0;
  362. info.midiOuts = 0;
  363. info.parameterIns = 0;
  364. info.parameterOuts = 0;
  365. info.name = gNullCharPtr;
  366. info.label = gNullCharPtr;
  367. info.maker = gNullCharPtr;
  368. info.copyright = gNullCharPtr;
  369. return &info;
  370. }
  371. // -------------------------------------------------------------------------------------------------------------------
  372. #include "../native-plugins/_data.all.cpp"
  373. // -------------------------------------------------------------------------------------------------------------------