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.

508 lines
15KB

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