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.

357 lines
11KB

  1. #pragma once
  2. #include <vector>
  3. #include <jansson.h>
  4. #include <common.hpp>
  5. #include <string.hpp>
  6. #include <plugin/Model.hpp>
  7. #include <engine/Param.hpp>
  8. #include <engine/Port.hpp>
  9. #include <engine/Light.hpp>
  10. #include <engine/ParamQuantity.hpp>
  11. #include <engine/PortInfo.hpp>
  12. #include <engine/LightInfo.hpp>
  13. namespace rack {
  14. namespace plugin {
  15. struct Model;
  16. }
  17. namespace engine {
  18. /** DSP processor instance for your module. */
  19. struct Module {
  20. struct Internal;
  21. Internal* internal;
  22. plugin::Model* model = NULL;
  23. /** Unique ID for referring to the module in the engine.
  24. Between 0 and 2^53 since this is serialized with JSON.
  25. Assigned when added to the engine.
  26. */
  27. int64_t id = -1;
  28. /** Arrays of components.
  29. Initialized with config().
  30. */
  31. std::vector<Param> params;
  32. std::vector<Input> inputs;
  33. std::vector<Output> outputs;
  34. std::vector<Light> lights;
  35. /** Arrays of components.
  36. Initialized with configParam(), configInput(), configOutput(), and configLight().
  37. LightInfos are initialized to null unless configLight() is called.
  38. */
  39. std::vector<ParamQuantity*> paramQuantities;
  40. std::vector<PortInfo*> inputInfos;
  41. std::vector<PortInfo*> outputInfos;
  42. std::vector<LightInfo*> lightInfos;
  43. /** Represents a message-passing channel for an adjacent module. */
  44. struct Expander {
  45. /** ID of the expander module, or -1 if nonexistent. */
  46. int64_t moduleId = -1;
  47. /** Pointer to the expander Module, or NULL if nonexistent. */
  48. Module* module = NULL;
  49. /** Double buffer for receiving messages from the expander module.
  50. If you intend to receive messages from an expander, allocate both message buffers with identical blocks of memory (arrays, structs, etc).
  51. Remember to free the buffer in the Module destructor.
  52. Example:
  53. rightExpander.producerMessage = new MyExpanderMessage;
  54. rightExpander.consumerMessage = new MyExpanderMessage;
  55. You must check the expander module's `model` before attempting to write its message buffer.
  56. Once the module is checked, you can reinterpret_cast its producerMessage at no performance cost.
  57. Producer messages are intended to be write-only.
  58. Consumer messages are intended to be read-only.
  59. Once you write a message, set messageFlipRequested to true to request that the messages are flipped at the end of the timestep.
  60. This means that message-passing has 1-sample latency.
  61. You may choose for your Module to instead write to its own message buffer for consumption by other modules, i.e. the expander "pulls" rather than this module "pushing".
  62. As long as this convention is followed by the other module, this is fine.
  63. */
  64. void* producerMessage = NULL;
  65. void* consumerMessage = NULL;
  66. bool messageFlipRequested = false;
  67. };
  68. Expander leftExpander;
  69. Expander rightExpander;
  70. struct BypassRoute {
  71. int inputId = -1;
  72. int outputId = -1;
  73. };
  74. std::vector<BypassRoute> bypassRoutes;
  75. /** Constructs a Module with no params, inputs, outputs, and lights. */
  76. Module();
  77. /** Use config() instead. */
  78. DEPRECATED Module(int numParams, int numInputs, int numOutputs, int numLights = 0) : Module() {
  79. config(numParams, numInputs, numOutputs, numLights);
  80. }
  81. virtual ~Module();
  82. /** Configures the number of Params, Outputs, Inputs, and Lights. */
  83. void config(int numParams, int numInputs, int numOutputs, int numLights = 0);
  84. /** Helper for creating a ParamQuantity and setting its properties.
  85. See ParamQuantity for documentation of arguments.
  86. */
  87. template <class TParamQuantity = ParamQuantity>
  88. TParamQuantity* configParam(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f, float displayOffset = 0.f) {
  89. assert(paramId < (int) params.size() && paramId < (int) paramQuantities.size());
  90. if (paramQuantities[paramId])
  91. delete paramQuantities[paramId];
  92. TParamQuantity* q = new TParamQuantity;
  93. q->module = this;
  94. q->paramId = paramId;
  95. q->minValue = minValue;
  96. q->maxValue = maxValue;
  97. q->defaultValue = defaultValue;
  98. q->name = name;
  99. q->unit = unit;
  100. q->displayBase = displayBase;
  101. q->displayMultiplier = displayMultiplier;
  102. q->displayOffset = displayOffset;
  103. paramQuantities[paramId] = q;
  104. Param* p = &params[paramId];
  105. p->value = q->getDefaultValue();
  106. return q;
  107. }
  108. /** Helper for creating a SwitchQuantity and setting its label strings.
  109. See ParamQuantity and SwitchQuantity for documentation of arguments.
  110. */
  111. template <class TSwitchQuantity = SwitchQuantity>
  112. TSwitchQuantity* configSwitch(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::vector<std::string> labels = {}) {
  113. TSwitchQuantity* sq = configParam<TSwitchQuantity>(paramId, minValue, maxValue, defaultValue, name);
  114. sq->labels = labels;
  115. return sq;
  116. }
  117. template <class TSwitchQuantity = SwitchQuantity>
  118. TSwitchQuantity* configButton(int paramId, std::string name = "") {
  119. TSwitchQuantity* sq = configParam<TSwitchQuantity>(paramId, 0.f, 1.f, 0.f, name);
  120. return sq;
  121. }
  122. /** Helper for creating a PortInfo for an input port and setting its properties.
  123. See PortInfo for documentation of arguments.
  124. */
  125. template <class TPortInfo = PortInfo>
  126. TPortInfo* configInput(int portId, std::string name = "") {
  127. assert(portId < (int) inputs.size() && portId < (int) inputInfos.size());
  128. if (inputInfos[portId])
  129. delete inputInfos[portId];
  130. TPortInfo* info = new TPortInfo;
  131. info->module = this;
  132. info->type = Port::INPUT;
  133. info->portId = portId;
  134. info->name = name;
  135. inputInfos[portId] = info;
  136. return info;
  137. }
  138. /** Helper for creating a PortInfo for an output port and setting its properties.
  139. See PortInfo for documentation of arguments.
  140. */
  141. template <class TPortInfo = PortInfo>
  142. TPortInfo* configOutput(int portId, std::string name = "") {
  143. assert(portId < (int) outputs.size() && portId < (int) outputInfos.size());
  144. if (outputInfos[portId])
  145. delete outputInfos[portId];
  146. TPortInfo* info = new TPortInfo;
  147. info->module = this;
  148. info->type = Port::OUTPUT;
  149. info->portId = portId;
  150. info->name = name;
  151. outputInfos[portId] = info;
  152. return info;
  153. }
  154. /** Helper for creating a LightInfo and setting its properties.
  155. For multi-colored lights, use the first lightId.
  156. See LightInfo for documentation of arguments.
  157. */
  158. template <class TLightInfo = LightInfo>
  159. TLightInfo* configLight(int lightId, std::string name = "") {
  160. assert(lightId < (int) lights.size() && lightId < (int) lightInfos.size());
  161. if (lightInfos[lightId])
  162. delete lightInfos[lightId];
  163. TLightInfo* info = new TLightInfo;
  164. info->module = this;
  165. info->lightId = lightId;
  166. info->name = name;
  167. lightInfos[lightId] = info;
  168. return info;
  169. }
  170. /** Adds a direct route from an input to an output when the module is bypassed.
  171. */
  172. void configBypass(int inputId, int outputId) {
  173. assert(inputId < (int) inputs.size());
  174. assert(outputId < (int) outputs.size());
  175. // Check that output is not yet routed
  176. for (BypassRoute& br : bypassRoutes) {
  177. assert(br.outputId != outputId);
  178. }
  179. BypassRoute br;
  180. br.inputId = inputId;
  181. br.outputId = outputId;
  182. bypassRoutes.push_back(br);
  183. }
  184. struct ProcessArgs {
  185. /** The current sample rate in Hz. */
  186. float sampleRate;
  187. /** The timestep of process() in seconds.
  188. Defined by `1 / sampleRate`.
  189. */
  190. float sampleTime;
  191. /** Number of audio samples since the Engine's first sample. */
  192. int64_t frame;
  193. };
  194. /** Advances the module by one audio sample.
  195. Override this method to read Inputs and Params and to write Outputs and Lights.
  196. */
  197. virtual void process(const ProcessArgs& args) {
  198. step();
  199. }
  200. /** DEPRECATED. Override `process(const ProcessArgs& args)` instead. */
  201. virtual void step() {}
  202. /** Called instead of process() when Module is bypassed.
  203. Typically you do not need to override this. Use configBypass() instead.
  204. If you do override it, avoid reading param values, since the state of the module should have no effect on routing.
  205. */
  206. virtual void processBypass(const ProcessArgs& args);
  207. /** Usually you should override dataToJson() instead.
  208. There are very few reasons you should override this (perhaps to lock a mutex while serialization is occurring).
  209. */
  210. virtual json_t* toJson();
  211. /** This is virtual only for the purpose of unserializing legacy data when you could set properties of the `.modules[]` object itself.
  212. Normally you should override dataFromJson().
  213. Remember to call `Module::fromJson(rootJ)` within your overridden method.
  214. */
  215. virtual void fromJson(json_t* rootJ);
  216. virtual json_t* paramsToJson();
  217. virtual void paramsFromJson(json_t* rootJ);
  218. /** Override to store extra internal data in the "data" property of the module's JSON object. */
  219. virtual json_t* dataToJson() {
  220. return NULL;
  221. }
  222. virtual void dataFromJson(json_t* root) {}
  223. ///////////////////////
  224. // Events
  225. ///////////////////////
  226. // All of these events are thread-safe with process().
  227. struct AddEvent {};
  228. /** Called after adding the module to the Engine.
  229. */
  230. virtual void onAdd(const AddEvent& e) {
  231. // Call deprecated event method by default
  232. onAdd();
  233. }
  234. struct RemoveEvent {};
  235. /** Called before removing the module to the Engine.
  236. */
  237. virtual void onRemove(const RemoveEvent& e) {
  238. // Call deprecated event method by default
  239. onRemove();
  240. }
  241. struct BypassEvent {};
  242. /** Called after bypassing the module.
  243. */
  244. virtual void onBypass(const BypassEvent& e) {}
  245. struct UnBypassEvent {};
  246. /** Called after enabling the module.
  247. */
  248. virtual void onUnBypass(const UnBypassEvent& e) {}
  249. struct PortChangeEvent {
  250. /** True if connecting, false if disconnecting. */
  251. bool connecting;
  252. Port::Type type;
  253. int portId;
  254. };
  255. /** Called after a cable connects to or disconnects from a port.
  256. This event is not called for output ports if a stackable cable was added/removed and did not change the port's connected state.
  257. */
  258. virtual void onPortChange(const PortChangeEvent& e) {}
  259. struct SampleRateChangeEvent {
  260. float sampleRate;
  261. float sampleTime;
  262. };
  263. /** Called after the Engine sample rate changes.
  264. */
  265. virtual void onSampleRateChange(const SampleRateChangeEvent& e) {
  266. // Call deprecated event method by default
  267. onSampleRateChange();
  268. }
  269. struct ExpanderChangeEvent {
  270. /** False for left, true for right. */
  271. bool side;
  272. };
  273. /** Called after an expander is added, removed, or changed on either the left or right side of the Module.
  274. */
  275. virtual void onExpanderChange(const ExpanderChangeEvent& e) {}
  276. struct ResetEvent {};
  277. /** Called when the user resets (initializes) the module.
  278. The default implementation resets all parameters to their default value, so you must call `Module::onReset(e)` in your overridden method if you want to keep this behavior.
  279. */
  280. virtual void onReset(const ResetEvent& e);
  281. struct RandomizeEvent {};
  282. /** Called when the user randomizes the module.
  283. The default implementation randomizes all parameters by default, so you must call `Module::onRandomize(e)` in your overridden method if you want to keep this behavior.
  284. */
  285. virtual void onRandomize(const RandomizeEvent& e);
  286. /** DEPRECATED. Override `onAdd(e)` instead. */
  287. virtual void onAdd() {}
  288. /** DEPRECATED. Override `onRemove(e)` instead. */
  289. virtual void onRemove() {}
  290. /** DEPRECATED. Override `onReset(e)` instead. */
  291. virtual void onReset() {}
  292. /** DEPRECATED. Override `onRandomize(e)` instead. */
  293. virtual void onRandomize() {}
  294. /** DEPRECATED. Override `onSampleRateChange(e)` instead. */
  295. virtual void onSampleRateChange() {}
  296. PRIVATE bool& bypass();
  297. PRIVATE const float* meterBuffer();
  298. PRIVATE int meterLength();
  299. PRIVATE int meterIndex();
  300. PRIVATE void doProcess(const ProcessArgs& args);
  301. };
  302. } // namespace engine
  303. } // namespace rack