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.

531 lines
15KB

  1. #include "global_pre.hpp"
  2. #include "app.hpp"
  3. #include "engine.hpp"
  4. #include "plugin.hpp"
  5. #include "window.hpp"
  6. #include "global.hpp"
  7. #include "global_ui.hpp"
  8. #ifdef USE_VST2
  9. // // extern "C" void glfw_hack_makeContextCurrent(GLFWwindow *handle);
  10. // #include <windows.h>
  11. #endif // USE_VST2
  12. namespace rack {
  13. ModuleWidget::ModuleWidget(Module *module) {
  14. // printf("xxx ModuleWidget::ModuleWidget(module=%p) global=%p\n", module, global);
  15. // printf("xxx ModuleWidget::ModuleWidget: GetCurrentThreadId=%d\n", GetCurrentThreadId());
  16. if (module) {
  17. engineAddModule(module);
  18. // printf("xxx ModuleWidget::ModuleWidget: engineAddModule OK\n");
  19. }
  20. this->module = module;
  21. // printf("xxx ModuleWidget::ModuleWidget(): bind GL context global_ui->window.gWindow=%p\n", global_ui->window.gWindow);
  22. // glfwMakeContextCurrent(global_ui->window.gWindow);
  23. // // glfw_hack_makeContextCurrent(global_ui->window.gWindow);
  24. // printf("xxx ModuleWidget::ModuleWidget(): RETURN\n");
  25. }
  26. ModuleWidget::~ModuleWidget() {
  27. // Make sure WireWidget destructors are called *before* removing `module` from the rack.
  28. disconnect();
  29. // Remove and delete the Module instance
  30. if (module) {
  31. engineRemoveModule(module);
  32. delete module;
  33. module = NULL;
  34. }
  35. }
  36. void ModuleWidget::setModule__deprecated__(Module *module) {
  37. if (module) {
  38. engineAddModule(module);
  39. }
  40. this->module = module;
  41. }
  42. void ModuleWidget::addInput(Port *input) {
  43. assert(input->type == Port::INPUT);
  44. inputs.push_back(input);
  45. addChild(input);
  46. }
  47. void ModuleWidget::addOutput(Port *output) {
  48. assert(output->type == Port::OUTPUT);
  49. outputs.push_back(output);
  50. addChild(output);
  51. }
  52. void ModuleWidget::addParam(ParamWidget *param) {
  53. params.push_back(param);
  54. addChild(param);
  55. }
  56. void ModuleWidget::setPanel(std::shared_ptr<SVG> svg) {
  57. // Remove old panel
  58. // #ifdef RACK_PLUGIN_SHARED
  59. // printf("xxx ModuleWidget::setPanel<shared>: 1\n");
  60. // #else
  61. // printf("xxx ModuleWidget::setPanel<host>: 1\n");
  62. // #endif
  63. if (panel) {
  64. removeChild(panel);
  65. delete panel;
  66. panel = NULL;
  67. }
  68. // printf("xxx ModuleWidget::setPanel: 2\n");
  69. panel = new SVGPanel();
  70. // printf("xxx ModuleWidget::setPanel: 3\n");
  71. panel->setBackground(svg);
  72. // printf("xxx ModuleWidget::setPanel: 4\n");
  73. addChild(panel);
  74. // printf("xxx ModuleWidget::setPanel: 5\n");
  75. box.size = panel->box.size;
  76. // printf("xxx ModuleWidget::setPanel: 6\n");
  77. }
  78. json_t *ModuleWidget::toJson() {
  79. json_t *rootJ = json_object();
  80. // plugin
  81. json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str()));
  82. // version (of plugin)
  83. if (!model->plugin->version.empty())
  84. json_object_set_new(rootJ, "version", json_string(model->plugin->version.c_str()));
  85. #ifdef USE_VST2
  86. json_t *vst2_unique_param_base_idJ = json_integer(module->vst2_unique_param_base_id);
  87. json_object_set_new(rootJ, "vst2_unique_param_base_id", vst2_unique_param_base_idJ);
  88. #endif // USE_VST2
  89. // model
  90. json_object_set_new(rootJ, "model", json_string(model->slug.c_str()));
  91. // pos
  92. Vec pos = box.pos.div(RACK_GRID_SIZE).round();
  93. json_t *posJ = json_pack("[i, i]", (int) pos.x, (int) pos.y);
  94. json_object_set_new(rootJ, "pos", posJ);
  95. // params
  96. json_t *paramsJ = json_array();
  97. for (ParamWidget *paramWidget : params) {
  98. json_t *paramJ = paramWidget->toJson();
  99. json_array_append_new(paramsJ, paramJ);
  100. }
  101. json_object_set_new(rootJ, "params", paramsJ);
  102. // data
  103. if (module) {
  104. json_t *dataJ = module->toJson();
  105. if (dataJ) {
  106. json_object_set_new(rootJ, "data", dataJ);
  107. }
  108. }
  109. return rootJ;
  110. }
  111. void ModuleWidget::fromJson(json_t *rootJ) {
  112. // legacy
  113. int legacy = 0;
  114. json_t *legacyJ = json_object_get(rootJ, "legacy");
  115. if (legacyJ)
  116. legacy = json_integer_value(legacyJ);
  117. #ifdef USE_VST2
  118. if(global_ui->app.bLoadVSTUniqueParamBaseId) {
  119. if(NULL != module) {
  120. json_t *vst2_unique_param_base_idJ = json_object_get(rootJ, "vst2_unique_param_base_id");
  121. if (vst2_unique_param_base_idJ) {
  122. module->vst2_unique_param_base_id = json_integer_value(vst2_unique_param_base_idJ);
  123. if((module->vst2_unique_param_base_id + module->params.size()) > global->vst2.next_unique_param_base_id) {
  124. global->vst2.next_unique_param_base_id = (module->vst2_unique_param_base_id + module->params.size());
  125. }
  126. }
  127. }
  128. }
  129. #endif // USE_VST2
  130. // pos
  131. json_t *posJ = json_object_get(rootJ, "pos");
  132. double x, y;
  133. json_unpack(posJ, "[F, F]", &x, &y);
  134. Vec pos = Vec(x, y);
  135. // printf("xxx ModuleWidget::fromJson: pos=(%f, %f) posJ=%p rootJ=%p\n", x, y, posJ, rootJ);
  136. if (legacy && legacy <= 1) {
  137. box.pos = pos;
  138. }
  139. else {
  140. box.pos = pos.mult(RACK_GRID_SIZE);
  141. }
  142. // params
  143. json_t *paramsJ = json_object_get(rootJ, "params");
  144. size_t i;
  145. json_t *paramJ;
  146. json_array_foreach(paramsJ, i, paramJ) {
  147. if (legacy && legacy <= 1) {
  148. // Legacy 1 mode
  149. // The index in the array we're iterating is the index of the ParamWidget in the params vector.
  150. if (i < params.size()) {
  151. // Create upgraded version of param JSON object
  152. json_t *newParamJ = json_object();
  153. json_object_set(newParamJ, "value", paramJ);
  154. params[i]->fromJson(newParamJ);
  155. json_decref(newParamJ);
  156. }
  157. }
  158. else {
  159. // Get paramId
  160. json_t *paramIdJ = json_object_get(paramJ, "paramId");
  161. if (!paramIdJ)
  162. continue;
  163. int paramId = json_integer_value(paramIdJ);
  164. // Find ParamWidget(s) with paramId
  165. for (ParamWidget *paramWidget : params) {
  166. if (paramWidget->paramId == paramId)
  167. paramWidget->fromJson(paramJ);
  168. }
  169. }
  170. }
  171. // data
  172. json_t *dataJ = json_object_get(rootJ, "data");
  173. if (dataJ && module) {
  174. module->fromJson(dataJ);
  175. }
  176. }
  177. void ModuleWidget::disconnect() {
  178. for (Port *input : inputs) {
  179. global_ui->app.gRackWidget->wireContainer->removeAllWires(input);
  180. }
  181. for (Port *output : outputs) {
  182. global_ui->app.gRackWidget->wireContainer->removeAllWires(output);
  183. }
  184. }
  185. void ModuleWidget::create() {
  186. }
  187. void ModuleWidget::_delete() {
  188. }
  189. void ModuleWidget::reset() {
  190. for (ParamWidget *param : params) {
  191. param->reset();
  192. }
  193. if (module) {
  194. module->onReset();
  195. }
  196. }
  197. void ModuleWidget::randomize() {
  198. for (ParamWidget *param : params) {
  199. param->randomize();
  200. }
  201. if (module) {
  202. module->onRandomize();
  203. }
  204. }
  205. ParamWidget *ModuleWidget::findParamWidgetByParamId(int _paramId) {
  206. for (ParamWidget *param : params) {
  207. if(param->paramId == _paramId)
  208. return param;
  209. }
  210. return NULL;
  211. }
  212. void ModuleWidget::draw(NVGcontext *vg) {
  213. // printf("xxx ModuleWidget::draw: ENTER this=%p global=%p global_ui=%p\n", this, global, global_ui);
  214. nvgScissor(vg, 0, 0, box.size.x, box.size.y);
  215. // printf("xxx ModuleWidget::draw: 2\n");
  216. Widget::draw(vg);
  217. // printf("xxx ModuleWidget::draw: 3\n");
  218. // CPU meter
  219. if (module && global->gPowerMeter) {
  220. // printf("xxx ModuleWidget::draw: 4b\n");
  221. nvgBeginPath(vg);
  222. // printf("xxx ModuleWidget::draw: 5b\n");
  223. nvgRect(vg,
  224. 0, box.size.y - 20,
  225. 55, 20);
  226. nvgFillColor(vg, nvgRGBAf(0, 0, 0, 0.5));
  227. nvgFill(vg);
  228. // printf("xxx ModuleWidget::draw: 6b module=%p\n", module);
  229. std::string cpuText = stringf("%.0f mS", module->cpuTime * 1000.f);
  230. // printf("xxx ModuleWidget::draw: 7b\n");
  231. nvgFontFaceId(vg, global_ui->window.gGuiFont->handle);
  232. nvgFontSize(vg, 12);
  233. nvgFillColor(vg, nvgRGBf(1, 1, 1));
  234. nvgText(vg, 10.0, box.size.y - 6.0, cpuText.c_str(), NULL);
  235. // printf("xxx ModuleWidget::draw: 8b\n");
  236. float p = clamp(module->cpuTime, 0.f, 1.f);
  237. nvgBeginPath(vg);
  238. nvgRect(vg,
  239. 0, (1.f - p) * box.size.y,
  240. 5, p * box.size.y);
  241. nvgFillColor(vg, nvgRGBAf(1, 0, 0, 1.0));
  242. nvgFill(vg);
  243. }
  244. // printf("xxx ModuleWidget::draw: 4\n");
  245. nvgResetScissor(vg);
  246. // printf("xxx ModuleWidget::draw: LEAVE\n");
  247. }
  248. void ModuleWidget::drawShadow(NVGcontext *vg) {
  249. nvgBeginPath(vg);
  250. float r = 20; // Blur radius
  251. float c = 20; // Corner radius
  252. Vec b = Vec(-10, 30); // Offset from each corner
  253. nvgRect(vg, b.x - r, b.y - r, box.size.x - 2*b.x + 2*r, box.size.y - 2*b.y + 2*r);
  254. NVGcolor shadowColor = nvgRGBAf(0, 0, 0, 0.2);
  255. NVGcolor transparentColor = nvgRGBAf(0, 0, 0, 0);
  256. nvgFillPaint(vg, nvgBoxGradient(vg, b.x, b.y, box.size.x - 2*b.x, box.size.y - 2*b.y, c, r, shadowColor, transparentColor));
  257. nvgFill(vg);
  258. }
  259. void ModuleWidget::onMouseDown(EventMouseDown &e) {
  260. Widget::onMouseDown(e);
  261. if (e.consumed)
  262. return;
  263. if (e.button == 1) {
  264. createContextMenu();
  265. }
  266. e.consumed = true;
  267. e.target = this;
  268. }
  269. void ModuleWidget::onMouseMove(EventMouseMove &e) {
  270. OpaqueWidget::onMouseMove(e);
  271. // // #if 0
  272. // // // Don't delete the ModuleWidget if a TextField is focused
  273. // // if (!global_ui->widgets.gFocusedWidget) {
  274. // // // Instead of checking key-down events, delete the module even if key-repeat hasn't fired yet and the cursor is hovering over the widget.
  275. // // if (glfwGetKey(global_ui->window.gWindow, GLFW_KEY_DELETE) == GLFW_PRESS || glfwGetKey(global_ui->window.gWindow, GLFW_KEY_BACKSPACE) == GLFW_PRESS) {
  276. // // if (!windowIsModPressed() && !windowIsShiftPressed()) {
  277. // // global_ui->app.gRackWidget->deleteModule(this);
  278. // // this->finalizeEvents();
  279. // // delete this;
  280. // // e.consumed = true;
  281. // // return;
  282. // // }
  283. // // }
  284. // // }
  285. // // #endif
  286. }
  287. void ModuleWidget::onHoverKey(EventHoverKey &e) {
  288. switch (e.key) {
  289. case 'i':
  290. if (windowIsModPressed() && !windowIsShiftPressed()) {
  291. reset();
  292. e.consumed = true;
  293. return;
  294. }
  295. break;
  296. case 'r':
  297. if (windowIsModPressed() && !windowIsShiftPressed()) {
  298. randomize();
  299. e.consumed = true;
  300. return;
  301. }
  302. break;
  303. case 'd':
  304. if (windowIsModPressed() && !windowIsShiftPressed()) {
  305. global_ui->app.gRackWidget->cloneModule(this);
  306. e.consumed = true;
  307. return;
  308. }
  309. break;
  310. case 'u':
  311. if (windowIsModPressed() && !windowIsShiftPressed()) {
  312. disconnect();
  313. e.consumed = true;
  314. return;
  315. }
  316. break;
  317. case LGLW_VKEY_DELETE:
  318. case LGLW_VKEY_BACKSPACE:
  319. if (!global_ui->widgets.gFocusedWidget) {
  320. if (!windowIsModPressed() && !windowIsShiftPressed()) {
  321. global_ui->app.gRackWidget->deleteModule(this);
  322. this->finalizeEvents();
  323. delete this;
  324. e.consumed = true;
  325. return;
  326. }
  327. }
  328. break;
  329. case 'w':
  330. if (windowIsModPressed() && !windowIsShiftPressed()) {
  331. global_ui->param_info.value_clipboard = global_ui->param_info.last_param_value;
  332. printf("xxx CopyParamItem: value=%f\n", global_ui->param_info.value_clipboard);
  333. e.consumed = true;
  334. return;
  335. }
  336. break;
  337. case 'e':
  338. if (windowIsModPressed() && !windowIsShiftPressed()) {
  339. vst2_queue_param_sync(global_ui->param_info.last_param_gid,
  340. global_ui->param_info.value_clipboard,
  341. false/*bNormalized*/
  342. );
  343. printf("xxx PasteParamItem: value=%f\n", global_ui->param_info.value_clipboard);
  344. e.consumed = true;
  345. return;
  346. }
  347. break;
  348. }
  349. Widget::onHoverKey(e);
  350. }
  351. void ModuleWidget::onDragStart(EventDragStart &e) {
  352. dragPos = global_ui->app.gRackWidget->lastMousePos.minus(box.pos);
  353. }
  354. void ModuleWidget::onDragEnd(EventDragEnd &e) {
  355. }
  356. void ModuleWidget::onDragMove(EventDragMove &e) {
  357. if (!global_ui->app.gRackWidget->lockModules) {
  358. Rect newBox = box;
  359. newBox.pos = global_ui->app.gRackWidget->lastMousePos.minus(dragPos);
  360. global_ui->app.gRackWidget->requestModuleBoxNearest(this, newBox);
  361. }
  362. }
  363. struct DisconnectMenuItem : MenuItem {
  364. ModuleWidget *moduleWidget;
  365. void onAction(EventAction &e) override {
  366. moduleWidget->disconnect();
  367. }
  368. };
  369. struct ResetMenuItem : MenuItem {
  370. ModuleWidget *moduleWidget;
  371. void onAction(EventAction &e) override {
  372. moduleWidget->reset();
  373. }
  374. };
  375. struct RandomizeMenuItem : MenuItem {
  376. ModuleWidget *moduleWidget;
  377. void onAction(EventAction &e) override {
  378. moduleWidget->randomize();
  379. }
  380. };
  381. struct CloneMenuItem : MenuItem {
  382. ModuleWidget *moduleWidget;
  383. void onAction(EventAction &e) override {
  384. global_ui->app.gRackWidget->cloneModule(moduleWidget);
  385. }
  386. };
  387. struct DeleteMenuItem : MenuItem {
  388. ModuleWidget *moduleWidget;
  389. void onAction(EventAction &e) override {
  390. global_ui->app.gRackWidget->deleteModule(moduleWidget);
  391. moduleWidget->finalizeEvents();
  392. delete moduleWidget;
  393. }
  394. };
  395. struct CopyParamItem : MenuItem {
  396. void onAction(EventAction &e) override {
  397. global_ui->param_info.value_clipboard = global_ui->param_info.last_param_value;
  398. printf("xxx CopyParamItem: value=%f\n", global_ui->param_info.value_clipboard);
  399. }
  400. };
  401. struct PasteParamItem : MenuItem {
  402. void onAction(EventAction &e) override {
  403. vst2_queue_param_sync(global_ui->param_info.last_param_gid,
  404. global_ui->param_info.value_clipboard,
  405. false/*bNormalized*/
  406. );
  407. printf("xxx PasteParamItem: value=%f\n", global_ui->param_info.value_clipboard);
  408. }
  409. };
  410. Menu *ModuleWidget::createContextMenu() {
  411. // printf("xxx ModuleWidget::createContextMenu: ENTER\n");
  412. Menu *menu = global_ui->ui.gScene->createMenu();
  413. MenuLabel *menuLabel = new MenuLabel();
  414. // printf("xxx ModuleWidget::createContextMenu: model->author=\"%s\"\n", model->author.c_str());
  415. // printf("xxx ModuleWidget::createContextMenu: model->name=\"%s\"\n", model->name.c_str());
  416. menuLabel->text = model->author + " " + model->name + " " + model->plugin->version;
  417. menu->addChild(menuLabel);
  418. ResetMenuItem *resetItem = new ResetMenuItem();
  419. resetItem->text = "Initialize";
  420. resetItem->rightText = WINDOW_MOD_KEY_NAME "+I";
  421. resetItem->moduleWidget = this;
  422. menu->addChild(resetItem);
  423. RandomizeMenuItem *randomizeItem = new RandomizeMenuItem();
  424. randomizeItem->text = "Randomize";
  425. randomizeItem->rightText = WINDOW_MOD_KEY_NAME "+R";
  426. randomizeItem->moduleWidget = this;
  427. menu->addChild(randomizeItem);
  428. DisconnectMenuItem *disconnectItem = new DisconnectMenuItem();
  429. disconnectItem->text = "Disconnect cables";
  430. disconnectItem->rightText = WINDOW_MOD_KEY_NAME "+U";
  431. disconnectItem->moduleWidget = this;
  432. menu->addChild(disconnectItem);
  433. CloneMenuItem *cloneItem = new CloneMenuItem();
  434. cloneItem->text = "Duplicate";
  435. cloneItem->rightText = WINDOW_MOD_KEY_NAME "+D";
  436. cloneItem->moduleWidget = this;
  437. menu->addChild(cloneItem);
  438. DeleteMenuItem *deleteItem = new DeleteMenuItem();
  439. deleteItem->text = "Delete";
  440. deleteItem->rightText = "Backspace/Delete";
  441. deleteItem->moduleWidget = this;
  442. menu->addChild(deleteItem);
  443. CopyParamItem *copyParamItem = new CopyParamItem();
  444. copyParamItem->text = "Copy Param Value";
  445. copyParamItem->rightText = WINDOW_MOD_KEY_NAME "+W";
  446. menu->addChild(copyParamItem);
  447. PasteParamItem *pasteParamItem = new PasteParamItem();
  448. pasteParamItem->text = "Paste Param Value";
  449. pasteParamItem->rightText = WINDOW_MOD_KEY_NAME "+E";
  450. menu->addChild(pasteParamItem);
  451. appendContextMenu(menu);
  452. return menu;
  453. }
  454. } // namespace rack