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.

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