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.

316 lines
11KB

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