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.

196 lines
5.1KB

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