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.

820 lines
24KB

  1. #include "global_pre.hpp"
  2. #include "plugin.hpp"
  3. #include "Core/Core.hpp"
  4. #include "app.hpp"
  5. #include "asset.hpp"
  6. #include "util/request.hpp"
  7. #include "osdialog.h"
  8. #include <stdio.h>
  9. #include <assert.h>
  10. #include <string.h>
  11. #ifdef YAC_POSIX
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <sys/param.h> // for MAXPATHLEN
  16. #include <fcntl.h>
  17. #include <dirent.h>
  18. #else
  19. #include "util/dirent_win32/dirent.h"
  20. #endif // YAC_POSIX
  21. #include <thread>
  22. #include <stdexcept>
  23. #include "global.hpp"
  24. #include "global_ui.hpp"
  25. #ifndef USE_VST2
  26. #define ZIP_STATIC
  27. #include <zip.h>
  28. #endif // USE_VST2
  29. #include <jansson.h>
  30. #if ARCH_WIN
  31. #include <windows.h>
  32. #include <direct.h>
  33. #define mkdir(_dir, _perms) _mkdir(_dir)
  34. #else
  35. #include <dlfcn.h>
  36. #endif
  37. namespace rack {
  38. typedef void (*InitCallback)(Plugin *);
  39. #ifdef USE_VST2
  40. #ifndef RACK_PLUGIN
  41. static void vst2_load_static_rack_plugins(void);
  42. #endif // RACK_PLUGIN
  43. #endif // USE_VST2
  44. Plugin::~Plugin() {
  45. for (Model *model : models) {
  46. delete model;
  47. }
  48. }
  49. void Plugin::addModel(Model *model) {
  50. assert(!model->plugin);
  51. model->plugin = this;
  52. models.push_back(model);
  53. }
  54. ////////////////////
  55. // private API
  56. ////////////////////
  57. static bool loadPlugin(std::string path) {
  58. #ifdef RACK_HOST
  59. std::string libraryFilename;
  60. #if ARCH_LIN
  61. libraryFilename = path + "/" + "plugin.so";
  62. #elif ARCH_WIN
  63. libraryFilename = path + "/" + "plugin.dll";
  64. #elif ARCH_MAC
  65. libraryFilename = path + "/" + "plugin.dylib";
  66. #endif
  67. // Check file existence
  68. if (!systemIsFile(libraryFilename)) {
  69. warn("Plugin file %s does not exist", libraryFilename.c_str());
  70. return false;
  71. }
  72. // Load dynamic/shared library
  73. #if ARCH_WIN
  74. SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
  75. // #ifdef USE_VST2
  76. // std::wstring libNameW = std::wstring(libraryFilename.begin(), libraryFilename.end());
  77. // HINSTANCE handle = LoadLibraryW(libNameW.c_str());
  78. // #else
  79. HINSTANCE handle = LoadLibrary(libraryFilename.c_str());
  80. // #endif
  81. SetErrorMode(0);
  82. if (!handle) {
  83. int error = GetLastError();
  84. warn("Failed to load library %s: code %d", libraryFilename.c_str(), error);
  85. return false;
  86. }
  87. #else
  88. void *handle = dlopen(libraryFilename.c_str(), RTLD_NOW);
  89. if (!handle) {
  90. warn("Failed to load library %s: %s", libraryFilename.c_str(), dlerror());
  91. return false;
  92. }
  93. #endif
  94. // Call plugin's init() function
  95. InitCallback initCallback;
  96. #ifdef USE_VST2
  97. #define init_symbol_name "init_plugin"
  98. #else
  99. #define init_symbol_name "init"
  100. #endif // USE_VST2
  101. #if ARCH_WIN
  102. initCallback = (InitCallback) GetProcAddress(handle, init_symbol_name);
  103. #else
  104. initCallback = (InitCallback) dlsym(handle, init_symbol_name);
  105. #endif
  106. if (!initCallback) {
  107. warn("Failed to read init() symbol in %s", libraryFilename.c_str());
  108. return false;
  109. }
  110. // Construct and initialize Plugin instance
  111. Plugin *plugin = new Plugin();
  112. plugin->path = path;
  113. plugin->handle = handle;
  114. #ifdef USE_VST2
  115. #ifdef RACK_HOST
  116. plugin->vst2_handle_ui_param_fxn = &vst2_handle_ui_param;
  117. plugin->global = global;
  118. plugin->global_ui = global_ui;
  119. #endif // RACK_HOST
  120. #endif // USE_VST2
  121. initCallback(plugin);
  122. // Reject plugin if slug already exists
  123. Plugin *oldPlugin = pluginGetPlugin(plugin->slug);
  124. if (oldPlugin) {
  125. warn("Plugin \"%s\" is already loaded, not attempting to load it again", plugin->slug.c_str());
  126. // TODO
  127. // Fix memory leak with `plugin` here
  128. return false;
  129. }
  130. // Add plugin to list
  131. global->plugin.gPlugins.push_back(plugin);
  132. info("Loaded plugin %s %s from %s", plugin->slug.c_str(), plugin->version.c_str(), libraryFilename.c_str());
  133. #else
  134. (void)path;
  135. #endif // RACK_HOST
  136. return true;
  137. }
  138. static bool syncPlugin(std::string slug, json_t *manifestJ, bool dryRun) {
  139. #ifndef USE_VST2
  140. // Check that "status" is "available"
  141. json_t *statusJ = json_object_get(manifestJ, "status");
  142. if (!statusJ) {
  143. return false;
  144. }
  145. std::string status = json_string_value(statusJ);
  146. if (status != "available") {
  147. return false;
  148. }
  149. // Get latest version
  150. json_t *latestVersionJ = json_object_get(manifestJ, "latestVersion");
  151. if (!latestVersionJ) {
  152. warn("Could not get latest version of plugin %s", slug.c_str());
  153. return false;
  154. }
  155. std::string latestVersion = json_string_value(latestVersionJ);
  156. // Check whether we already have a plugin with the same slug and version
  157. Plugin *plugin = pluginGetPlugin(slug);
  158. if (plugin && plugin->version == latestVersion) {
  159. return false;
  160. }
  161. json_t *nameJ = json_object_get(manifestJ, "name");
  162. std::string name;
  163. if (nameJ) {
  164. name = json_string_value(nameJ);
  165. }
  166. else {
  167. name = slug;
  168. }
  169. #if ARCH_WIN
  170. std::string arch = "win";
  171. #elif ARCH_MAC
  172. std::string arch = "mac";
  173. #elif ARCH_LIN
  174. std::string arch = "lin";
  175. #endif
  176. std::string downloadUrl;
  177. downloadUrl = global_ui->app.gApiHost;
  178. downloadUrl += "/download";
  179. if (dryRun) {
  180. downloadUrl += "/available";
  181. }
  182. downloadUrl += "?token=" + requestEscape(global->plugin.gToken);
  183. downloadUrl += "&slug=" + requestEscape(slug);
  184. downloadUrl += "&version=" + requestEscape(latestVersion);
  185. downloadUrl += "&arch=" + requestEscape(arch);
  186. #ifdef USE_VST2
  187. downloadUrl += "&format=vst2";
  188. #endif // USE_VST2
  189. if (dryRun) {
  190. // Check if available
  191. json_t *availableResJ = requestJson(METHOD_GET, downloadUrl, NULL);
  192. if (!availableResJ) {
  193. warn("Could not check whether download is available");
  194. return false;
  195. }
  196. defer({
  197. json_decref(availableResJ);
  198. });
  199. json_t *successJ = json_object_get(availableResJ, "success");
  200. return json_boolean_value(successJ);
  201. }
  202. else {
  203. global->plugin.downloadName = name;
  204. global->plugin.downloadProgress = 0.0;
  205. info("Downloading plugin %s %s %s", slug.c_str(), latestVersion.c_str(), arch.c_str());
  206. // Download zip
  207. std::string pluginDest = assetLocal("plugins/" + slug + ".zip");
  208. if (!requestDownload(downloadUrl, pluginDest, &global->plugin.downloadProgress)) {
  209. warn("Plugin %s download was unsuccessful", slug.c_str());
  210. return false;
  211. }
  212. global->plugin.downloadName = "";
  213. return true;
  214. }
  215. #else
  216. return false;
  217. #endif // USE_VST2
  218. }
  219. static void loadPlugins(std::string path) {
  220. #ifdef RACK_HOST
  221. std::string message;
  222. for (std::string pluginPath : systemListEntries(path)) {
  223. if (!systemIsDirectory(pluginPath))
  224. continue;
  225. if (!loadPlugin(pluginPath)) {
  226. #ifndef USE_VST2
  227. // (note) skip message (some plugins are linked statically in VST2 build)
  228. message += stringf("Could not load plugin %s\n", pluginPath.c_str());
  229. #endif // USE_VST2
  230. }
  231. }
  232. if (!message.empty()) {
  233. message += "See log for details.";
  234. osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str());
  235. }
  236. #else
  237. (void)path;
  238. #endif // RACK_HOST
  239. }
  240. #ifndef USE_VST2
  241. /** Returns 0 if successful */
  242. static int extractZipHandle(zip_t *za, const char *dir) {
  243. int err;
  244. for (int i = 0; i < zip_get_num_entries(za, 0); i++) {
  245. zip_stat_t zs;
  246. err = zip_stat_index(za, i, 0, &zs);
  247. if (err) {
  248. warn("zip_stat_index() failed: error %d", err);
  249. return err;
  250. }
  251. int nameLen = strlen(zs.name);
  252. char path[MAXPATHLEN];
  253. snprintf(path, sizeof(path), "%s/%s", dir, zs.name);
  254. if (zs.name[nameLen - 1] == '/') {
  255. if (mkdir(path, 0755)) {
  256. if (errno != EEXIST) {
  257. warn("mkdir(%s) failed: error %d", path, errno);
  258. return errno;
  259. }
  260. }
  261. }
  262. else {
  263. zip_file_t *zf = zip_fopen_index(za, i, 0);
  264. if (!zf) {
  265. warn("zip_fopen_index() failed");
  266. return -1;
  267. }
  268. FILE *outFile = fopen(path, "wb");
  269. if (!outFile)
  270. continue;
  271. while (1) {
  272. char buffer[1<<15];
  273. int len = zip_fread(zf, buffer, sizeof(buffer));
  274. if (len <= 0)
  275. break;
  276. fwrite(buffer, 1, len, outFile);
  277. }
  278. err = zip_fclose(zf);
  279. if (err) {
  280. warn("zip_fclose() failed: error %d", err);
  281. return err;
  282. }
  283. fclose(outFile);
  284. }
  285. }
  286. return 0;
  287. }
  288. #endif // USE_VST2
  289. #ifndef USE_VST2
  290. /** Returns 0 if successful */
  291. static int extractZip(const char *filename, const char *path) {
  292. int err;
  293. zip_t *za = zip_open(filename, 0, &err);
  294. if (!za) {
  295. warn("Could not open zip %s: error %d", filename, err);
  296. return err;
  297. }
  298. defer({
  299. zip_close(za);
  300. });
  301. err = extractZipHandle(za, path);
  302. return err;
  303. }
  304. #endif // USE_VST2
  305. #ifndef USE_VST2
  306. static void extractPackages(std::string path) {
  307. std::string message;
  308. for (std::string packagePath : systemListEntries(path)) {
  309. if (stringExtension(packagePath) != "zip")
  310. continue;
  311. info("Extracting package %s", packagePath.c_str());
  312. // Extract package
  313. if (extractZip(packagePath.c_str(), path.c_str())) {
  314. warn("Package %s failed to extract", packagePath.c_str());
  315. message += stringf("Could not extract package %s\n", packagePath.c_str());
  316. continue;
  317. }
  318. // Remove package
  319. if (remove(packagePath.c_str())) {
  320. warn("Could not delete file %s: error %d", packagePath.c_str(), errno);
  321. }
  322. }
  323. if (!message.empty()) {
  324. osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK, message.c_str());
  325. }
  326. }
  327. #endif // USE_VST2
  328. ////////////////////
  329. // public API
  330. ////////////////////
  331. void pluginInit(bool devMode) {
  332. tagsInit();
  333. #ifdef RACK_HOST
  334. // Load core
  335. // This function is defined in core.cpp
  336. Plugin *corePlugin = new Plugin();
  337. init_plugin_Core(corePlugin);
  338. global->plugin.gPlugins.push_back(corePlugin);
  339. // Init statically linked plugins
  340. vst2_load_static_rack_plugins();
  341. // Get local plugins directory
  342. std::string localPlugins = assetLocal("plugins");
  343. mkdir(localPlugins.c_str(), 0755);
  344. #ifndef USE_VST2
  345. if (!devMode) {
  346. // Copy Fundamental package to plugins directory if folder does not exist
  347. std::string fundamentalSrc = assetGlobal("Fundamental.zip");
  348. std::string fundamentalDest = assetLocal("plugins/Fundamental.zip");
  349. std::string fundamentalDir = assetLocal("plugins/Fundamental");
  350. if (systemIsFile(fundamentalSrc) && !systemIsFile(fundamentalDest) && !systemIsDirectory(fundamentalDir)) {
  351. systemCopy(fundamentalSrc, fundamentalDest);
  352. }
  353. }
  354. #endif // USE_VST2
  355. // Extract packages and load plugins
  356. #ifndef USE_VST2
  357. extractPackages(localPlugins);
  358. #endif // USE_VST2
  359. // Load/init dynamically loaded plugins
  360. loadPlugins(localPlugins);
  361. #endif // RACK_HOST
  362. }
  363. void pluginDestroy() {
  364. #ifndef USE_VST2
  365. for (Plugin *plugin : global->plugin.gPlugins) {
  366. // Free library handle
  367. #if ARCH_WIN
  368. if (plugin->handle)
  369. FreeLibrary((HINSTANCE)plugin->handle);
  370. #else
  371. if (plugin->handle)
  372. dlclose(plugin->handle);
  373. #endif
  374. // For some reason this segfaults.
  375. // It might be best to let them leak anyway, because "crash on exit" issues would occur with badly-written plugins.
  376. // delete plugin;
  377. }
  378. #endif // USE_VST2
  379. global->plugin.gPlugins.clear();
  380. }
  381. bool pluginSync(bool dryRun) {
  382. #ifndef USE_VST2
  383. if (global->plugin.gToken.empty())
  384. return false;
  385. bool available = false;
  386. if (!dryRun) {
  387. global->plugin.isDownloading = true;
  388. global->plugin.downloadProgress = 0.0;
  389. global->plugin.downloadName = "Updating plugins...";
  390. }
  391. defer({
  392. global->plugin.isDownloading = false;
  393. });
  394. // Get user's plugins list
  395. json_t *pluginsReqJ = json_object();
  396. json_object_set(pluginsReqJ, "token", json_string(global->plugin.gToken.c_str()));
  397. json_t *pluginsResJ = requestJson(METHOD_GET, global_ui->app.gApiHost + "/plugins", pluginsReqJ);
  398. json_decref(pluginsReqJ);
  399. if (!pluginsResJ) {
  400. warn("Request for user's plugins failed");
  401. return false;
  402. }
  403. defer({
  404. json_decref(pluginsResJ);
  405. });
  406. json_t *errorJ = json_object_get(pluginsResJ, "error");
  407. if (errorJ) {
  408. warn("Request for user's plugins returned an error: %s", json_string_value(errorJ));
  409. return false;
  410. }
  411. // Get community manifests
  412. json_t *manifestsResJ = requestJson(METHOD_GET, global_ui->app.gApiHost + "/community/manifests", NULL);
  413. if (!manifestsResJ) {
  414. warn("Request for community manifests failed");
  415. return false;
  416. }
  417. defer({
  418. json_decref(manifestsResJ);
  419. });
  420. // Check each plugin in list of plugin slugs
  421. json_t *pluginsJ = json_object_get(pluginsResJ, "plugins");
  422. if (!pluginsJ) {
  423. warn("No plugins array");
  424. return false;
  425. }
  426. json_t *manifestsJ = json_object_get(manifestsResJ, "manifests");
  427. if (!manifestsJ) {
  428. warn("No manifests object");
  429. return false;
  430. }
  431. size_t slugIndex;
  432. json_t *slugJ;
  433. json_array_foreach(pluginsJ, slugIndex, slugJ) {
  434. std::string slug = json_string_value(slugJ);
  435. // Search for slug in manifests
  436. const char *manifestSlug;
  437. json_t *manifestJ = NULL;
  438. json_object_foreach(manifestsJ, manifestSlug, manifestJ) {
  439. if (slug == std::string(manifestSlug))
  440. break;
  441. }
  442. if (!manifestJ)
  443. continue;
  444. if (syncPlugin(slug, manifestJ, dryRun)) {
  445. available = true;
  446. }
  447. }
  448. return available;
  449. #else
  450. return false;
  451. #endif // USE_VST2
  452. }
  453. void pluginLogIn(std::string email, std::string password) {
  454. #ifndef USE_VST2
  455. json_t *reqJ = json_object();
  456. json_object_set(reqJ, "email", json_string(email.c_str()));
  457. json_object_set(reqJ, "password", json_string(password.c_str()));
  458. json_t *resJ = requestJson(METHOD_POST, global_ui->app.gApiHost + "/token", reqJ);
  459. json_decref(reqJ);
  460. if (resJ) {
  461. json_t *errorJ = json_object_get(resJ, "error");
  462. if (errorJ) {
  463. const char *errorStr = json_string_value(errorJ);
  464. global->plugin.loginStatus = errorStr;
  465. }
  466. else {
  467. json_t *tokenJ = json_object_get(resJ, "token");
  468. if (tokenJ) {
  469. const char *tokenStr = json_string_value(tokenJ);
  470. global->plugin.gToken = tokenStr;
  471. global->plugin.loginStatus = "";
  472. }
  473. }
  474. json_decref(resJ);
  475. }
  476. #endif
  477. }
  478. void pluginLogOut() {
  479. global->plugin.gToken = "";
  480. }
  481. void pluginCancelDownload() {
  482. // TODO
  483. }
  484. bool pluginIsLoggedIn() {
  485. return global->plugin.gToken != "";
  486. }
  487. bool pluginIsDownloading() {
  488. return global->plugin.isDownloading;
  489. }
  490. float pluginGetDownloadProgress() {
  491. return global->plugin.downloadProgress;
  492. }
  493. std::string pluginGetDownloadName() {
  494. return global->plugin.downloadName;
  495. }
  496. std::string pluginGetLoginStatus() {
  497. return global->plugin.loginStatus;
  498. }
  499. Plugin *pluginGetPlugin(std::string pluginSlug) {
  500. for (Plugin *plugin : global->plugin.gPlugins) {
  501. // printf("xxx pluginGetPlugin: find pluginSlug=\"%s\" current=\"%s\"\n", pluginSlug.c_str(), plugin->slug.c_str());
  502. if (plugin->slug == pluginSlug) {
  503. return plugin;
  504. }
  505. }
  506. return NULL;
  507. }
  508. Model *pluginGetModel(std::string pluginSlug, std::string modelSlug) {
  509. Plugin *plugin = pluginGetPlugin(pluginSlug);
  510. // printf("xxx vstrack_plugin: plugSlug=\"%s\" modelSlug=\"%s\" => plugin=%p\n", pluginSlug.c_str(), modelSlug.c_str(), plugin);
  511. if (plugin) {
  512. for (Model *model : plugin->models) {
  513. if (model->slug == modelSlug) {
  514. // printf("xxx vstrack_plugin: plugSlug=\"%s\" modelSlug=\"%s\" => plugin=%p model=%p\n", pluginSlug.c_str(), modelSlug.c_str(), plugin, model);
  515. return model;
  516. }
  517. }
  518. }
  519. return NULL;
  520. }
  521. #ifdef USE_VST2
  522. #ifndef RACK_PLUGIN
  523. extern "C" {
  524. extern void init_plugin_Alikins (rack::Plugin *p);
  525. extern void init_plugin_AS (rack::Plugin *p);
  526. extern void init_plugin_AudibleInstruments (rack::Plugin *p);
  527. extern void init_plugin_BaconMusic (rack::Plugin *p);
  528. extern void init_plugin_Befaco (rack::Plugin *p);
  529. extern void init_plugin_Bidoo (rack::Plugin *p);
  530. extern void init_plugin_Bogaudio (rack::Plugin *p);
  531. // extern void init_plugin_BOKONTEPByteBeatMachine (rack::Plugin *p); // unstable
  532. extern void init_plugin_cf (rack::Plugin *p);
  533. //extern void init_plugin_dBiz (rack::Plugin *p); // now a DLL (13Jul2018)
  534. extern void init_plugin_DHE_Modules (rack::Plugin *p);
  535. extern void init_plugin_DrumKit (rack::Plugin *p);
  536. extern void init_plugin_ErraticInstruments (rack::Plugin *p);
  537. extern void init_plugin_ESeries (rack::Plugin *p);
  538. extern void init_plugin_FrozenWasteland (rack::Plugin *p);
  539. extern void init_plugin_Fundamental (rack::Plugin *p);
  540. extern void init_plugin_Gratrix (rack::Plugin *p);
  541. extern void init_plugin_HetrickCV (rack::Plugin *p);
  542. extern void init_plugin_huaba (rack::Plugin *p);
  543. extern void init_plugin_JW_Modules (rack::Plugin *p);
  544. extern void init_plugin_Koralfx (rack::Plugin *p);
  545. extern void init_plugin_LindenbergResearch (rack::Plugin *p);
  546. extern void init_plugin_LOGinstruments (rack::Plugin *p);
  547. extern void init_plugin_ML_modules (rack::Plugin *p);
  548. extern void init_plugin_moDllz (rack::Plugin *p);
  549. extern void init_plugin_modular80 (rack::Plugin *p);
  550. extern void init_plugin_mscHack (rack::Plugin *p);
  551. extern void init_plugin_mtsch_plugins (rack::Plugin *p);
  552. extern void init_plugin_NauModular (rack::Plugin *p);
  553. extern void init_plugin_Ohmer (rack::Plugin *p);
  554. // extern void init_plugin_ParableInstruments (rack::Plugin *p); // alternative "Clouds" module (crashes)
  555. extern void init_plugin_Qwelk (rack::Plugin *p);
  556. extern void init_plugin_RJModules (rack::Plugin *p);
  557. extern void init_plugin_SerialRacker (rack::Plugin *p);
  558. extern void init_plugin_SonusModular (rack::Plugin *p);
  559. extern void init_plugin_Southpole_parasites(rack::Plugin *p);
  560. extern void init_plugin_squinkylabs_plug1 (rack::Plugin *p);
  561. extern void init_plugin_SubmarineFree (rack::Plugin *p);
  562. extern void init_plugin_Template (rack::Plugin *p);
  563. extern void init_plugin_trowaSoft (rack::Plugin *p);
  564. extern void init_plugin_unless_modules (rack::Plugin *p);
  565. extern void init_plugin_Valley (rack::Plugin *p);
  566. // extern void init_plugin_VultModules (rack::Plugin *p);
  567. }
  568. static void vst2_load_static_rack_plugin(const char *_name, InitCallback _initCallback) {
  569. std::string path = assetStaticPlugin(_name);
  570. // Construct and initialize Plugin instance
  571. Plugin *plugin = new Plugin();
  572. plugin->path = path;
  573. plugin->handle = NULL;
  574. _initCallback(plugin);
  575. #if 0
  576. // Reject plugin if slug already exists
  577. Plugin *oldPlugin = pluginGetPlugin(plugin->slug);
  578. if (oldPlugin) {
  579. warn("Plugin \"%s\" is already loaded, not attempting to load it again", plugin->slug.c_str());
  580. // TODO
  581. // Fix memory leak with `plugin` here
  582. return false;
  583. }
  584. #endif
  585. // Add plugin to list
  586. global->plugin.gPlugins.push_back(plugin);
  587. info("vcvrack: Loaded static plugin %s %s", plugin->slug.c_str(), plugin->version.c_str());
  588. }
  589. void vst2_load_static_rack_plugins(void) {
  590. vst2_load_static_rack_plugin("Alikins", &init_plugin_Alikins);
  591. vst2_load_static_rack_plugin("AS", &init_plugin_AS);
  592. vst2_load_static_rack_plugin("AudibleInstruments", &init_plugin_AudibleInstruments);
  593. vst2_load_static_rack_plugin("BaconMusic", &init_plugin_BaconMusic);
  594. vst2_load_static_rack_plugin("Befaco", &init_plugin_Befaco);
  595. vst2_load_static_rack_plugin("Bidoo", &init_plugin_Bidoo);
  596. vst2_load_static_rack_plugin("Bogaudio", &init_plugin_Bogaudio);
  597. // vst2_load_static_rack_plugin("BOKONTEPByteBeatMachine", &init_plugin_BOKONTEPByteBeatMachine);
  598. vst2_load_static_rack_plugin("cf", &init_plugin_cf);
  599. // vst2_load_static_rack_plugin("dBiz", &init_plugin_dBiz); // now a DLL (13Jul2018)
  600. vst2_load_static_rack_plugin("DHE-Modules", &init_plugin_DHE_Modules);
  601. vst2_load_static_rack_plugin("DrumKit", &init_plugin_DrumKit);
  602. vst2_load_static_rack_plugin("ErraticInstruments", &init_plugin_ErraticInstruments);
  603. vst2_load_static_rack_plugin("ESeries", &init_plugin_ESeries);
  604. vst2_load_static_rack_plugin("FrozenWasteland", &init_plugin_FrozenWasteland);
  605. vst2_load_static_rack_plugin("Fundamental", &init_plugin_Fundamental);
  606. vst2_load_static_rack_plugin("Gratrix", &init_plugin_Gratrix);
  607. vst2_load_static_rack_plugin("HetrickCV", &init_plugin_HetrickCV);
  608. vst2_load_static_rack_plugin("huaba", &init_plugin_huaba);
  609. vst2_load_static_rack_plugin("JW_Modules", &init_plugin_JW_Modules);
  610. vst2_load_static_rack_plugin("Koralfx-Modules", &init_plugin_Koralfx);
  611. vst2_load_static_rack_plugin("LindenbergResearch", &init_plugin_LindenbergResearch);
  612. vst2_load_static_rack_plugin("LOGinstruments", &init_plugin_LOGinstruments);
  613. vst2_load_static_rack_plugin("ML_modules", &init_plugin_ML_modules);
  614. vst2_load_static_rack_plugin("moDllz", &init_plugin_moDllz);
  615. vst2_load_static_rack_plugin("modular80", &init_plugin_modular80);
  616. vst2_load_static_rack_plugin("mscHack", &init_plugin_mscHack);
  617. vst2_load_static_rack_plugin("mtsch_plugins", &init_plugin_mtsch_plugins);
  618. vst2_load_static_rack_plugin("NauModular", &init_plugin_NauModular);
  619. vst2_load_static_rack_plugin("Ohmer", &init_plugin_Ohmer);
  620. // vst2_load_static_rack_plugin("ParableInstruments", &init_plugin_ParableInstruments);
  621. vst2_load_static_rack_plugin("Qwelk", &init_plugin_Qwelk);
  622. vst2_load_static_rack_plugin("RJModules", &init_plugin_RJModules);
  623. vst2_load_static_rack_plugin("SerialRacker", &init_plugin_SerialRacker);
  624. vst2_load_static_rack_plugin("SonusModular", &init_plugin_SonusModular);
  625. vst2_load_static_rack_plugin("Southpole_parasites",&init_plugin_Southpole_parasites);
  626. vst2_load_static_rack_plugin("squinkylabs-plug1", &init_plugin_squinkylabs_plug1);
  627. vst2_load_static_rack_plugin("SubmarineFree", &init_plugin_SubmarineFree);
  628. vst2_load_static_rack_plugin("Template", &init_plugin_Template);
  629. vst2_load_static_rack_plugin("trowaSoft", &init_plugin_trowaSoft);
  630. vst2_load_static_rack_plugin("unless_modules", &init_plugin_unless_modules);
  631. vst2_load_static_rack_plugin("Valley", &init_plugin_Valley);
  632. // vst2_load_static_rack_plugin("VultModules", &init_plugin_VultModules);
  633. }
  634. #endif // RACK_PLUGIN
  635. #endif // USE_VST2
  636. } // namespace rack
  637. using namespace rack;
  638. #ifdef USE_VST2
  639. #ifdef ARCH_WIN
  640. extern "C" extern long seed_initialized;
  641. #else
  642. extern "C" extern volatile char seed_initialized;
  643. #endif // ARCH_WIN
  644. extern "C" extern volatile uint32_t hashtable_seed;
  645. void vst2_set_shared_plugin_tls_globals(void) {
  646. // Called in audio thread (see vst2_main.cpp:VSTPluginProcessReplacingFloat32())
  647. for(Plugin *p : global->plugin.gPlugins) {
  648. if(NULL != p->set_tls_globals_fxn) {
  649. // printf("xxx vcvrack: calling p->set_tls_globals_fxn() global=%p\n", p->global);
  650. p->json.hashtable_seed = hashtable_seed;
  651. p->json.seed_initialized = seed_initialized;
  652. p->set_tls_globals_fxn(p);
  653. // printf("xxx vcvrack: calling p->set_tls_globals_fxn() OK\n");
  654. }
  655. }
  656. }
  657. #endif // USE_VST2
  658. RackScene *rack_plugin_ui_get_rackscene(void) {
  659. #ifdef USE_VST2
  660. return rack::global_ui->app.gRackScene;
  661. #else
  662. return gRackScene;
  663. #endif // USE_VST2
  664. }
  665. RackWidget *rack_plugin_ui_get_rackwidget(void) {
  666. #ifdef USE_VST2
  667. return rack::global_ui->app.gRackWidget;
  668. #else
  669. return gRackWidget;
  670. #endif // USE_VST2
  671. }
  672. Toolbar *rack_plugin_ui_get_toolbar(void) {
  673. #ifdef USE_VST2
  674. return rack::global_ui->app.gToolbar;
  675. #else
  676. return gToolbar;
  677. #endif // USE_VST2
  678. }
  679. Widget *rack_plugin_ui_get_hovered_widget(void) {
  680. #ifdef USE_VST2
  681. return rack::global_ui->widgets.gHoveredWidget;
  682. #else
  683. return gHoveredWidget;
  684. #endif // USE_VST2
  685. }
  686. Widget *rack_plugin_ui_get_dragged_widget(void) {
  687. #ifdef USE_VST2
  688. return rack::global_ui->widgets.gDraggedWidget;
  689. #else
  690. return gDraggedWidget;
  691. #endif // USE_VST2
  692. }
  693. void rack_plugin_ui_set_dragged_widget(Widget *w) {
  694. #ifdef USE_VST2
  695. rack::global_ui->widgets.gDraggedWidget = w;
  696. #else
  697. gDraggedWidget = w;
  698. #endif // USE_VST2
  699. }
  700. Widget *rack_plugin_ui_get_draghovered_widget(void) {
  701. #ifdef USE_VST2
  702. return rack::global_ui->widgets.gDragHoveredWidget;
  703. #else
  704. return gDragHovered;
  705. #endif // USE_VST2
  706. }
  707. Widget *rack_plugin_ui_get_focused_widget(void) {
  708. #ifdef USE_VST2
  709. return rack::global_ui->widgets.gFocusedWidget;
  710. #else
  711. return gFocusedWidget;
  712. #endif // USE_VST2
  713. }
  714. void rack_plugin_ui_set_focused_widget(Widget *w) {
  715. #ifdef USE_VST2
  716. rack::global_ui->widgets.gFocusedWidget = w;
  717. #else
  718. gFocusedWidget = w;
  719. #endif // USE_VST2
  720. }