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.

437 lines
14KB

  1. /*
  2. * DISTRHO Cardinal Plugin
  3. * Copyright (C) 2021-2022 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 3 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 LICENSE file.
  16. */
  17. #include "rack.hpp"
  18. #include "plugin.hpp"
  19. #include "DistrhoUtils.hpp"
  20. // Cardinal (built-in)
  21. #include "Cardinal/src/plugin.hpp"
  22. // Fundamental
  23. #include "Fundamental/src/plugin.hpp"
  24. // AudibleInstruments
  25. #include "AudibleInstruments/src/plugin.hpp"
  26. // BogaudioModules - integrate theme/skin support
  27. #include <mutex>
  28. #include <string>
  29. #include <unordered_map>
  30. #include <unordered_set>
  31. #include <vector>
  32. #define private public
  33. #include "BogaudioModules/src/skins.hpp"
  34. #undef private
  35. // BogaudioModules
  36. extern Model* modelBogaudioLFO;
  37. extern Model* modelBogaudioNoise;
  38. extern Model* modelBogaudioVCA;
  39. extern Model* modelBogaudioVCF;
  40. extern Model* modelBogaudioVCO;
  41. // known terminal modules
  42. std::vector<Model*> hostTerminalModels;
  43. // plugin instances
  44. Plugin* pluginInstance__Cardinal;
  45. Plugin* pluginInstance__Fundamental;
  46. Plugin* pluginInstance__AudibleInstruments;
  47. Plugin* pluginInstance__BogaudioModules;
  48. namespace rack {
  49. namespace asset {
  50. std::string pluginManifest(const std::string& dirname);
  51. std::string pluginPath(const std::string& dirname);
  52. }
  53. namespace plugin {
  54. struct StaticPluginLoader {
  55. Plugin* const plugin;
  56. FILE* file;
  57. json_t* rootJ;
  58. StaticPluginLoader(Plugin* const p, const char* const name)
  59. : plugin(p),
  60. file(nullptr),
  61. rootJ(nullptr)
  62. {
  63. #ifdef DEBUG
  64. DEBUG("Loading plugin module %s", name);
  65. #endif
  66. p->path = asset::pluginPath(name);
  67. const std::string manifestFilename = asset::pluginManifest(name);
  68. if ((file = std::fopen(manifestFilename.c_str(), "r")) == nullptr)
  69. {
  70. d_stderr2("Manifest file %s does not exist", manifestFilename.c_str());
  71. return;
  72. }
  73. json_error_t error;
  74. if ((rootJ = json_loadf(file, 0, &error)) == nullptr)
  75. {
  76. d_stderr2("JSON parsing error at %s %d:%d %s", manifestFilename.c_str(), error.line, error.column, error.text);
  77. return;
  78. }
  79. // force ABI, we use static plugins so this doesnt matter as long as it builds
  80. json_t* const version = json_string((APP_VERSION_MAJOR + ".0").c_str());
  81. json_object_set(rootJ, "version", version);
  82. json_decref(version);
  83. // Load manifest
  84. p->fromJson(rootJ);
  85. // Reject plugin if slug already exists
  86. if (Plugin* const existingPlugin = getPlugin(p->slug))
  87. throw Exception("Plugin %s is already loaded, not attempting to load it again", p->slug.c_str());
  88. }
  89. ~StaticPluginLoader()
  90. {
  91. if (rootJ != nullptr)
  92. {
  93. // Load modules manifest
  94. json_t* const modulesJ = json_object_get(rootJ, "modules");
  95. plugin->modulesFromJson(modulesJ);
  96. json_decref(rootJ);
  97. plugins.push_back(plugin);
  98. }
  99. if (file != nullptr)
  100. std::fclose(file);
  101. }
  102. bool ok() const noexcept
  103. {
  104. return rootJ != nullptr;
  105. }
  106. void removeModule(const char* const slugToRemove) const noexcept
  107. {
  108. json_t* const modules = json_object_get(rootJ, "modules");
  109. DISTRHO_SAFE_ASSERT_RETURN(modules != nullptr,);
  110. size_t i;
  111. json_t* v;
  112. json_array_foreach(modules, i, v)
  113. {
  114. if (json_t* const slug = json_object_get(v, "slug"))
  115. {
  116. if (const char* const value = json_string_value(slug))
  117. {
  118. if (std::strcmp(value, slugToRemove) == 0)
  119. {
  120. json_array_remove(modules, i);
  121. break;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. };
  128. static void initStatic__Cardinal()
  129. {
  130. Plugin* const p = new Plugin;
  131. pluginInstance__Cardinal = p;
  132. const StaticPluginLoader spl(p, "Cardinal");
  133. if (spl.ok())
  134. {
  135. p->addModel(modelHostAudio2);
  136. p->addModel(modelHostCV);
  137. p->addModel(modelHostMIDI);
  138. p->addModel(modelHostMIDICC);
  139. p->addModel(modelHostMIDIGate);
  140. p->addModel(modelHostMIDIMap);
  141. p->addModel(modelHostParameters);
  142. p->addModel(modelHostParametersMap);
  143. p->addModel(modelHostTime);
  144. p->addModel(modelTextEditor);
  145. /* TODO
  146. #ifdef HAVE_FFTW3F
  147. p->addModel(modelAudioToCVPitch);
  148. #else
  149. */
  150. spl.removeModule("AudioToCVPitch");
  151. /*
  152. #endif
  153. */
  154. spl.removeModule("AudioFile");
  155. spl.removeModule("Blank");
  156. spl.removeModule("Carla");
  157. spl.removeModule("ExpanderInputMIDI");
  158. spl.removeModule("ExpanderOutputMIDI");
  159. spl.removeModule("HostAudio8");
  160. spl.removeModule("Ildaeil");
  161. spl.removeModule("MPV");
  162. spl.removeModule("SassyScope");
  163. spl.removeModule("glBars");
  164. hostTerminalModels = {
  165. modelHostAudio2,
  166. modelHostCV,
  167. modelHostMIDI,
  168. modelHostMIDICC,
  169. modelHostMIDIGate,
  170. modelHostMIDIMap,
  171. modelHostParameters,
  172. modelHostParametersMap,
  173. modelHostTime,
  174. };
  175. }
  176. }
  177. static void initStatic__Fundamental()
  178. {
  179. Plugin* const p = new Plugin;
  180. pluginInstance__Fundamental = p;
  181. const StaticPluginLoader spl(p, "Fundamental");
  182. if (spl.ok())
  183. {
  184. p->addModel(modelADSR);
  185. p->addModel(modelLFO);
  186. p->addModel(modelNoise);
  187. p->addModel(modelRandom);
  188. p->addModel(modelScope);
  189. p->addModel(modelVCA_1);
  190. p->addModel(modelVCF);
  191. p->addModel(modelVCMixer);
  192. p->addModel(modelVCO);
  193. spl.removeModule("8vert");
  194. spl.removeModule("Delay");
  195. spl.removeModule("LFO2");
  196. spl.removeModule("Merge");
  197. spl.removeModule("MidSide");
  198. spl.removeModule("Mixer");
  199. spl.removeModule("Mutes");
  200. spl.removeModule("Octave");
  201. spl.removeModule("Pulses");
  202. spl.removeModule("Quantizer");
  203. spl.removeModule("SEQ3");
  204. spl.removeModule("SequentialSwitch1");
  205. spl.removeModule("SequentialSwitch2");
  206. spl.removeModule("Split");
  207. spl.removeModule("Sum");
  208. spl.removeModule("VCA");
  209. spl.removeModule("VCO2");
  210. }
  211. }
  212. static void initStatic__AudibleInstruments()
  213. {
  214. Plugin* const p = new Plugin;
  215. pluginInstance__AudibleInstruments = p;
  216. const StaticPluginLoader spl(p, "AudibleInstruments");
  217. if (spl.ok())
  218. {
  219. p->addModel(modelPlaits);
  220. spl.removeModule("Blinds");
  221. spl.removeModule("Braids");
  222. spl.removeModule("Branches");
  223. spl.removeModule("Clouds");
  224. spl.removeModule("Elements");
  225. spl.removeModule("Frames");
  226. spl.removeModule("Kinks");
  227. spl.removeModule("Links");
  228. spl.removeModule("Marbles");
  229. spl.removeModule("Rings");
  230. spl.removeModule("Ripples");
  231. spl.removeModule("Shades");
  232. spl.removeModule("Shelves");
  233. spl.removeModule("Stages");
  234. spl.removeModule("Streams");
  235. spl.removeModule("Tides");
  236. spl.removeModule("Tides2");
  237. spl.removeModule("Veils");
  238. spl.removeModule("Warps");
  239. }
  240. }
  241. static void initStatic__BogaudioModules()
  242. {
  243. Plugin* const p = new Plugin;
  244. pluginInstance__BogaudioModules = p;
  245. const StaticPluginLoader spl(p, "BogaudioModules");
  246. if (spl.ok())
  247. {
  248. // Make sure to use match Cardinal theme
  249. Skins& skins(Skins::skins());
  250. skins._default = settings::darkMode ? "dark" : "light";
  251. p->addModel(modelBogaudioLFO);
  252. p->addModel(modelBogaudioNoise);
  253. p->addModel(modelBogaudioVCA);
  254. p->addModel(modelBogaudioVCF);
  255. p->addModel(modelBogaudioVCO);
  256. // cat plugins/BogaudioModules/plugin.json | jq -r .modules[].slug - | sort
  257. spl.removeModule("Bogaudio-AD");
  258. spl.removeModule("Bogaudio-Additator");
  259. spl.removeModule("Bogaudio-AddrSeq");
  260. spl.removeModule("Bogaudio-AddrSeqX");
  261. spl.removeModule("Bogaudio-ADSR");
  262. spl.removeModule("Bogaudio-AMRM");
  263. spl.removeModule("Bogaudio-Analyzer");
  264. spl.removeModule("Bogaudio-AnalyzerXL");
  265. spl.removeModule("Bogaudio-Arp");
  266. spl.removeModule("Bogaudio-ASR");
  267. spl.removeModule("Bogaudio-Assign");
  268. spl.removeModule("Bogaudio-Blank3");
  269. spl.removeModule("Bogaudio-Blank6");
  270. spl.removeModule("Bogaudio-Bool");
  271. spl.removeModule("Bogaudio-Chirp");
  272. spl.removeModule("Bogaudio-Clpr");
  273. spl.removeModule("Bogaudio-Cmp");
  274. spl.removeModule("Bogaudio-CmpDist");
  275. spl.removeModule("Bogaudio-CVD");
  276. spl.removeModule("Bogaudio-DADSRH");
  277. spl.removeModule("Bogaudio-DADSRHPlus");
  278. spl.removeModule("Bogaudio-Detune");
  279. spl.removeModule("Bogaudio-DGate");
  280. spl.removeModule("Bogaudio-Edge");
  281. spl.removeModule("Bogaudio-EightFO");
  282. spl.removeModule("Bogaudio-EightOne");
  283. spl.removeModule("Bogaudio-EQ");
  284. spl.removeModule("Bogaudio-EQS");
  285. spl.removeModule("Bogaudio-FFB");
  286. spl.removeModule("Bogaudio-FlipFlop");
  287. spl.removeModule("Bogaudio-FMOp");
  288. spl.removeModule("Bogaudio-Follow");
  289. spl.removeModule("Bogaudio-FourFO");
  290. spl.removeModule("Bogaudio-FourMan");
  291. spl.removeModule("Bogaudio-Inv");
  292. spl.removeModule("Bogaudio-Lgsw");
  293. spl.removeModule("Bogaudio-LLFO");
  294. spl.removeModule("Bogaudio-LLPG");
  295. spl.removeModule("Bogaudio-Lmtr");
  296. spl.removeModule("Bogaudio-LPG");
  297. spl.removeModule("Bogaudio-LVCF");
  298. spl.removeModule("Bogaudio-LVCO");
  299. spl.removeModule("Bogaudio-Manual");
  300. spl.removeModule("Bogaudio-Matrix18");
  301. spl.removeModule("Bogaudio-Matrix44");
  302. spl.removeModule("Bogaudio-Matrix44Cvm");
  303. spl.removeModule("Bogaudio-Matrix81");
  304. spl.removeModule("Bogaudio-Matrix88");
  305. spl.removeModule("Bogaudio-Matrix88Cv");
  306. spl.removeModule("Bogaudio-Matrix88M");
  307. spl.removeModule("Bogaudio-MegaGate");
  308. spl.removeModule("Bogaudio-Mix1");
  309. spl.removeModule("Bogaudio-Mix2");
  310. spl.removeModule("Bogaudio-Mix4");
  311. spl.removeModule("Bogaudio-Mix4x");
  312. spl.removeModule("Bogaudio-Mix8");
  313. spl.removeModule("Bogaudio-Mix8x");
  314. spl.removeModule("Bogaudio-Mono");
  315. spl.removeModule("Bogaudio-Mult");
  316. spl.removeModule("Bogaudio-Mumix");
  317. spl.removeModule("Bogaudio-Mute8");
  318. spl.removeModule("Bogaudio-Nsgt");
  319. spl.removeModule("Bogaudio-Offset");
  320. spl.removeModule("Bogaudio-OneEight");
  321. spl.removeModule("Bogaudio-Pan");
  322. spl.removeModule("Bogaudio-PEQ");
  323. spl.removeModule("Bogaudio-PEQ14");
  324. spl.removeModule("Bogaudio-PEQ14XF");
  325. spl.removeModule("Bogaudio-PEQ6");
  326. spl.removeModule("Bogaudio-PEQ6XF");
  327. spl.removeModule("Bogaudio-Pgmr");
  328. spl.removeModule("Bogaudio-PgmrX");
  329. spl.removeModule("Bogaudio-PolyCon");
  330. spl.removeModule("Bogaudio-PolyCon8");
  331. spl.removeModule("Bogaudio-PolyMult");
  332. spl.removeModule("Bogaudio-PolyOff16");
  333. spl.removeModule("Bogaudio-PolyOff8");
  334. spl.removeModule("Bogaudio-Pressor");
  335. spl.removeModule("Bogaudio-Pulse");
  336. spl.removeModule("Bogaudio-Ranalyzer");
  337. spl.removeModule("Bogaudio-Reftone");
  338. spl.removeModule("Bogaudio-RGate");
  339. spl.removeModule("Bogaudio-SampleHold");
  340. spl.removeModule("Bogaudio-Shaper");
  341. spl.removeModule("Bogaudio-ShaperPlus");
  342. spl.removeModule("Bogaudio-Sine");
  343. spl.removeModule("Bogaudio-Slew");
  344. spl.removeModule("Bogaudio-Stack");
  345. spl.removeModule("Bogaudio-Sums");
  346. spl.removeModule("Bogaudio-Switch");
  347. spl.removeModule("Bogaudio-Switch1616");
  348. spl.removeModule("Bogaudio-Switch18");
  349. spl.removeModule("Bogaudio-Switch44");
  350. spl.removeModule("Bogaudio-Switch81");
  351. spl.removeModule("Bogaudio-Switch88");
  352. spl.removeModule("Bogaudio-UMix");
  353. spl.removeModule("Bogaudio-Unison");
  354. spl.removeModule("Bogaudio-VCAmp");
  355. spl.removeModule("Bogaudio-VCM");
  356. spl.removeModule("Bogaudio-Velo");
  357. spl.removeModule("Bogaudio-Vish");
  358. spl.removeModule("Bogaudio-VU");
  359. spl.removeModule("Bogaudio-Walk");
  360. spl.removeModule("Bogaudio-Walk2");
  361. spl.removeModule("Bogaudio-XCO");
  362. spl.removeModule("Bogaudio-XFade");
  363. }
  364. }
  365. void initStaticPlugins()
  366. {
  367. initStatic__Cardinal();
  368. initStatic__Fundamental();
  369. initStatic__AudibleInstruments();
  370. initStatic__BogaudioModules();
  371. }
  372. void destroyStaticPlugins()
  373. {
  374. for (Plugin* p : plugins)
  375. delete p;
  376. plugins.clear();
  377. }
  378. void updateStaticPluginsDarkMode()
  379. {
  380. const bool darkMode = settings::darkMode;
  381. // bogaudio
  382. {
  383. Skins& skins(Skins::skins());
  384. skins._default = darkMode ? "dark" : "light";
  385. std::lock_guard<std::mutex> lock(skins._defaultSkinListenersLock);
  386. for (auto listener : skins._defaultSkinListeners) {
  387. listener->defaultSkinChanged(skins._default);
  388. }
  389. }
  390. }
  391. }
  392. }