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.

318 lines
12KB

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