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.

233 lines
6.3KB

  1. #include <settings.hpp>
  2. #include <window.hpp>
  3. #include <plugin.hpp>
  4. #include <app/Scene.hpp>
  5. #include <app/ModuleBrowser.hpp>
  6. #include <engine/Engine.hpp>
  7. #include <app.hpp>
  8. #include <patch.hpp>
  9. #include <jansson.h>
  10. namespace rack {
  11. namespace settings {
  12. bool devMode = false;
  13. bool headless = false;
  14. std::string token;
  15. math::Vec windowSize;
  16. math::Vec windowPos;
  17. float zoom = 0.0;
  18. bool invertZoom = false;
  19. float cableOpacity = 0.5;
  20. float cableTension = 0.5;
  21. bool allowCursorLock = true;
  22. bool realTime = false;
  23. float sampleRate = 44100.0;
  24. int threadCount = 1;
  25. bool paramTooltip = false;
  26. bool cpuMeter = false;
  27. bool lockModules = false;
  28. float frameRateLimit = 70.0;
  29. bool frameRateSync = true;
  30. float autosavePeriod = 15.0;
  31. bool skipLoadOnLaunch = false;
  32. std::string patchPath;
  33. std::vector<NVGcolor> cableColors = {
  34. nvgRGB(0xc9, 0xb7, 0x0e), // yellow
  35. nvgRGB(0x0c, 0x8e, 0x15), // green
  36. nvgRGB(0xc9, 0x18, 0x47), // red
  37. nvgRGB(0x09, 0x86, 0xad), // blue
  38. };
  39. json_t *toJson() {
  40. json_t *rootJ = json_object();
  41. json_object_set_new(rootJ, "token", json_string(token.c_str()));
  42. json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y);
  43. json_object_set_new(rootJ, "windowSize", windowSizeJ);
  44. json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y);
  45. json_object_set_new(rootJ, "windowPos", windowPosJ);
  46. json_object_set_new(rootJ, "zoom", json_real(zoom));
  47. json_object_set_new(rootJ, "invertZoom", json_boolean(invertZoom));
  48. json_object_set_new(rootJ, "cableOpacity", json_real(cableOpacity));
  49. json_object_set_new(rootJ, "cableTension", json_real(cableTension));
  50. json_object_set_new(rootJ, "allowCursorLock", json_boolean(allowCursorLock));
  51. json_object_set_new(rootJ, "realTime", json_boolean(realTime));
  52. json_object_set_new(rootJ, "sampleRate", json_real(sampleRate));
  53. json_object_set_new(rootJ, "threadCount", json_integer(threadCount));
  54. json_object_set_new(rootJ, "paramTooltip", json_boolean(paramTooltip));
  55. json_object_set_new(rootJ, "cpuMeter", json_boolean(cpuMeter));
  56. json_object_set_new(rootJ, "lockModules", json_boolean(lockModules));
  57. json_object_set_new(rootJ, "frameRateLimit", json_real(frameRateLimit));
  58. json_object_set_new(rootJ, "frameRateSync", json_boolean(frameRateSync));
  59. json_object_set_new(rootJ, "autosavePeriod", json_real(autosavePeriod));
  60. if (skipLoadOnLaunch) {
  61. json_object_set_new(rootJ, "skipLoadOnLaunch", json_true());
  62. }
  63. json_object_set_new(rootJ, "patchPath", json_string(patchPath.c_str()));
  64. json_t *cableColorsJ = json_array();
  65. for (NVGcolor cableColor : cableColors) {
  66. std::string colorStr = color::toHexString(cableColor);
  67. json_array_append_new(cableColorsJ, json_string(colorStr.c_str()));
  68. }
  69. json_object_set_new(rootJ, "cableColors", cableColorsJ);
  70. return rootJ;
  71. }
  72. void fromJson(json_t *rootJ) {
  73. json_t *tokenJ = json_object_get(rootJ, "token");
  74. if (tokenJ)
  75. token = json_string_value(tokenJ);
  76. json_t *windowSizeJ = json_object_get(rootJ, "windowSize");
  77. if (windowSizeJ) {
  78. double x, y;
  79. json_unpack(windowSizeJ, "[F, F]", &x, &y);
  80. windowSize = math::Vec(x, y);
  81. }
  82. json_t *windowPosJ = json_object_get(rootJ, "windowPos");
  83. if (windowPosJ) {
  84. double x, y;
  85. json_unpack(windowPosJ, "[F, F]", &x, &y);
  86. windowPos = math::Vec(x, y);
  87. }
  88. json_t *zoomJ = json_object_get(rootJ, "zoom");
  89. if (zoomJ)
  90. zoom = json_number_value(zoomJ);
  91. json_t *invertZoomJ = json_object_get(rootJ, "invertZoom");
  92. if (invertZoomJ)
  93. invertZoom = json_boolean_value(invertZoomJ);
  94. json_t *cableOpacityJ = json_object_get(rootJ, "cableOpacity");
  95. if (cableOpacityJ)
  96. cableOpacity = json_number_value(cableOpacityJ);
  97. json_t *tensionJ = json_object_get(rootJ, "cableTension");
  98. if (tensionJ)
  99. cableTension = json_number_value(tensionJ);
  100. json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock");
  101. if (allowCursorLockJ)
  102. allowCursorLock = json_is_true(allowCursorLockJ);
  103. json_t *realTimeJ = json_object_get(rootJ, "realTime");
  104. if (realTimeJ)
  105. realTime = json_boolean_value(realTimeJ);
  106. json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
  107. if (sampleRateJ)
  108. sampleRate = json_number_value(sampleRateJ);
  109. json_t *threadCountJ = json_object_get(rootJ, "threadCount");
  110. if (threadCountJ)
  111. threadCount = json_integer_value(threadCountJ);
  112. json_t *paramTooltipJ = json_object_get(rootJ, "paramTooltip");
  113. if (paramTooltipJ)
  114. paramTooltip = json_boolean_value(paramTooltipJ);
  115. json_t *cpuMeterJ = json_object_get(rootJ, "cpuMeter");
  116. if (cpuMeterJ)
  117. cpuMeter = json_boolean_value(cpuMeterJ);
  118. json_t *lockModulesJ = json_object_get(rootJ, "lockModules");
  119. if (lockModulesJ)
  120. lockModules = json_boolean_value(lockModulesJ);
  121. json_t *frameRateLimitJ = json_object_get(rootJ, "frameRateLimit");
  122. if (frameRateLimitJ)
  123. frameRateLimit = json_number_value(frameRateLimitJ);
  124. json_t *frameRateSyncJ = json_object_get(rootJ, "frameRateSync");
  125. if (frameRateSyncJ)
  126. frameRateSync = json_boolean_value(frameRateSyncJ);
  127. json_t *autosavePeriodJ = json_object_get(rootJ, "autosavePeriod");
  128. if (autosavePeriodJ)
  129. autosavePeriod = json_number_value(autosavePeriodJ);
  130. json_t *skipLoadOnLaunchJ = json_object_get(rootJ, "skipLoadOnLaunch");
  131. if (skipLoadOnLaunchJ)
  132. skipLoadOnLaunch = json_boolean_value(skipLoadOnLaunchJ);
  133. json_t *patchPathJ = json_object_get(rootJ, "patchPath");
  134. if (patchPathJ)
  135. patchPath = json_string_value(patchPathJ);
  136. json_t *cableColorsJ = json_object_get(rootJ, "cableColors");
  137. if (cableColorsJ) {
  138. cableColors.clear();
  139. size_t i;
  140. json_t *cableColorJ;
  141. json_array_foreach(cableColorsJ, i, cableColorJ) {
  142. std::string colorStr = json_string_value(cableColorJ);
  143. cableColors.push_back(color::fromHexString(colorStr));
  144. }
  145. }
  146. }
  147. void save(const std::string &path) {
  148. INFO("Saving settings %s", path.c_str());
  149. json_t *rootJ = toJson();
  150. if (!rootJ)
  151. return;
  152. FILE *file = fopen(path.c_str(), "w");
  153. if (!file)
  154. return;
  155. DEFER({
  156. fclose(file);
  157. });
  158. json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
  159. json_decref(rootJ);
  160. }
  161. void load(const std::string &path) {
  162. INFO("Loading settings %s", path.c_str());
  163. FILE *file = fopen(path.c_str(), "r");
  164. if (!file)
  165. return;
  166. DEFER({
  167. fclose(file);
  168. });
  169. json_error_t error;
  170. json_t *rootJ = json_loadf(file, 0, &error);
  171. if (!rootJ)
  172. throw UserException(string::f("Settings file has invalid JSON at %d:%d %s", error.line, error.column, error.text));
  173. fromJson(rootJ);
  174. json_decref(rootJ);
  175. }
  176. } // namespace settings
  177. } // namespace rack