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.

869 lines
27KB

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