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.

292 lines
9.9KB

  1. #pragma once
  2. #include "global_pre.hpp"
  3. #include <string>
  4. #include <stdio.h> // debug
  5. #include <list>
  6. #include "tags.hpp"
  7. #define RACK_PLUGIN_INIT_ID_INTERNAL p->slug = TOSTRING(SLUG); p->version = TOSTRING(VERSION)
  8. #ifdef USE_VST2
  9. namespace rack {
  10. struct Plugin;
  11. }
  12. typedef void (*vst2_handle_ui_param_fxn_t) (int uniqueParamId, float normValue);
  13. typedef void (*rack_set_tls_globals_fxn_t) (rack::Plugin *p);
  14. #ifdef RACK_HOST
  15. // Rack host build:
  16. extern void vst2_handle_ui_param (int uniqueParamId, float normValue);
  17. #define RACK_PLUGIN_DECLARE(pluginname)
  18. #define RACK_PLUGIN_INIT(pluginname) extern "C" void init_plugin_##pluginname##(rack::Plugin *p)
  19. #define RACK_PLUGIN_INIT_ID() RACK_PLUGIN_INIT_ID_INTERNAL
  20. #else
  21. // Plugin build:
  22. #ifdef _MSC_VER
  23. #ifdef RACK_PLUGIN_SHARED
  24. #define RACK_PLUGIN_EXPORT extern "C" __declspec(dllexport)
  25. #else
  26. #define RACK_PLUGIN_EXPORT extern "C"
  27. #endif // RACK_PLUGIN_SHARED
  28. #define RACK_TLS __declspec(thread)
  29. #else
  30. #define RACK_PLUGIN_EXPORT extern "C"
  31. #define RACK_TLS __thread
  32. #endif // _MSC_VER
  33. extern vst2_handle_ui_param_fxn_t vst2_handle_ui_param;
  34. #ifndef RACK_PLUGIN_SHARED_LIB_BUILD
  35. #ifdef RACK_PLUGIN_SHARED
  36. // Dynamically loaded plugin build
  37. #define RACK_PLUGIN_DECLARE(pluginname) namespace rack { extern RACK_TLS Plugin *plugin; } extern void __rack_unused_symbol(void)
  38. #ifdef ARCH_WIN
  39. #define JSON_SEED_INIT_EXTERNAL extern "C" extern long seed_initialized;
  40. #else
  41. #define JSON_SEED_INIT_EXTERNAL extern "C" extern volatile char seed_initialized;
  42. #endif
  43. #define RACK_PLUGIN_INIT(pluginname) \
  44. vst2_handle_ui_param_fxn_t vst2_handle_ui_param; \
  45. JSON_SEED_INIT_EXTERNAL \
  46. extern "C" extern volatile uint32_t hashtable_seed; \
  47. namespace rack { \
  48. RACK_TLS Plugin *plugin; \
  49. RACK_TLS Global *global; \
  50. RACK_TLS GlobalUI *global_ui; \
  51. static void loc_set_tls_globals(rack::Plugin *p) { \
  52. plugin = p; \
  53. global = plugin->global; \
  54. global_ui = plugin->global_ui; \
  55. hashtable_seed = p->json.hashtable_seed; \
  56. seed_initialized = p->json.seed_initialized; \
  57. } \
  58. } \
  59. RACK_PLUGIN_EXPORT void init_plugin(rack::Plugin *p)
  60. #define RACK_PLUGIN_INIT_ID() \
  61. rack::plugin = p; \
  62. rack::plugin->set_tls_globals_fxn = &rack::loc_set_tls_globals; \
  63. vst2_handle_ui_param = p->vst2_handle_ui_param_fxn; \
  64. rack::global = p->global; \
  65. rack::global_ui = p->global_ui; \
  66. RACK_PLUGIN_INIT_ID_INTERNAL
  67. #else
  68. // Statically linked plugin build
  69. #define RACK_PLUGIN_DECLARE(pluginname)
  70. #define RACK_PLUGIN_INIT(pluginname) extern "C" void init_plugin_##pluginname##(rack::Plugin *p)
  71. #define RACK_PLUGIN_INIT_ID() RACK_PLUGIN_INIT_ID_INTERNAL
  72. #endif // RACK_PLUGIN_SHARED
  73. #endif // RACK_PLUGIN_SHARED_LIB_BUILD
  74. #endif // RACK_HOST
  75. #else
  76. #define RACK_PLUGIN_DECLARE(pluginname) extern Plugin *plugin
  77. #define RACK_PLUGIN_INIT(pluginname) extern "C" RACK_PLUGIN_EXPORT void init(rack::Plugin *p)
  78. #define RACK_PLUGIN_INIT_ID() plugin = p; RACK_PLUGIN_INIT_ID_INTERNAL
  79. #endif // USE_VST2
  80. #define RACK_PLUGIN_INIT_WEBSITE(url) p->website = url
  81. #define RACK_PLUGIN_INIT_MANUAL(url) p->manual = url
  82. #define RACK_PLUGIN_INIT_VERSION(ver) p->version = ver
  83. #define RACK_PLUGIN_MODEL_DECLARE(pluginname, modelname) extern Model *create_model_##pluginname##_##modelname##(void)
  84. #define RACK_PLUGIN_MODEL_INIT(pluginname, modelname) Model *create_model_##pluginname##_##modelname##(void)
  85. #define RACK_PLUGIN_MODEL_ADD(pluginname, modelname) p->addModel(create_model_##pluginname##_##modelname##())
  86. namespace rack {
  87. struct ModuleWidget;
  88. struct Module;
  89. struct Model;
  90. // Subclass this and return a pointer to a new one when init() is called
  91. struct Plugin {
  92. /** A list of the models available by this plugin, add with addModel() */
  93. std::list<Model*> models;
  94. /** The file path of the plugin's directory */
  95. std::string path;
  96. /** OS-dependent library handle */
  97. void *handle = NULL;
  98. /** Must be unique. Used for patch files and the VCV store API.
  99. To guarantee uniqueness, it is a good idea to prefix the slug by your "company name" if available, e.g. "MyCompany-MyPlugin"
  100. */
  101. std::string slug;
  102. /** The version of your plugin
  103. Plugins should follow the versioning scheme described at https://github.com/VCVRack/Rack/issues/266
  104. Do not include the "v" in "v1.0" for example.
  105. */
  106. std::string version;
  107. /** Deprecated, do not use. */
  108. std::string website;
  109. std::string manual;
  110. #ifdef USE_VST2
  111. //
  112. // Set by Rack host (before init_plugin()):
  113. //
  114. vst2_handle_ui_param_fxn_t vst2_handle_ui_param_fxn = NULL;
  115. Global *global = NULL;
  116. GlobalUI *global_ui = NULL;
  117. // Set by Rack host immediately before set_tls_globals_fxn is called:
  118. // (note) must be copied by the plugin or json import won't function properly
  119. struct {
  120. uint32_t hashtable_seed;
  121. #ifdef ARCH_WIN
  122. long seed_initialized;
  123. #else
  124. char seed_initialized;
  125. #endif
  126. } json;
  127. //
  128. // Set by plugin:
  129. // - in init_plugin()
  130. // - called by Rack host in audio thread
  131. // - NULL if this is a statically linked add-on
  132. //
  133. rack_set_tls_globals_fxn_t set_tls_globals_fxn = NULL;
  134. #endif // USE_VST2
  135. virtual ~Plugin();
  136. void addModel(Model *model);
  137. };
  138. struct Model {
  139. Plugin *plugin = NULL;
  140. /** An identifier for the model, e.g. "VCO". Used for saving patches.
  141. The model slug must be unique in your plugin, but it doesn't need to be unique among different plugins.
  142. */
  143. std::string slug;
  144. /** Human readable name for your model, e.g. "Voltage Controlled Oscillator" */
  145. std::string name;
  146. /** The author name of the module.
  147. This might be different than the plugin slug. For example, if you create multiple plugins but want them to be branded similarly, you may use the same author in multiple plugins.
  148. You may even have multiple authors in one plugin, although this property will be moved to Plugin for Rack 1.0.
  149. */
  150. std::string author;
  151. /** List of tags representing the function(s) of the module (optional) */
  152. std::list<ModelTag> tags;
  153. virtual ~Model() {}
  154. /** Creates a headless Module */
  155. virtual Module *createModule() { return NULL; }
  156. /** Creates a ModuleWidget with a Module attached */
  157. virtual ModuleWidget *createModuleWidget() { return NULL; }
  158. /** Creates a ModuleWidget with no Module, useful for previews */
  159. virtual ModuleWidget *createModuleWidgetNull() { return NULL; }
  160. /** Create Model subclass which constructs a specific Module and ModuleWidget subclass */
  161. template <typename TModule, typename TModuleWidget, typename... Tags>
  162. static Model *create(std::string author, std::string slug, std::string name, Tags... tags) {
  163. struct TModel : Model {
  164. Module *createModule() override {
  165. TModule *module = new TModule();
  166. return module;
  167. }
  168. ModuleWidget *createModuleWidget() override {
  169. printf("xxx createModuleWidget: ENTER\n");
  170. TModule *module = new TModule();
  171. printf("xxx createModuleWidget: module=%p\n", module);
  172. TModuleWidget *moduleWidget = new TModuleWidget(module);
  173. printf("xxx createModuleWidget: moduleWidget=%p\n", moduleWidget);
  174. moduleWidget->model = this;
  175. printf("xxx createModuleWidget: LEAVE\n");
  176. return moduleWidget;
  177. }
  178. ModuleWidget *createModuleWidgetNull() override {
  179. TModuleWidget *moduleWidget = new TModuleWidget(NULL);
  180. moduleWidget->model = this;
  181. return moduleWidget;
  182. }
  183. };
  184. TModel *o = new TModel();
  185. o->author = author;
  186. o->slug = slug;
  187. o->name = name;
  188. o->tags = {tags...};
  189. return o;
  190. }
  191. };
  192. void pluginInit(bool devMode);
  193. void pluginDestroy();
  194. void pluginLogIn(std::string email, std::string password);
  195. void pluginLogOut();
  196. /** Returns whether a new plugin is available, and downloads it unless doing a dry run */
  197. bool pluginSync(bool dryRun);
  198. void pluginCancelDownload();
  199. bool pluginIsLoggedIn();
  200. bool pluginIsDownloading();
  201. float pluginGetDownloadProgress();
  202. std::string pluginGetDownloadName();
  203. std::string pluginGetLoginStatus();
  204. Plugin *pluginGetPlugin(std::string pluginSlug);
  205. Model *pluginGetModel(std::string pluginSlug, std::string modelSlug);
  206. extern std::list<Plugin*> gPlugins;
  207. extern std::string gToken;
  208. } // namespace rack
  209. // Access helpers for global UI vars
  210. //
  211. // (note) these avoid accessing the global rack vars directly
  212. // (global TLS vars cannot be exported to dynamically loaded plugins)
  213. //
  214. // (note) please use the macros and do _not_ call the functions directly!
  215. //
  216. #include "global_pre.hpp"
  217. #include "global_ui.hpp"
  218. extern rack::RackScene *rack_plugin_ui_get_rackscene(void);
  219. #define RACK_PLUGIN_UI_RACKSCENE rack_plugin_ui_get_rackscene()
  220. extern rack::RackWidget *rack_plugin_ui_get_rackwidget(void);
  221. #define RACK_PLUGIN_UI_RACKWIDGET rack_plugin_ui_get_rackwidget()
  222. extern rack::Toolbar *rack_plugin_ui_get_toolbar(void);
  223. #define RACK_PLUGIN_UI_TOOLBAR rack_plugin_ui_get_toolbar()
  224. extern rack::Widget *rack_plugin_ui_get_hovered_widget(void);
  225. #define RACK_PLUGIN_UI_HOVERED_WIDGET rack_plugin_ui_get_hovered_widget()
  226. extern rack::Widget *rack_plugin_ui_get_dragged_widget(void);
  227. #define RACK_PLUGIN_UI_DRAGGED_WIDGET rack_plugin_ui_get_dragged_widget()
  228. extern void rack_plugin_ui_set_dragged_widget(rack::Widget *);
  229. #define RACK_PLUGIN_UI_DRAGGED_WIDGET_SET(a) rack_plugin_ui_set_dragged_widget(a)
  230. extern rack::Widget *rack_plugin_ui_get_draghovered_widget(void);
  231. #define RACK_PLUGIN_UI_DRAGHOVERED_WIDGET rack_plugin_ui_get_draghovered_widget()
  232. extern rack::Widget *rack_plugin_ui_get_focused_widget(void);
  233. #define RACK_PLUGIN_UI_FOCUSED_WIDGET rack_plugin_ui_get_focused_widget()
  234. extern void rack_plugin_ui_set_focused_widget(rack::Widget *);
  235. #define RACK_PLUGIN_UI_FOCUSED_WIDGET_SET(a) rack_plugin_ui_set_focused_widget(a)