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.

190 lines
4.5KB

  1. #include "app/Scene.hpp"
  2. #include "app/ModuleBrowser.hpp"
  3. #include "app.hpp"
  4. #include "system.hpp"
  5. #include "network.hpp"
  6. #include "history.hpp"
  7. #include "settings.hpp"
  8. #include "patch.hpp"
  9. #include "asset.hpp"
  10. #include "osdialog.h"
  11. #include <thread>
  12. namespace rack {
  13. namespace app {
  14. Scene::Scene() {
  15. rackScroll = new RackScrollWidget;
  16. addChild(rackScroll);
  17. rack = rackScroll->rackWidget;
  18. toolbar = new Toolbar;
  19. addChild(toolbar);
  20. rackScroll->box.pos.y = toolbar->box.size.y;
  21. moduleBrowser = moduleBrowserCreate();
  22. moduleBrowser->hide();
  23. addChild(moduleBrowser);
  24. }
  25. Scene::~Scene() {
  26. }
  27. void Scene::step() {
  28. // Resize owned descendants
  29. toolbar->box.size.x = box.size.x;
  30. rackScroll->box.size = box.size.minus(rackScroll->box.pos);
  31. // Autosave every 15 seconds
  32. double time = glfwGetTime();
  33. if (time - lastAutoSaveTime >= 15.0) {
  34. lastAutoSaveTime = time;
  35. APP->patch->save(asset::user("autosave.vcv"));
  36. settings::save(asset::user("settings.json"));
  37. }
  38. // Request latest version from server
  39. if (!settings::devMode && checkVersion && !checkedVersion) {
  40. std::thread t(&Scene::runCheckVersion, this);
  41. t.detach();
  42. checkedVersion = true;
  43. }
  44. // Version popup message
  45. if (!latestVersion.empty()) {
  46. std::string versionMessage = string::f("Rack v%s is available.\n\nYou have Rack v%s.\n\nClose Rack and download new version on the website?", latestVersion.c_str(), app::APP_VERSION);
  47. if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, versionMessage.c_str())) {
  48. std::thread t(system::openBrowser, "https://vcvrack.com/");
  49. t.detach();
  50. APP->window->close();
  51. }
  52. latestVersion = "";
  53. }
  54. Widget::step();
  55. }
  56. void Scene::draw(const DrawArgs &args) {
  57. Widget::draw(args);
  58. }
  59. void Scene::onHoverKey(const event::HoverKey &e) {
  60. OpaqueWidget::onHoverKey(e);
  61. if (e.isConsumed())
  62. return;
  63. if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
  64. switch (e.key) {
  65. case GLFW_KEY_N: {
  66. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  67. APP->patch->resetDialog();
  68. e.consume(this);
  69. }
  70. } break;
  71. case GLFW_KEY_Q: {
  72. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  73. APP->window->close();
  74. e.consume(this);
  75. }
  76. } break;
  77. case GLFW_KEY_O: {
  78. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  79. APP->patch->loadDialog();
  80. e.consume(this);
  81. }
  82. if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  83. APP->patch->revertDialog();
  84. e.consume(this);
  85. }
  86. } break;
  87. case GLFW_KEY_S: {
  88. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  89. APP->patch->saveDialog();
  90. e.consume(this);
  91. }
  92. if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  93. APP->patch->saveAsDialog();
  94. e.consume(this);
  95. }
  96. } break;
  97. case GLFW_KEY_Z: {
  98. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  99. APP->history->undo();
  100. e.consume(this);
  101. }
  102. if ((e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
  103. APP->history->redo();
  104. e.consume(this);
  105. }
  106. } break;
  107. case GLFW_KEY_MINUS: {
  108. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  109. float z = std::log2(settings::zoom);
  110. z *= 2;
  111. z = std::ceil(z - 0.01) - 1;
  112. z /= 2;
  113. settings::zoom = std::pow(2, z);
  114. e.consume(this);
  115. }
  116. } break;
  117. case GLFW_KEY_EQUAL: {
  118. if ((e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
  119. float z = std::log2(settings::zoom);
  120. z *= 2;
  121. z = std::floor(z + 0.01) + 1;
  122. z /= 2;
  123. settings::zoom = std::pow(2, z);
  124. e.consume(this);
  125. }
  126. } break;
  127. case GLFW_KEY_ENTER:
  128. case GLFW_KEY_KP_ENTER: {
  129. moduleBrowser->show();
  130. e.consume(this);
  131. } break;
  132. case GLFW_KEY_F11: {
  133. APP->window->setFullScreen(!APP->window->isFullScreen());
  134. e.consume(this);
  135. }
  136. }
  137. }
  138. }
  139. void Scene::onPathDrop(const event::PathDrop &e) {
  140. OpaqueWidget::onPathDrop(e);
  141. if (e.isConsumed())
  142. return;
  143. if (e.paths.size() >= 1) {
  144. const std::string &path = e.paths[0];
  145. if (string::filenameExtension(string::filename(path)) == "vcv") {
  146. APP->patch->load(path);
  147. e.consume(this);
  148. }
  149. }
  150. }
  151. void Scene::runCheckVersion() {
  152. std::string versionUrl = app::API_URL;
  153. versionUrl += "/version";
  154. json_t *versionResJ = network::requestJson(network::METHOD_GET, versionUrl, NULL);
  155. if (versionResJ) {
  156. json_t *versionJ = json_object_get(versionResJ, "version");
  157. if (versionJ) {
  158. std::string version = json_string_value(versionJ);
  159. if (version != app::APP_VERSION) {
  160. latestVersion = version;
  161. }
  162. }
  163. json_decref(versionResJ);
  164. }
  165. }
  166. } // namespace app
  167. } // namespace rack