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.

239 lines
6.4KB

  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. // known terminal modules
  25. std::vector<Model*> hostTerminalModels;
  26. // plugin instances
  27. Plugin* pluginInstance__Cardinal;
  28. Plugin* pluginInstance__Fundamental;
  29. namespace rack {
  30. namespace asset {
  31. std::string pluginManifest(const std::string& dirname);
  32. std::string pluginPath(const std::string& dirname);
  33. }
  34. namespace plugin {
  35. struct StaticPluginLoader {
  36. Plugin* const plugin;
  37. FILE* file;
  38. json_t* rootJ;
  39. StaticPluginLoader(Plugin* const p, const char* const name)
  40. : plugin(p),
  41. file(nullptr),
  42. rootJ(nullptr)
  43. {
  44. #ifdef DEBUG
  45. DEBUG("Loading plugin module %s", name);
  46. #endif
  47. p->path = asset::pluginPath(name);
  48. const std::string manifestFilename = asset::pluginManifest(name);
  49. if ((file = std::fopen(manifestFilename.c_str(), "r")) == nullptr)
  50. {
  51. d_stderr2("Manifest file %s does not exist", manifestFilename.c_str());
  52. return;
  53. }
  54. json_error_t error;
  55. if ((rootJ = json_loadf(file, 0, &error)) == nullptr)
  56. {
  57. d_stderr2("JSON parsing error at %s %d:%d %s", manifestFilename.c_str(), error.line, error.column, error.text);
  58. return;
  59. }
  60. // force ABI, we use static plugins so this doesnt matter as long as it builds
  61. json_t* const version = json_string((APP_VERSION_MAJOR + ".0").c_str());
  62. json_object_set(rootJ, "version", version);
  63. json_decref(version);
  64. // Load manifest
  65. p->fromJson(rootJ);
  66. // Reject plugin if slug already exists
  67. if (Plugin* const existingPlugin = getPlugin(p->slug))
  68. throw Exception("Plugin %s is already loaded, not attempting to load it again", p->slug.c_str());
  69. }
  70. ~StaticPluginLoader()
  71. {
  72. if (rootJ != nullptr)
  73. {
  74. // Load modules manifest
  75. json_t* const modulesJ = json_object_get(rootJ, "modules");
  76. plugin->modulesFromJson(modulesJ);
  77. json_decref(rootJ);
  78. plugins.push_back(plugin);
  79. }
  80. if (file != nullptr)
  81. std::fclose(file);
  82. }
  83. bool ok() const noexcept
  84. {
  85. return rootJ != nullptr;
  86. }
  87. void removeModule(const char* const slugToRemove) const noexcept
  88. {
  89. json_t* const modules = json_object_get(rootJ, "modules");
  90. DISTRHO_SAFE_ASSERT_RETURN(modules != nullptr,);
  91. size_t i;
  92. json_t* v;
  93. json_array_foreach(modules, i, v)
  94. {
  95. if (json_t* const slug = json_object_get(v, "slug"))
  96. {
  97. if (const char* const value = json_string_value(slug))
  98. {
  99. if (std::strcmp(value, slugToRemove) == 0)
  100. {
  101. json_array_remove(modules, i);
  102. break;
  103. }
  104. }
  105. }
  106. }
  107. }
  108. };
  109. static void initStatic__Cardinal()
  110. {
  111. Plugin* const p = new Plugin;
  112. pluginInstance__Cardinal = p;
  113. const StaticPluginLoader spl(p, "Cardinal");
  114. if (spl.ok())
  115. {
  116. p->addModel(modelHostAudio2);
  117. p->addModel(modelHostCV);
  118. p->addModel(modelHostMIDI);
  119. p->addModel(modelHostMIDICC);
  120. p->addModel(modelHostMIDIGate);
  121. p->addModel(modelHostMIDIMap);
  122. p->addModel(modelHostParameters);
  123. p->addModel(modelHostParametersMap);
  124. p->addModel(modelHostTime);
  125. p->addModel(modelTextEditor);
  126. #ifdef HAVE_FFTW3F
  127. p->addModel(modelAudioToCVPitch);
  128. #else
  129. spl.removeModule("AudioToCVPitch");
  130. #endif
  131. spl.removeModule("AudioFile");
  132. spl.removeModule("Blank");
  133. spl.removeModule("Carla");
  134. spl.removeModule("ExpanderInputMIDI");
  135. spl.removeModule("ExpanderOutputMIDI");
  136. spl.removeModule("HostAudio8");
  137. spl.removeModule("Ildaeil");
  138. spl.removeModule("MPV");
  139. spl.removeModule("SassyScope");
  140. spl.removeModule("glBars");
  141. hostTerminalModels = {
  142. modelHostAudio2,
  143. modelHostCV,
  144. modelHostMIDI,
  145. modelHostMIDICC,
  146. modelHostMIDIGate,
  147. modelHostMIDIMap,
  148. modelHostParameters,
  149. modelHostParametersMap,
  150. modelHostTime,
  151. };
  152. }
  153. }
  154. static void initStatic__Fundamental()
  155. {
  156. Plugin* const p = new Plugin;
  157. pluginInstance__Fundamental = p;
  158. const StaticPluginLoader spl(p, "Fundamental");
  159. if (spl.ok())
  160. {
  161. p->addModel(modelADSR);
  162. p->addModel(modelLFO);
  163. p->addModel(modelVCF);
  164. p->addModel(modelVCO);
  165. spl.removeModule("VCO2");
  166. spl.removeModule("VCA-1");
  167. spl.removeModule("VCA");
  168. spl.removeModule("LFO2");
  169. spl.removeModule("Delay");
  170. spl.removeModule("Mixer");
  171. spl.removeModule("VCMixer");
  172. spl.removeModule("8vert");
  173. spl.removeModule("Mutes");
  174. spl.removeModule("Pulses");
  175. spl.removeModule("Scope");
  176. spl.removeModule("SEQ3");
  177. spl.removeModule("SequentialSwitch1");
  178. spl.removeModule("SequentialSwitch2");
  179. spl.removeModule("Octave");
  180. spl.removeModule("Quantizer");
  181. spl.removeModule("Split");
  182. spl.removeModule("Merge");
  183. spl.removeModule("Sum");
  184. spl.removeModule("MidSide");
  185. spl.removeModule("Noise");
  186. spl.removeModule("Random");
  187. }
  188. }
  189. void initStaticPlugins()
  190. {
  191. initStatic__Cardinal();
  192. initStatic__Fundamental();
  193. }
  194. void destroyStaticPlugins()
  195. {
  196. for (Plugin* p : plugins)
  197. delete p;
  198. plugins.clear();
  199. }
  200. void updateStaticPluginsDarkMode()
  201. {
  202. d_stdout("TODO");
  203. }
  204. }
  205. }