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.

223 lines
6.7KB

  1. #pragma once
  2. #include <vector>
  3. #include <common.hpp>
  4. #include <engine/Module.hpp>
  5. #include <engine/Cable.hpp>
  6. #include <engine/ParamHandle.hpp>
  7. namespace rack {
  8. namespace engine {
  9. /** Manages Modules and Cables and steps them in time.
  10. Engine contains a read/write mutex that locks when the Engine state is being read or written (manipulated).
  11. Methods that read-lock (stated in their documentation) can be called simultaneously with other read-locking methods.
  12. Methods that write-lock cannot be called simultaneously or recursively with another read-locking or write-locking method.
  13. */
  14. struct Engine {
  15. struct Internal;
  16. Internal* internal;
  17. Engine();
  18. ~Engine();
  19. /** Removes all modules and cables.
  20. Write-locks.
  21. */
  22. void clear();
  23. INTERNAL void clear_NoLock();
  24. /** Advances the engine by `frames` frames.
  25. Only call this method from the primary module.
  26. Read-locks. Also locks so only one stepBlock() can be called simultaneously or recursively.
  27. */
  28. void stepBlock(int frames);
  29. /** Module does not need to belong to the Engine.
  30. However, Engine will unset the primary module when it is removed from the Engine.
  31. NULL will unset the primary module.
  32. Write-locks.
  33. */
  34. void setPrimaryModule(Module* module);
  35. Module* getPrimaryModule();
  36. /** Returns the sample rate used by the engine for stepping each module.
  37. */
  38. float getSampleRate();
  39. /** Sets the sample rate to step the modules.
  40. Write-locks.
  41. */
  42. INTERNAL void setSampleRate(float sampleRate);
  43. /** Sets the sample rate if the sample rate in the settings is "Auto".
  44. Write-locks.
  45. */
  46. void setSuggestedSampleRate(float suggestedSampleRate);
  47. /** Returns the inverse of the current sample rate.
  48. */
  49. float getSampleTime();
  50. /** Causes worker threads to block on a mutex instead of spinlock.
  51. Call this in your Module::stepBlock() method to hint that the operation will take more than ~0.1 ms.
  52. */
  53. void yieldWorkers();
  54. /** Returns the number of stepBlock() calls since the Engine was created.
  55. */
  56. int64_t getBlock();
  57. /** Returns the frame counter which increases every sample step.
  58. Not necessarily monotonically increasing. Can be reset at any time.
  59. */
  60. int64_t getFrame();
  61. /** Sets the frame counter.
  62. Useful for when the DAW playhead position jumps to a new position.
  63. Rack plugins and standalone Rack should not call this function.
  64. */
  65. void setFrame(int64_t frame);
  66. /** Returns the frame when stepBlock() was last called.
  67. */
  68. int64_t getBlockFrame();
  69. /** Returns the time in seconds when stepBlock() was last called.
  70. */
  71. double getBlockTime();
  72. /** Returns the total number of frames in the current stepBlock() call.
  73. */
  74. int getBlockFrames();
  75. /** Returns the total time that stepBlock() is advancing, in seconds.
  76. Calculated by `stepFrames / sampleRate`.
  77. */
  78. double getBlockDuration();
  79. // Modules
  80. size_t getNumModules();
  81. /** Fills `moduleIds` with up to `len` module IDs in the rack.
  82. Returns the number of IDs written.
  83. This C-like method does no allocations. The vector C++ version below does.
  84. Read-locks.
  85. */
  86. size_t getModuleIds(int64_t* moduleIds, size_t len);
  87. /** Returns a vector of module IDs in the rack.
  88. Read-locks.
  89. */
  90. std::vector<int64_t> getModuleIds();
  91. /** Adds a Module to the rack.
  92. The module ID must not be taken by another Module.
  93. If the module ID is -1, an ID is automatically assigned.
  94. Does not transfer pointer ownership.
  95. Write-locks.
  96. */
  97. void addModule(Module* module);
  98. /** Removes a Module from the rack.
  99. Write-locks.
  100. */
  101. void removeModule(Module* module);
  102. INTERNAL void removeModule_NoLock(Module* module);
  103. /** Checks whether a Module is in the rack.
  104. Read-locks.
  105. */
  106. bool hasModule(Module* module);
  107. /** Returns the Module with the given ID in the rack.
  108. Read-locks.
  109. */
  110. Module* getModule(int64_t moduleId);
  111. /** Triggers a ResetEvent for the given Module.
  112. Write-locks.
  113. */
  114. void resetModule(Module* module);
  115. /** Triggers a RandomizeEvent for the given Module.
  116. Write-locks.
  117. */
  118. void randomizeModule(Module* module);
  119. /** Sets the bypassed state and triggers a BypassEvent or UnBypassEvent of the given Module.
  120. Write-locks.
  121. */
  122. void bypassModule(Module* module, bool bypassed);
  123. /** Serializes the given Module with locking, ensuring that Module::process() is not called simultaneously.
  124. Read-locks.
  125. */
  126. json_t* moduleToJson(Module* module);
  127. /** Serializes the given Module with locking, ensuring that Module::process() is not called simultaneously.
  128. Write-locks.
  129. */
  130. void moduleFromJson(Module* module, json_t* rootJ);
  131. // Cables
  132. size_t getNumCables();
  133. /** Fills `cableIds` with up to `len` cable IDs in the rack.
  134. Returns the number of IDs written.
  135. This C-like method does no allocations. The vector C++ version below does.
  136. Read-locks.
  137. */
  138. size_t getCableIds(int64_t* cableIds, size_t len);
  139. /** Returns a vector of cable IDs in the rack.
  140. Read-locks.
  141. */
  142. std::vector<int64_t> getCableIds();
  143. /** Adds a Cable to the rack.
  144. The cable ID must not be taken by another cable.
  145. If the cable ID is -1, an ID is automatically assigned.
  146. Does not transfer pointer ownership.
  147. Write-locks.
  148. */
  149. void addCable(Cable* cable);
  150. /** Removes a Cable from the rack.
  151. Write-locks.
  152. */
  153. void removeCable(Cable* cable);
  154. INTERNAL void removeCable_NoLock(Cable* cable);
  155. /** Checks whether a Cable is in the rack.
  156. Read-locks.
  157. */
  158. bool hasCable(Cable* cable);
  159. /** Returns the Cable with the given ID in the rack.
  160. Read-locks.
  161. */
  162. Cable* getCable(int64_t cableId);
  163. // Params
  164. void setParam(Module* module, int paramId, float value);
  165. float getParam(Module* module, int paramId);
  166. /** Requests the parameter to smoothly change toward `value`.
  167. */
  168. void setSmoothParam(Module* module, int paramId, float value);
  169. /** Returns the target value before smoothing.
  170. */
  171. float getSmoothParam(Module* module, int paramId);
  172. // ParamHandles
  173. /** Adds a ParamHandle to the rack.
  174. Does not automatically update the ParamHandle.
  175. Write-locks.
  176. */
  177. void addParamHandle(ParamHandle* paramHandle);
  178. /**
  179. Write-locks.
  180. */
  181. void removeParamHandle(ParamHandle* paramHandle);
  182. INTERNAL void removeParamHandle_NoLock(ParamHandle* paramHandle);
  183. /** Returns the unique ParamHandle for the given paramId
  184. Read-locks.
  185. */
  186. ParamHandle* getParamHandle(int64_t moduleId, int paramId);
  187. /** Use getParamHandle(moduleId, paramId) instead.
  188. Read-locks.
  189. */
  190. DEPRECATED ParamHandle* getParamHandle(Module* module, int paramId);
  191. /** Sets the ParamHandle IDs and module pointer.
  192. If `overwrite` is true and another ParamHandle points to the same param, unsets that one and replaces it with the given handle.
  193. Read-locks.
  194. */
  195. void updateParamHandle(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite = true);
  196. /** Serializes the rack.
  197. Read-locks.
  198. */
  199. json_t* toJson();
  200. /** Deserializes the rack.
  201. Write-locks.
  202. */
  203. void fromJson(json_t* rootJ);
  204. };
  205. } // namespace engine
  206. } // namespace rack