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.

241 lines
5.6KB

  1. /*
  2. * DISTRHO Cardinal Plugin
  3. * Copyright (C) 2021 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. #ifndef PLUGIN_INSTANCE
  18. # error PLUGIN_INSTANCE undefined
  19. #endif
  20. #ifndef PLUGIN_MODEL
  21. # error PLUGIN_MODEL undefined
  22. #endif
  23. #ifndef PLUGIN_URI
  24. # error PLUGIN_URI undefined
  25. #endif
  26. #define PRIVATE
  27. #include <common.hpp>
  28. #include <engine/Engine.hpp>
  29. #undef PRIVATE
  30. #include <rack.hpp>
  31. #include "src/lv2/buf-size.h"
  32. #include "src/lv2/options.h"
  33. #include "DistrhoUtils.hpp"
  34. using namespace rack;
  35. extern Model* PLUGIN_MODEL;
  36. extern Plugin* PLUGIN_INSTANCE;
  37. namespace rack {
  38. namespace engine {
  39. struct Engine::Internal {
  40. float sampleRate;
  41. };
  42. Engine::Engine()
  43. {
  44. internal = new Internal;
  45. }
  46. Engine::~Engine()
  47. {
  48. delete internal;
  49. }
  50. float Engine::getSampleRate()
  51. {
  52. return internal->sampleRate;
  53. }
  54. }
  55. namespace plugin {
  56. void Plugin::addModel(Model* model)
  57. {
  58. // Check that the model is not added to a plugin already
  59. DISTRHO_SAFE_ASSERT_RETURN(model != nullptr,);
  60. DISTRHO_SAFE_ASSERT_RETURN(model->plugin == nullptr,);
  61. model->plugin = this;
  62. models.push_back(model);
  63. }
  64. Model* modelFromJson(json_t* moduleJ) {
  65. return nullptr;
  66. }
  67. std::vector<Plugin*> plugins;
  68. } // namespace plugin
  69. } // namespace rack
  70. struct PluginLv2 {
  71. Plugin* plugin;
  72. engine::Module* module;
  73. float sampleRate;
  74. int frameCount = 0;
  75. int numInputs, numOutputs, numParams, numLights;
  76. void** ports;
  77. PluginLv2(double sr)
  78. {
  79. // FIXME shared instance for these 2
  80. Context* const context = new Context;
  81. context->engine = new Engine;
  82. context->engine->internal->sampleRate = sr;
  83. contextSet(context);
  84. plugin = new Plugin;
  85. PLUGIN_INSTANCE = plugin;
  86. sampleRate = sr;
  87. plugin->addModel(PLUGIN_MODEL);
  88. module = PLUGIN_MODEL->createModule();
  89. numInputs = module->getNumInputs();
  90. numOutputs = module->getNumOutputs();
  91. numParams = module->getNumParams();
  92. numLights = module->getNumLights();
  93. ports = new void*[numInputs+numOutputs+numParams+numLights];
  94. // FIXME for CV ports we need to detect if something is connected
  95. for (int i=numInputs; --i >=0;)
  96. module->inputs[i].channels = 1;
  97. for (int i=numOutputs; --i >=0;)
  98. module->outputs[i].channels = 1;
  99. d_stdout("Loaded %s :: %i inputs, %i outputs, %i params and %i lights",
  100. PLUGIN_URI, numInputs, numOutputs, numParams, numLights);
  101. }
  102. PluginLv2()
  103. {
  104. delete[] ports;
  105. delete module;
  106. // FIXME shared instance for this
  107. delete plugin;
  108. delete contextGet();
  109. }
  110. void lv2_connect_port(const uint32_t port, void* const dataLocation)
  111. {
  112. ports[port] = dataLocation;
  113. }
  114. void lv2_activate()
  115. {
  116. module->onReset();
  117. }
  118. void lv2_run(const uint32_t sampleCount)
  119. {
  120. if (sampleCount == 0)
  121. return;
  122. Module::ProcessArgs args = {
  123. sampleRate,
  124. 1.0f / sampleRate,
  125. frameCount
  126. };
  127. for (int i=numParams; --i >=0;)
  128. module->params[i].setValue(*static_cast<float*>(ports[numInputs+numOutputs+i]) * 0.1f); // FIXME?
  129. for (uint32_t s=0; s<sampleCount; ++s)
  130. {
  131. for (int i=numInputs; --i >=0;)
  132. module->inputs[i].setVoltage(static_cast<const float*>(ports[i])[s] * 5.0f);
  133. module->doProcess(args);
  134. for (int i=numOutputs; --i >=0;)
  135. static_cast<float*>(ports[numInputs+i])[s] = module->outputs[i].getVoltage() * 0.2f;
  136. ++args.frame;
  137. }
  138. frameCount += sampleCount;
  139. }
  140. };
  141. static LV2_Handle lv2_instantiate(const LV2_Descriptor*, double sampleRate, const char* bundlePath, const LV2_Feature* const* features)
  142. {
  143. return new PluginLv2(sampleRate);
  144. }
  145. // -----------------------------------------------------------------------
  146. #define instancePtr ((PluginLv2*)instance)
  147. static void lv2_connect_port(LV2_Handle instance, uint32_t port, void* dataLocation)
  148. {
  149. instancePtr->lv2_connect_port(port, dataLocation);
  150. }
  151. static void lv2_activate(LV2_Handle instance)
  152. {
  153. instancePtr->lv2_activate();
  154. }
  155. static void lv2_run(LV2_Handle instance, uint32_t sampleCount)
  156. {
  157. instancePtr->lv2_run(sampleCount);
  158. }
  159. static void lv2_deactivate(LV2_Handle instance)
  160. {
  161. }
  162. static void lv2_cleanup(LV2_Handle instance)
  163. {
  164. delete instancePtr;
  165. }
  166. // -----------------------------------------------------------------------
  167. static const void* lv2_extension_data(const char* uri)
  168. {
  169. return nullptr;
  170. }
  171. #undef instancePtr
  172. // -----------------------------------------------------------------------
  173. static const LV2_Descriptor sLv2Descriptor = {
  174. PLUGIN_URI,
  175. lv2_instantiate,
  176. lv2_connect_port,
  177. lv2_activate,
  178. lv2_run,
  179. lv2_deactivate,
  180. lv2_cleanup,
  181. lv2_extension_data
  182. };
  183. DISTRHO_PLUGIN_EXPORT
  184. const LV2_Descriptor* lv2_descriptor(uint32_t index)
  185. {
  186. USE_NAMESPACE_DISTRHO
  187. return (index == 0) ? &sLv2Descriptor : nullptr;
  188. }
  189. // -----------------------------------------------------------------------