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.

456 lines
13KB

  1. #include "global_pre.hpp"
  2. #include "settings.hpp"
  3. #include "app.hpp"
  4. #include "window.hpp"
  5. #include "engine.hpp"
  6. #include "plugin.hpp"
  7. #include <jansson.h>
  8. #include "global.hpp"
  9. #include "global_ui.hpp"
  10. #ifdef RACK_HOST
  11. extern void vst2_window_size_set (int _width, int _height);
  12. extern void vst2_refresh_rate_set (float _hz);
  13. extern float vst2_refresh_rate_get (void);
  14. extern void vst2_oversample_realtime_set (float _factor, int _quality);
  15. extern void vst2_oversample_realtime_get (float *_factor, int *_quality);
  16. extern void vst2_oversample_offline_set (float _factor, int _quality);
  17. extern void vst2_oversample_offline_get (float *_factor, int *_quality);
  18. extern void vst2_oversample_offline_check_set (int _bEnable);
  19. extern int32_t vst2_oversample_offline_check_get (void);
  20. extern void vst2_oversample_channels_set (int _numIn, int _numOut);
  21. extern void vst2_oversample_channels_get (int *_numIn, int *_numOut);
  22. extern void vst2_idle_detect_mode_fx_set (int _mode);
  23. extern int vst2_idle_detect_mode_fx_get (void);
  24. extern void vst2_idle_detect_mode_instr_set (int _mode);
  25. extern int vst2_idle_detect_mode_instr_get (void);
  26. #endif // RACK_HOST
  27. namespace rack {
  28. bool b_touchkeyboard_enable = false; // true=support effEditKey*
  29. static json_t *settingsToJson() {
  30. // root
  31. json_t *rootJ = json_object();
  32. #ifdef RACK_HOST
  33. // token
  34. json_t *tokenJ = json_string(global->plugin.gToken.c_str());
  35. json_object_set_new(rootJ, "token", tokenJ);
  36. #if 0
  37. if (!windowIsMaximized())
  38. #endif
  39. {
  40. // windowSize
  41. Vec windowSize = windowGetWindowSize();
  42. json_t *windowSizeJ = json_pack("[f, f]", windowSize.x, windowSize.y);
  43. json_object_set_new(rootJ, "windowSize", windowSizeJ);
  44. // windowPos
  45. Vec windowPos = windowGetWindowPos();
  46. json_t *windowPosJ = json_pack("[f, f]", windowPos.x, windowPos.y);
  47. json_object_set_new(rootJ, "windowPos", windowPosJ);
  48. }
  49. // opacity
  50. float opacity = global_ui->app.gToolbar->wireOpacitySlider->value;
  51. json_t *opacityJ = json_real(opacity);
  52. json_object_set_new(rootJ, "wireOpacity", opacityJ);
  53. // tension
  54. float tension = global_ui->app.gToolbar->wireTensionSlider->value;
  55. json_t *tensionJ = json_real(tension);
  56. json_object_set_new(rootJ, "wireTension", tensionJ);
  57. // zoom
  58. float zoom = global_ui->app.gRackScene->zoomWidget->zoom;
  59. json_t *zoomJ = json_real(zoom);
  60. json_object_set_new(rootJ, "zoom", zoomJ);
  61. // refresh rate (Hz)
  62. float refreshRate = vst2_refresh_rate_get();
  63. json_t *refreshRateJ = json_integer(int(refreshRate));
  64. json_object_set_new(rootJ, "refreshRate", refreshRateJ);
  65. // vsync
  66. int vsync = lglw_swap_interval_get(global_ui->window.lglw);
  67. json_t *vsyncJ = json_boolean(vsync);
  68. json_object_set_new(rootJ, "vsync", vsyncJ);
  69. // touchInput
  70. int touchInput = lglw_touchinput_get(global_ui->window.lglw);
  71. json_t *touchInputJ = json_boolean(touchInput);
  72. json_object_set_new(rootJ, "touchInput", touchInputJ);
  73. // touchKbd
  74. int touchKbd = b_touchkeyboard_enable;
  75. json_t *touchKbdJ = json_boolean(touchKbd);
  76. json_object_set_new(rootJ, "touchKbd", touchKbdJ);
  77. // (realtime) oversampleFactor, oversampleQuality
  78. {
  79. float factor;
  80. int quality;
  81. vst2_oversample_realtime_get(&factor, &quality);
  82. json_t *factorJ = json_real(factor);
  83. json_object_set_new(rootJ, "oversampleFactor", factorJ);
  84. json_t *qualityJ = json_integer(quality);
  85. json_object_set_new(rootJ, "oversampleQuality", qualityJ);
  86. }
  87. // oversampleOfflineFactor, oversampleOfflineQuality
  88. {
  89. float factor;
  90. int quality;
  91. vst2_oversample_offline_get(&factor, &quality);
  92. json_t *factorJ = json_real(factor);
  93. json_object_set_new(rootJ, "oversampleOfflineFactor", factorJ);
  94. json_t *qualityJ = json_integer(quality);
  95. json_object_set_new(rootJ, "oversampleOfflineQuality", qualityJ);
  96. }
  97. // oversample offline check (oversampleOffline)
  98. json_t *offlineJ = json_boolean(vst2_oversample_offline_check_get());
  99. json_object_set_new(rootJ, "oversampleOffline", offlineJ);
  100. // oversample input channel limit (oversampleNumIn)
  101. // oversample output channel limit (oversampleNumOut)
  102. {
  103. int numIn;
  104. int numOut;
  105. vst2_oversample_channels_get(&numIn, &numOut);
  106. json_t *numInJ = json_real(numIn);
  107. json_object_set_new(rootJ, "oversampleNumIn", numInJ);
  108. json_t *numOutJ = json_real(numOut);
  109. json_object_set_new(rootJ, "oversampleNumOut", numOutJ);
  110. }
  111. // idleDetectInstr
  112. {
  113. int idleMode = vst2_idle_detect_mode_instr_get();
  114. json_t *idleJ = json_integer(idleMode);
  115. json_object_set_new(rootJ, "idleDetectInstr", idleJ);
  116. }
  117. // idleDetectFx
  118. {
  119. int idleMode = vst2_idle_detect_mode_fx_get();
  120. json_t *idleJ = json_integer(idleMode);
  121. json_object_set_new(rootJ, "idleDetectFx", idleJ);
  122. }
  123. // allowCursorLock
  124. json_t *allowCursorLockJ = json_boolean(global_ui->window.gAllowCursorLock);
  125. json_object_set_new(rootJ, "allowCursorLock", allowCursorLockJ);
  126. // sampleRate
  127. json_t *sampleRateJ = json_real(engineGetSampleRate());
  128. json_object_set_new(rootJ, "sampleRate", sampleRateJ);
  129. // lastPath
  130. json_t *lastPathJ = json_string(global_ui->app.gRackWidget->lastPath.c_str());
  131. json_object_set_new(rootJ, "lastPath", lastPathJ);
  132. // skipAutosaveOnLaunch
  133. if (global->settings.gSkipAutosaveOnLaunch) {
  134. json_object_set_new(rootJ, "skipAutosaveOnLaunch", json_true());
  135. }
  136. // moduleBrowser
  137. json_object_set_new(rootJ, "moduleBrowser", appModuleBrowserToJson());
  138. // powerMeter
  139. json_object_set_new(rootJ, "powerMeter", json_boolean(global->gPowerMeter));
  140. // checkVersion
  141. json_object_set_new(rootJ, "checkVersion", json_boolean(global_ui->app.gCheckVersion));
  142. #endif // RACK_HOST
  143. return rootJ;
  144. }
  145. static void settingsFromJson(json_t *rootJ, bool bWindowSizeOnly) {
  146. // token
  147. json_t *tokenJ = json_object_get(rootJ, "token");
  148. if (tokenJ)
  149. global->plugin.gToken = json_string_value(tokenJ);
  150. // windowSize
  151. json_t *windowSizeJ = json_object_get(rootJ, "windowSize");
  152. if (windowSizeJ) {
  153. double width, height;
  154. json_unpack(windowSizeJ, "[F, F]", &width, &height);
  155. #ifdef USE_VST2
  156. // (note) calling windowSetWindowSize() causes the window to be not resizable initially, and when it is moved, it reverts to a default size (TBI)
  157. if(bWindowSizeOnly)
  158. {
  159. global_ui->window.windowWidth = int(width);
  160. global_ui->window.windowHeight = int(height);
  161. #ifdef RACK_HOST
  162. vst2_window_size_set((int)width, (int)height);
  163. #endif // RACK_HOST
  164. return;
  165. }
  166. #else
  167. windowSetWindowSize(Vec(width, height));
  168. #endif // USE_VST2
  169. }
  170. // windowPos
  171. json_t *windowPosJ = json_object_get(rootJ, "windowPos");
  172. if (windowPosJ) {
  173. double x, y;
  174. json_unpack(windowPosJ, "[F, F]", &x, &y);
  175. #ifndef USE_VST2
  176. windowSetWindowPos(Vec(x, y));
  177. #endif // USE_VST2
  178. }
  179. // opacity
  180. json_t *opacityJ = json_object_get(rootJ, "wireOpacity");
  181. if (opacityJ)
  182. global_ui->app.gToolbar->wireOpacitySlider->value = json_number_value(opacityJ);
  183. // tension
  184. json_t *tensionJ = json_object_get(rootJ, "wireTension");
  185. if (tensionJ)
  186. global_ui->app.gToolbar->wireTensionSlider->value = json_number_value(tensionJ);
  187. // zoom
  188. json_t *zoomJ = json_object_get(rootJ, "zoom");
  189. if (zoomJ) {
  190. global_ui->app.gRackScene->zoomWidget->setZoom(clamp((float) json_number_value(zoomJ), 0.25f, 4.0f));
  191. global_ui->app.gToolbar->zoomSlider->setValue(json_number_value(zoomJ) * 100.0);
  192. }
  193. // refresh rate (Hz)
  194. // (note) <15: use DAW timer (effEditIdle)
  195. json_t *refreshJ = json_object_get(rootJ, "refreshRate");
  196. if (refreshJ) {
  197. #ifdef RACK_HOST
  198. vst2_refresh_rate_set(clamp((float) json_number_value(refreshJ), 0.0f, 200.0f));
  199. #endif // RACK_HOST
  200. }
  201. // vsync
  202. if(!bWindowSizeOnly)
  203. {
  204. json_t *vsyncJ = json_object_get(rootJ, "vsync");
  205. if (vsyncJ)
  206. {
  207. lglw_glcontext_push(global_ui->window.lglw);
  208. lglw_swap_interval_set(global_ui->window.lglw, json_is_true(vsyncJ));
  209. lglw_glcontext_pop(global_ui->window.lglw);
  210. }
  211. }
  212. // allowCursorLock
  213. json_t *allowCursorLockJ = json_object_get(rootJ, "allowCursorLock");
  214. if (allowCursorLockJ)
  215. {
  216. global_ui->window.gAllowCursorLock = json_is_true(allowCursorLockJ);
  217. }
  218. // touchInput
  219. if(!bWindowSizeOnly)
  220. {
  221. json_t *touchJ = json_object_get(rootJ, "touchInput");
  222. if (touchJ)
  223. {
  224. if(json_is_true(touchJ))
  225. {
  226. lglw_touchinput_set(global_ui->window.lglw, LGLW_TRUE);
  227. }
  228. }
  229. }
  230. // touchKbd
  231. if(!bWindowSizeOnly)
  232. {
  233. json_t *touchJ = json_object_get(rootJ, "touchKbd");
  234. if (touchJ)
  235. {
  236. b_touchkeyboard_enable = json_is_true(touchJ);
  237. }
  238. }
  239. #ifndef USE_VST2
  240. // sampleRate
  241. json_t *sampleRateJ = json_object_get(rootJ, "sampleRate");
  242. if (sampleRateJ) {
  243. float sampleRate = json_number_value(sampleRateJ);
  244. engineSetSampleRate(sampleRate);
  245. }
  246. #endif // USE_VST2
  247. #ifdef RACK_HOST
  248. // Realtime Oversample factor and quality
  249. {
  250. float oversampleFactor = -1.0f;
  251. int oversampleQuality = -1;
  252. // Realtime Oversample factor
  253. {
  254. json_t *oversampleJ = json_object_get(rootJ, "oversampleFactor");
  255. if (oversampleJ) {
  256. oversampleFactor = float(json_number_value(oversampleJ));
  257. }
  258. }
  259. // Realtime Oversample quality (0..10)
  260. {
  261. json_t *oversampleJ = json_object_get(rootJ, "oversampleQuality");
  262. if (oversampleJ) {
  263. oversampleQuality = int(json_number_value(oversampleJ));
  264. }
  265. }
  266. vst2_oversample_realtime_set(oversampleFactor, oversampleQuality);
  267. }
  268. // Offline Oversample factor and quality
  269. {
  270. float oversampleFactor = -1.0f;
  271. int oversampleQuality = -1;
  272. // Offline Oversample factor
  273. {
  274. json_t *oversampleJ = json_object_get(rootJ, "oversampleOfflineFactor");
  275. if (oversampleJ) {
  276. oversampleFactor = float(json_number_value(oversampleJ));
  277. }
  278. }
  279. // Offline Oversample quality (0..10)
  280. {
  281. json_t *oversampleJ = json_object_get(rootJ, "oversampleOfflineQuality");
  282. if (oversampleJ) {
  283. oversampleQuality = int(json_number_value(oversampleJ));
  284. }
  285. }
  286. vst2_oversample_offline_set(oversampleFactor, oversampleQuality);
  287. }
  288. json_t *checkOfflineJ = json_object_get(rootJ, "oversampleOffline");
  289. if (checkOfflineJ)
  290. {
  291. vst2_oversample_offline_check_set(json_is_true(checkOfflineJ));
  292. }
  293. // Oversample channel limit
  294. int oversampleNumIn = -1;
  295. int oversampleNumOut = -1;
  296. // Oversample input channel limit
  297. {
  298. json_t *oversampleJ = json_object_get(rootJ, "oversampleNumIn");
  299. if (oversampleJ) {
  300. oversampleNumIn = int(json_number_value(oversampleJ));
  301. }
  302. }
  303. // Oversample output channel limit
  304. {
  305. json_t *oversampleJ = json_object_get(rootJ, "oversampleNumOut");
  306. if (oversampleJ) {
  307. oversampleNumOut = int(json_number_value(oversampleJ));
  308. }
  309. }
  310. vst2_oversample_channels_set(oversampleNumIn, oversampleNumOut);
  311. // Idle detection mode (instrument build)
  312. {
  313. json_t *idleJ = json_object_get(rootJ, "idleDetectInstr");
  314. if (idleJ) {
  315. vst2_idle_detect_mode_instr_set(int(json_number_value(idleJ)));
  316. }
  317. }
  318. // Idle detection mode (FX build)
  319. {
  320. json_t *idleJ = json_object_get(rootJ, "idleDetectFx");
  321. if (idleJ) {
  322. vst2_idle_detect_mode_fx_set(int(json_number_value(idleJ)));
  323. }
  324. }
  325. #endif // RACK_HOST
  326. // lastPath
  327. json_t *lastPathJ = json_object_get(rootJ, "lastPath");
  328. if (lastPathJ)
  329. global_ui->app.gRackWidget->lastPath = json_string_value(lastPathJ);
  330. // skipAutosaveOnLaunch
  331. json_t *skipAutosaveOnLaunchJ = json_object_get(rootJ, "skipAutosaveOnLaunch");
  332. if (skipAutosaveOnLaunchJ)
  333. global->settings.gSkipAutosaveOnLaunch = json_boolean_value(skipAutosaveOnLaunchJ);
  334. // moduleBrowser
  335. json_t *moduleBrowserJ = json_object_get(rootJ, "moduleBrowser");
  336. if (moduleBrowserJ)
  337. appModuleBrowserFromJson(moduleBrowserJ);
  338. // powerMeter
  339. json_t *powerMeterJ = json_object_get(rootJ, "powerMeter");
  340. if (powerMeterJ)
  341. global->gPowerMeter = json_boolean_value(powerMeterJ);
  342. // checkVersion
  343. json_t *checkVersionJ = json_object_get(rootJ, "checkVersion");
  344. if (checkVersionJ)
  345. global_ui->app.gCheckVersion = json_boolean_value(checkVersionJ);
  346. }
  347. void settingsSave(std::string filename) {
  348. info("Saving settings %s", filename.c_str());
  349. json_t *rootJ = settingsToJson();
  350. if (rootJ) {
  351. FILE *file = fopen(filename.c_str(), "w");
  352. if (!file)
  353. return;
  354. json_dumpf(rootJ, file, JSON_INDENT(2) | JSON_REAL_PRECISION(9));
  355. json_decref(rootJ);
  356. fclose(file);
  357. }
  358. }
  359. void settingsLoad(std::string filename, bool bWindowSizeOnly) {
  360. info("Loading settings %s", filename.c_str());
  361. FILE *file = fopen(filename.c_str(), "r");
  362. if (!file)
  363. return;
  364. json_error_t error;
  365. json_t *rootJ = json_loadf(file, 0, &error);
  366. if (rootJ) {
  367. settingsFromJson(rootJ, bWindowSizeOnly);
  368. json_decref(rootJ);
  369. }
  370. else {
  371. warn("JSON parsing error at %s %d:%d %s", error.source, error.line, error.column, error.text);
  372. }
  373. fclose(file);
  374. }
  375. } // namespace rack