14 enum class ReloadType {
27 static const std::map<std::string, std::pair<ReloadType, std::string>> settingsMetadata;
30 std::string VPXTablesPath =
"$HOME/Games/VPX_Tables/";
31 std::string VPinballXPath =
"$HOME/Games/vpinball/build/VPinballX_BGFX";
32 std::string vpxIniPath =
"";
33 std::string vpxStartArgs =
"";
34 std::string vpxEndArgs =
"";
35 bool autoPatchTables =
false;
38 float dpiScale = 1.0f;
39 bool enableDpiScaling =
true;
42 std::string defaultPlayfieldImage =
"img/default_table.png";
43 std::string defaultBackglassImage =
"img/default_backglass.png";
44 std::string defaultDmdImage =
"img/default_dmd.png";
45 std::string defaultWheelImage =
"img/default_wheel.png";
46 std::string defaultTopperImage =
"img/default_topper.png";
47 std::string defaultPlayfieldVideo =
"img/default_table.mp4";
48 std::string defaultBackglassVideo =
"img/default_backglass.mp4";
49 std::string defaultDmdVideo =
"img/default_dmd.mp4";
50 std::string defaultTopperVideo =
"img/default_topper.mp4";
53 std::string customPlayfieldImage =
"images/table.png";
54 std::string customBackglassImage =
"images/backglass.png";
55 std::string customDmdImage =
"images/dmd.png";
56 std::string customWheelImage =
"images/wheel.png";
57 std::string customTopperImage =
"images/topper.png";
58 std::string customPlayfieldVideo =
"video/table.mp4";
59 std::string customBackglassVideo =
"video/backglass.mp4";
60 std::string customDmdVideo =
"video/dmd.mp4";
61 std::string customTopperVideo =
"images/topper.mp4";
62 std::string tableMusic =
"audio/music.mp3";
63 std::string customLaunchSound =
"audio/launch.mp3";
66 std::string videoBackend =
"vlc";
67 bool useVPinballXIni =
true;
68 int playfieldWindowWidth = 1080;
69 int playfieldWindowHeight = 1920;
73 bool showBackglass =
true;
74 int backglassWindowWidth = 1024;
75 int backglassWindowHeight = 768;
80 int dmdWindowWidth = 1024;
81 int dmdWindowHeight = 256;
85 bool showTopper =
false;
86 int topperWindowWidth = 512;
87 int topperWindowHeight = 128;
88 int topperWindowX = -1;
89 int topperWindowY = -1;
92 std::string titleSource =
"filename";
93 bool fetchVPSdb =
false;
94 bool useVpxtool =
false;
95 bool fetchVpinMediaDb =
false;
96 bool resizeToWindows =
false;
97 bool ignoreScanners =
false;
98 bool forceRebuildMetadata =
false;
99 std::string titleSortBy =
"title";
100 bool showMetadata =
false;
102 float metadataPanelWidth = 0.7f;
103 float metadataPanelHeight = 0.5f;
104 float metadataPanelAlpha = 0.6f;
106 float titleWeight = 0.6f;
107 float yearWeight = 0.2f;
108 float manufacturerWeight = 0.1f;
109 float romWeight = 0.25f;
110 float titleThreshold = 0.55f;
111 float confidenceThreshold = 0.6f;
114 bool showArrowHint =
true;
115 float arrowHintWidth = 20.0f;
116 float arrowHintHeight = 100.0f;
117 float arrowThickness = 4.0f;
118 float arrowAlpha = 0.6f;
119 float arrowGlow = 1.5f;
120 SDL_Color arrowGlowColor = {200, 200, 200, 255};
121 SDL_Color arrowColorTop = {100, 100, 100, 255};
122 SDL_Color arrowColorBottom = {150, 150, 150, 255};
124 bool showScrollbar =
true;
125 float scrollbarWidth = 12.0f;
126 float thumbWidth = 15.0f;
127 float scrollbarLength = 0.5f;
128 SDL_Color scrollbarColor = {50, 50, 50, 200};
129 SDL_Color scrollbarThumbColor = {50, 150, 150, 255};
132 bool showWheel =
true;
133 std::string wheelWindow =
"playfield";
134 bool showTitle =
true;
135 std::string titleWindow =
"playfield";
136 std::string fontPath =
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf";
137 SDL_Color fontColor = {255, 255, 255, 255};
138 SDL_Color fontBgColor = {0, 0, 0, 128};
144 bool forceImagesOnly =
false;
146 int wheelMediaHeight = 350;
147 int wheelMediaWidth = 350;
148 int wheelMediaX = 720;
149 int wheelMediaY = 1550;
151 int playfieldMediaWidth = 1080;
152 int playfieldMediaHeight = 1920;
153 int playfieldMediaX = 0;
154 int playfieldMediaY = 0;
155 int playfieldRotation = 0;
157 int backglassMediaWidth = 1024;
158 int backglassMediaHeight = 768;
159 int backglassMediaX = 0;
160 int backglassMediaY = 0;
161 int backglassRotation = 0;
163 int dmdMediaWidth = 1024;
164 int dmdMediaHeight = 256;
169 int topperMediaWidth = 512;
170 int topperMediaHeight = 128;
171 int topperMediaX = 0;
172 int topperMediaY = 0;
173 int topperRotation = 0;
176 bool masterMute =
false;
177 float masterVol = 100.0f;
178 bool mediaAudioMute =
false;
179 float mediaAudioVol = 60.0f;
180 bool tableMusicMute =
false;
181 float tableMusicVol = 60.0f;
182 bool interfaceAudioMute =
false;
183 float interfaceAudioVol = 60.0f;
184 bool interfaceAmbienceMute =
false;
185 float interfaceAmbienceVol = 60.0f;
188 std::string scrollNormalSound =
"snd/scroll_normal.mp3";
189 std::string scrollFastSound =
"snd/scroll_fast.mp3";
190 std::string scrollJumpSound =
"snd/scroll_jump.mp3";
191 std::string scrollRandomSound =
"snd/scroll_random.mp3";
192 std::string launchTableSound =
"snd/launch_table.mp3";
193 std::string launchScreenshotSound =
"snd/launch_screenshot.mp3";
194 std::string panelToggleSound =
"snd/panel_toggle.mp3";
195 std::string screenshotTakeSound =
"snd/screenshot_take.mp3";
196 std::string ambienceSound =
"snd/interface_ambience.mp3";
200 std::string vpxSubCmd =
"-Play";
201 std::string vpsDbPath =
"data/vpsdb.json";
202 std::string vpsDbUpdateFrequency =
"startup";
203 std::string vpsDbLastUpdated =
"data/lastUpdated.json";
204 std::string vpxtoolBin =
"";
205 std::string vpxtoolIndex =
"vpxtool_index.json";
206 std::string indexPath =
"data/asapcab_index.json";
207 int screenshotWait = 4;
209 float configUIWidth = 0.7f;
210 float configUIHeight = 0.5f;
213 std::map<std::string, std::string> keybinds_ = {
214 {
"Previous Table",
"Left Shift"},
215 {
"Next Table",
"Right Shift"},
216 {
"Fast Previous Table",
"Left Ctrl"},
217 {
"Fast Next Table",
"Right Ctrl"},
218 {
"Jump Next Letter",
"/"},
219 {
"Jump Previous Letter",
"Z"},
220 {
"Random Table",
"R"},
221 {
"Launch Table",
"Return"},
222 {
"Toggle Config",
"C"},
224 {
"Screenshot Mode",
"S"},
225 {
"Screenshot Key",
"S"},
226 {
"Screenshot Quit",
"Q"},
227 {
"Toggle Editor",
"M"},
228 {
"Toggle Catalog",
"N"}
232 void applyPostProcessing(
const std::string& exeDir) {
234 this->exeDir = exeDir;
237 VPXTablesPath = resolvePath(VPXTablesPath, exeDir);
238 VPinballXPath = resolvePath(VPinballXPath, exeDir);
241 std::vector<std::string> pathFields = {
243 "defaultPlayfieldImage",
"defaultBackglassImage",
"defaultDmdImage",
244 "defaultWheelImage",
"defaultTopperImage",
"defaultPlayfieldVideo",
245 "defaultBackglassVideo",
"defaultDmdVideo",
"defaultTopperVideo",
248 "scrollNormalSound",
"scrollFastSound",
"scrollJumpSound",
249 "scrollRandomSound",
"launchTableSound",
"launchScreenshotSound",
250 "panelToggleSound",
"screenshotTakeSound",
"ambienceSound",
253 "vpsDbPath",
"vpsDbLastUpdated",
"indexPath",
257 for (
const auto& field : pathFields) {
258 if (field ==
"defaultPlayfieldImage") defaultPlayfieldImage = resolvePath(defaultPlayfieldImage, exeDir);
259 else if (field ==
"defaultBackglassImage") defaultBackglassImage = resolvePath(defaultBackglassImage, exeDir);
260 else if (field ==
"defaultDmdImage") defaultDmdImage = resolvePath(defaultDmdImage, exeDir);
261 else if (field ==
"defaultWheelImage") defaultWheelImage = resolvePath(defaultWheelImage, exeDir);
262 else if (field ==
"defaultTopperImage") defaultTopperImage = resolvePath(defaultTopperImage, exeDir);
263 else if (field ==
"defaultPlayfieldVideo") defaultPlayfieldVideo = resolvePath(defaultPlayfieldVideo, exeDir);
264 else if (field ==
"defaultBackglassVideo") defaultBackglassVideo = resolvePath(defaultBackglassVideo, exeDir);
265 else if (field ==
"defaultDmdVideo") defaultDmdVideo = resolvePath(defaultDmdVideo, exeDir);
266 else if (field ==
"defaultTopperVideo") defaultTopperVideo = resolvePath(defaultTopperVideo, exeDir);
268 else if (field ==
"scrollNormalSound") scrollNormalSound = resolvePath(scrollNormalSound, exeDir);
269 else if (field ==
"scrollFastSound") scrollFastSound = resolvePath(scrollFastSound, exeDir);
270 else if (field ==
"scrollJumpSound") scrollJumpSound = resolvePath(scrollJumpSound, exeDir);
271 else if (field ==
"scrollRandomSound") scrollRandomSound = resolvePath(scrollRandomSound, exeDir);
272 else if (field ==
"launchTableSound") launchTableSound = resolvePath(launchTableSound, exeDir);
273 else if (field ==
"launchScreenshotSound") launchScreenshotSound = resolvePath(launchScreenshotSound, exeDir);
274 else if (field ==
"panelToggleSound") panelToggleSound = resolvePath(panelToggleSound, exeDir);
275 else if (field ==
"screenshotTakeSound") screenshotTakeSound = resolvePath(screenshotTakeSound, exeDir);
276 else if (field ==
"ambienceSound") ambienceSound = resolvePath(ambienceSound, exeDir);
278 else if (field ==
"vpsDbPath") vpsDbPath = resolvePath(vpsDbPath, exeDir);
279 else if (field ==
"vpsDbLastUpdated") vpsDbLastUpdated = resolvePath(vpsDbLastUpdated, exeDir);
280 else if (field ==
"indexPath") indexPath = resolvePath(indexPath, exeDir);
284 if (enableDpiScaling) {
285 fontSize =
static_cast<int>(fontSize * dpiScale);
291 std::string resolvePath(
const std::string& value,
const std::string& exeDir)
const {
292 std::string result = value;
294 const char* home = std::getenv(
"HOME");
297 while ((pos = result.find(
"$HOME")) != std::string::npos) {
298 result.replace(pos, 5, home);
300 if (!result.empty() && result[0] ==
'~') {
301 result.replace(0, 1, home);
305 if (result.empty())
return exeDir + value;
306 if (result[0] ==
'/' || result[0] ==
'\\')
return result;
307 return exeDir + result;
312 friend void to_json(nlohmann::json& j,
const Settings& s) {
315 {
"VPXTablesPath", s.VPXTablesPath},
316 {
"VPinballXPath", s.VPinballXPath},
317 {
"vpxIniPath", s.vpxIniPath},
318 {
"vpxStartArgs", s.vpxStartArgs},
319 {
"vpxEndArgs", s.vpxEndArgs},
320 {
"autoPatchTables", s.autoPatchTables}
323 {
"dpiScale", s.dpiScale},
324 {
"enableDpiScaling", s.enableDpiScaling}
327 {
"defaultPlayfieldImage", s.defaultPlayfieldImage},
328 {
"defaultBackglassImage", s.defaultBackglassImage},
329 {
"defaultDmdImage", s.defaultDmdImage},
330 {
"defaultWheelImage", s.defaultWheelImage},
331 {
"defaultTopperImage", s.defaultTopperImage},
332 {
"defaultPlayfieldVideo", s.defaultPlayfieldVideo},
333 {
"defaultBackglassVideo", s.defaultBackglassVideo},
334 {
"defaultDmdVideo", s.defaultDmdVideo},
335 {
"defaultTopperVideo", s.defaultTopperVideo}
338 {
"customPlayfieldImage", s.customPlayfieldImage},
339 {
"customBackglassImage", s.customBackglassImage},
340 {
"customDmdImage", s.customDmdImage},
341 {
"customWheelImage", s.customWheelImage},
342 {
"customTopperImage", s.customTopperImage},
343 {
"customPlayfieldVideo", s.customPlayfieldVideo},
344 {
"customBackglassVideo", s.customBackglassVideo},
345 {
"customDmdVideo", s.customDmdVideo},
346 {
"customTopperVideo", s.customTopperVideo},
347 {
"tableMusic", s.tableMusic},
348 {
"customLaunchSound", s.customLaunchSound}
351 {
"videoBackend", s.videoBackend},
352 {
"useVPinballXIni", s.useVPinballXIni},
353 {
"playfieldWindowWidth", s.playfieldWindowWidth},
354 {
"playfieldWindowHeight", s.playfieldWindowHeight},
355 {
"playfieldX", s.playfieldX},
356 {
"playfieldY", s.playfieldY},
357 {
"showBackglass", s.showBackglass},
358 {
"backglassWindowWidth", s.backglassWindowWidth},
359 {
"backglassWindowHeight", s.backglassWindowHeight},
360 {
"backglassX", s.backglassX},
361 {
"backglassY", s.backglassY},
362 {
"showDMD", s.showDMD},
363 {
"dmdWindowWidth", s.dmdWindowWidth},
364 {
"dmdWindowHeight", s.dmdWindowHeight},
367 {
"showTopper", s.showTopper},
368 {
"topperWindowWidth", s.topperWindowWidth},
369 {
"topperWindowHeight", s.topperWindowHeight},
370 {
"topperWindowX", s.topperWindowX},
371 {
"topperWindowY", s.topperWindowY}
374 {
"titleSource", s.titleSource},
375 {
"fetchVPSdb", s.fetchVPSdb},
376 {
"useVpxtool", s.useVpxtool},
377 {
"fetchVpinMediaDb", s.fetchVpinMediaDb},
378 {
"resizeToWindows", s.resizeToWindows},
379 {
"ignoreScanners", s.ignoreScanners},
380 {
"forceRebuildMetadata", s.forceRebuildMetadata},
381 {
"titleSortBy", s.titleSortBy},
382 {
"showMetadata", s.showMetadata},
383 {
"metadataPanelWidth", s.metadataPanelWidth},
384 {
"metadataPanelHeight", s.metadataPanelHeight},
385 {
"metadataPanelAlpha", s.metadataPanelAlpha},
386 {
"titleWeight", s.titleWeight},
387 {
"yearWeight", s.yearWeight},
388 {
"manufacturerWeight", s.manufacturerWeight},
389 {
"romWeight", s.romWeight},
390 {
"titleThreshold", s.titleThreshold},
391 {
"confidenceThreshold", s.confidenceThreshold}
394 {
"showArrowHint", s.showArrowHint},
395 {
"arrowHintWidth", s.arrowHintWidth},
396 {
"arrowHintHeight", s.arrowHintHeight},
397 {
"arrowThickness", s.arrowThickness},
398 {
"arrowAlpha", s.arrowAlpha},
399 {
"arrowGlow", s.arrowGlow},
400 {
"arrowGlowColor", {s.arrowGlowColor.r, s.arrowGlowColor.g, s.arrowGlowColor.b, s.arrowGlowColor.a}},
401 {
"arrowColorTop", {s.arrowColorTop.r, s.arrowColorTop.g, s.arrowColorTop.b, s.arrowColorTop.a}},
402 {
"arrowColorBottom", {s.arrowColorBottom.r, s.arrowColorBottom.g, s.arrowColorBottom.b, s.arrowColorBottom.a}},
403 {
"showScrollbar", s.showScrollbar},
404 {
"scrollbarWidth", s.scrollbarWidth},
405 {
"thumbWidth", s.thumbWidth},
406 {
"scrollbarLength", s.scrollbarLength},
407 {
"scrollbarColor", {s.scrollbarColor.r, s.scrollbarColor.g, s.scrollbarColor.b, s.scrollbarColor.a}},
408 {
"scrollbarThumbColor", {s.scrollbarThumbColor.r, s.scrollbarThumbColor.g, s.scrollbarThumbColor.b, s.scrollbarThumbColor.a}}
411 {
"showWheel", s.showWheel},
412 {
"wheelWindow", s.wheelWindow},
413 {
"showTitle", s.showTitle},
414 {
"titleWindow", s.titleWindow},
415 {
"fontPath", s.fontPath},
416 {
"fontColor", {s.fontColor.r, s.fontColor.g, s.fontColor.b, s.fontColor.a}},
417 {
"fontBgColor", {s.fontBgColor.r, s.fontBgColor.g, s.fontBgColor.b, s.fontBgColor.a}},
418 {
"fontSize", s.fontSize},
419 {
"titleX", s.titleX},
422 {
"MediaDimensions", {
423 {
"forceImagesOnly", s.forceImagesOnly},
424 {
"wheelMediaHeight", s.wheelMediaHeight},
425 {
"wheelMediaWidth", s.wheelMediaWidth},
426 {
"wheelMediaX", s.wheelMediaX},
427 {
"wheelMediaY", s.wheelMediaY},
428 {
"playfieldMediaWidth", s.playfieldMediaWidth},
429 {
"playfieldMediaHeight", s.playfieldMediaHeight},
430 {
"playfieldMediaX", s.playfieldMediaX},
431 {
"playfieldMediaY", s.playfieldMediaY},
432 {
"playfieldRotation", s.playfieldRotation},
433 {
"backglassMediaWidth", s.backglassMediaWidth},
434 {
"backglassMediaHeight", s.backglassMediaHeight},
435 {
"backglassMediaX", s.backglassMediaX},
436 {
"backglassMediaY", s.backglassMediaY},
437 {
"backglassRotation", s.backglassRotation},
438 {
"dmdMediaWidth", s.dmdMediaWidth},
439 {
"dmdMediaHeight", s.dmdMediaHeight},
440 {
"dmdMediaX", s.dmdMediaX},
441 {
"dmdMediaY", s.dmdMediaY},
442 {
"dmdRotation", s.dmdRotation},
443 {
"topperMediaWidth", s.topperMediaWidth},
444 {
"topperMediaHeight", s.topperMediaHeight},
445 {
"topperMediaX", s.topperMediaX},
446 {
"topperMediaY", s.topperMediaY},
447 {
"topperRotation", s.topperRotation}
450 {
"masterMute", s.masterMute},
451 {
"masterVol", s.masterVol},
452 {
"mediaAudioMute", s.mediaAudioMute},
453 {
"mediaAudioVol", s.mediaAudioVol},
454 {
"tableMusicMute", s.tableMusicMute},
455 {
"tableMusicVol", s.tableMusicVol},
456 {
"interfaceAudioMute", s.interfaceAudioMute},
457 {
"interfaceAudioVol", s.interfaceAudioVol},
458 {
"interfaceAmbienceMute", s.interfaceAmbienceMute},
459 {
"interfaceAmbienceVol", s.interfaceAmbienceVol}
462 {
"scrollNormalSound", s.scrollNormalSound},
463 {
"scrollFastSound", s.scrollFastSound},
464 {
"scrollJumpSound", s.scrollJumpSound},
465 {
"scrollRandomSound", s.scrollRandomSound},
466 {
"launchTableSound", s.launchTableSound},
467 {
"launchScreenshotSound", s.launchScreenshotSound},
468 {
"panelToggleSound", s.panelToggleSound},
469 {
"screenshotTakeSound", s.screenshotTakeSound},
470 {
"ambienceSound", s.ambienceSound}
473 {
"exeDir", s.exeDir},
474 {
"vpxSubCmd", s.vpxSubCmd},
475 {
"vpsDbPath", s.vpsDbPath},
476 {
"vpsDbUpdateFrequency", s.vpsDbUpdateFrequency},
477 {
"vpsDbLastUpdated", s.vpsDbLastUpdated},
478 {
"vpxtoolBin", s.vpxtoolBin},
479 {
"vpxtoolIndex", s.vpxtoolIndex},
480 {
"indexPath", s.indexPath},
481 {
"screenshotWait", s.screenshotWait},
482 {
"configUIWidth", s.configUIWidth},
483 {
"configUIHeight", s.configUIHeight}
485 {
"Keybinds", s.keybinds_}
489 friend void from_json(
const nlohmann::json& j,
Settings& s) {
491 s.VPXTablesPath = j.value(
"VPX", nlohmann::json{}).value(
"VPXTablesPath", s.VPXTablesPath);
492 s.VPinballXPath = j.value(
"VPX", nlohmann::json{}).value(
"VPinballXPath", s.VPinballXPath);
493 s.vpxIniPath = j.value(
"VPX", nlohmann::json{}).value(
"vpxIniPath", s.vpxIniPath);
494 s.vpxStartArgs = j.value(
"VPX", nlohmann::json{}).value(
"vpxStartArgs", s.vpxStartArgs);
495 s.vpxEndArgs = j.value(
"VPX", nlohmann::json{}).value(
"vpxEndArgs", s.vpxEndArgs);
496 s.autoPatchTables = j.value(
"VPX", nlohmann::json{}).value(
"autoPatchTables", s.autoPatchTables);
499 s.dpiScale = j.value(
"DPISettings", nlohmann::json{}).value(
"dpiScale", s.dpiScale);
500 s.enableDpiScaling = j.value(
"DPISettings", nlohmann::json{}).value(
"enableDpiScaling", s.enableDpiScaling);
503 s.defaultPlayfieldImage = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultPlayfieldImage", s.defaultPlayfieldImage);
504 s.defaultBackglassImage = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultBackglassImage", s.defaultBackglassImage);
505 s.defaultDmdImage = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultDmdImage", s.defaultDmdImage);
506 s.defaultWheelImage = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultWheelImage", s.defaultWheelImage);
507 s.defaultTopperImage = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultTopperImage", s.defaultTopperImage);
508 s.defaultPlayfieldVideo = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultPlayfieldVideo", s.defaultPlayfieldVideo);
509 s.defaultBackglassVideo = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultBackglassVideo", s.defaultBackglassVideo);
510 s.defaultDmdVideo = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultDmdVideo", s.defaultDmdVideo);
511 s.defaultTopperVideo = j.value(
"DefaultMedia", nlohmann::json{}).value(
"defaultTopperVideo", s.defaultTopperVideo);
514 s.customPlayfieldImage = j.value(
"CustomMedia", nlohmann::json{}).value(
"customPlayfieldImage", s.customPlayfieldImage);
515 s.customBackglassImage = j.value(
"CustomMedia", nlohmann::json{}).value(
"customBackglassImage", s.customBackglassImage);
516 s.customDmdImage = j.value(
"CustomMedia", nlohmann::json{}).value(
"customDmdImage", s.customDmdImage);
517 s.customWheelImage = j.value(
"CustomMedia", nlohmann::json{}).value(
"customWheelImage", s.customWheelImage);
518 s.customTopperImage = j.value(
"CustomMedia", nlohmann::json{}).value(
"customTopperImage", s.customTopperImage);
519 s.customPlayfieldVideo = j.value(
"CustomMedia", nlohmann::json{}).value(
"customPlayfieldVideo", s.customPlayfieldVideo);
520 s.customBackglassVideo = j.value(
"CustomMedia", nlohmann::json{}).value(
"customBackglassVideo", s.customBackglassVideo);
521 s.customDmdVideo = j.value(
"CustomMedia", nlohmann::json{}).value(
"customDmdVideo", s.customDmdVideo);
522 s.customTopperVideo = j.value(
"CustomMedia", nlohmann::json{}).value(
"customTopperVideo", s.customTopperVideo);
523 s.tableMusic = j.value(
"CustomMedia", nlohmann::json{}).value(
"tableMusic", s.tableMusic);
524 s.customLaunchSound = j.value(
"CustomMedia", nlohmann::json{}).value(
"customLaunchSound", s.customLaunchSound);
527 s.videoBackend = j.value(
"WindowSettings", nlohmann::json{}).value(
"videoBackend", s.videoBackend);
528 s.useVPinballXIni = j.value(
"WindowSettings", nlohmann::json{}).value(
"useVPinballXIni", s.useVPinballXIni);
529 s.playfieldWindowWidth = j.value(
"WindowSettings", nlohmann::json{}).value(
"playfieldWindowWidth", s.playfieldWindowWidth);
530 s.playfieldWindowHeight = j.value(
"WindowSettings", nlohmann::json{}).value(
"playfieldWindowHeight", s.playfieldWindowHeight);
531 s.playfieldX = j.value(
"WindowSettings", nlohmann::json{}).value(
"playfieldX", s.playfieldX);
532 s.playfieldY = j.value(
"WindowSettings", nlohmann::json{}).value(
"playfieldY", s.playfieldY);
533 s.showBackglass = j.value(
"WindowSettings", nlohmann::json{}).value(
"showBackglass", s.showBackglass);
534 s.backglassWindowWidth = j.value(
"WindowSettings", nlohmann::json{}).value(
"backglassWindowWidth", s.backglassWindowWidth);
535 s.backglassWindowHeight = j.value(
"WindowSettings", nlohmann::json{}).value(
"backglassWindowHeight", s.backglassWindowHeight);
536 s.backglassX = j.value(
"WindowSettings", nlohmann::json{}).value(
"backglassX", s.backglassX);
537 s.backglassY = j.value(
"WindowSettings", nlohmann::json{}).value(
"backglassY", s.backglassY);
538 s.showDMD = j.value(
"WindowSettings", nlohmann::json{}).value(
"showDMD", s.showDMD);
539 s.dmdWindowWidth = j.value(
"WindowSettings", nlohmann::json{}).value(
"dmdWindowWidth", s.dmdWindowWidth);
540 s.dmdWindowHeight = j.value(
"WindowSettings", nlohmann::json{}).value(
"dmdWindowHeight", s.dmdWindowHeight);
541 s.dmdX = j.value(
"WindowSettings", nlohmann::json{}).value(
"dmdX", s.dmdX);
542 s.dmdY = j.value(
"WindowSettings", nlohmann::json{}).value(
"dmdY", s.dmdY);
543 s.showTopper = j.value(
"WindowSettings", nlohmann::json{}).value(
"showTopper", s.showTopper);
544 s.topperWindowWidth = j.value(
"WindowSettings", nlohmann::json{}).value(
"topperWindowWidth", s.topperWindowWidth);
545 s.topperWindowHeight = j.value(
"WindowSettings", nlohmann::json{}).value(
"topperWindowHeight", s.topperWindowHeight);
546 s.topperWindowX = j.value(
"WindowSettings", nlohmann::json{}).value(
"topperWindowX", s.topperWindowX);
547 s.topperWindowY = j.value(
"WindowSettings", nlohmann::json{}).value(
"topperWindowY", s.topperWindowY);
550 s.titleSource = j.value(
"TableMetadata", nlohmann::json{}).value(
"titleSource", s.titleSource);
551 s.fetchVPSdb = j.value(
"TableMetadata", nlohmann::json{}).value(
"fetchVPSdb", s.fetchVPSdb);
552 s.useVpxtool = j.value(
"TableMetadata", nlohmann::json{}).value(
"useVpxtool", s.useVpxtool);
553 s.fetchVpinMediaDb = j.value(
"TableMetadata", nlohmann::json{}).value(
"fetchVpinMediaDb", s.fetchVpinMediaDb);
554 s.resizeToWindows = j.value(
"TableMetadata", nlohmann::json{}).value(
"resizeToWindows", s.resizeToWindows);
555 s.forceRebuildMetadata = j.value(
"TableMetadata", nlohmann::json{}).value(
"forceRebuildMetadata", s.forceRebuildMetadata);
556 s.ignoreScanners = j.value(
"TableMetadata", nlohmann::json{}).value(
"ignoreScanners", s.ignoreScanners);
557 s.titleSortBy = j.value(
"TableMetadata", nlohmann::json{}).value(
"titleSortBy", s.titleSortBy);
558 s.showMetadata = j.value(
"TableMetadata", nlohmann::json{}).value(
"showMetadata", s.showMetadata);
559 s.metadataPanelWidth = j.value(
"TableMetadata", nlohmann::json{}).value(
"metadataPanelWidth", s.metadataPanelWidth);
560 s.metadataPanelHeight = j.value(
"TableMetadata", nlohmann::json{}).value(
"metadataPanelHeight", s.metadataPanelHeight);
561 s.metadataPanelAlpha = j.value(
"TableMetadata", nlohmann::json{}).value(
"metadataPanelAlpha", s.metadataPanelAlpha);
563 s.titleWeight = j.value(
"TableMetadata", nlohmann::json{}).value(
"titleWeight", s.titleWeight);
564 s.yearWeight = j.value(
"TableMetadata", nlohmann::json{}).value(
"yearWeight", s.yearWeight);
565 s.manufacturerWeight = j.value(
"TableMetadata", nlohmann::json{}).value(
"manufacturerWeight", s.manufacturerWeight);
566 s.romWeight = j.value(
"TableMetadata", nlohmann::json{}).value(
"romWeight", s.romWeight);
567 s.titleThreshold = j.value(
"TableMetadata", nlohmann::json{}).value(
"titleThreshold", s.titleThreshold);
568 s.confidenceThreshold = j.value(
"TableMetadata", nlohmann::json{}).value(
"confidenceThreshold", s.confidenceThreshold);
571 s.showArrowHint = j.value(
"UIWidgets", nlohmann::json{}).value(
"showArrowHint", s.showArrowHint);
572 s.arrowHintWidth = j.value(
"UIWidgets", nlohmann::json{}).value(
"arrowHintWidth", s.arrowHintWidth);
573 s.arrowHintHeight = j.value(
"UIWidgets", nlohmann::json{}).value(
"arrowHintHeight", s.arrowHintHeight);
574 s.arrowThickness = j.value(
"UIWidgets", nlohmann::json{}).value(
"arrowThickness", s.arrowThickness);
575 s.arrowAlpha = j.value(
"UIWidgets", nlohmann::json{}).value(
"arrowAlpha", s.arrowAlpha);
576 s.arrowGlow = j.value(
"UIWidgets", nlohmann::json{}).value(
"arrowGlow", s.arrowGlow);
577 if (j.value(
"UIWidgets", nlohmann::json{}).contains(
"arrowGlowColor") && j[
"UIWidgets"][
"arrowGlowColor"].is_array() && j[
"UIWidgets"][
"arrowGlowColor"].size() == 4) {
578 s.arrowGlowColor = {
static_cast<Uint8
>(j[
"UIWidgets"][
"arrowGlowColor"][0]),
579 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowGlowColor"][1]),
580 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowGlowColor"][2]),
581 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowGlowColor"][3])};
583 if (j.value(
"UIWidgets", nlohmann::json{}).contains(
"arrowColorTop") && j[
"UIWidgets"][
"arrowColorTop"].is_array() && j[
"UIWidgets"][
"arrowColorTop"].size() == 4) {
584 s.arrowColorTop = {
static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorTop"][0]),
585 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorTop"][1]),
586 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorTop"][2]),
587 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorTop"][3])};
589 if (j.value(
"UIWidgets", nlohmann::json{}).contains(
"arrowColorBottom") && j[
"UIWidgets"][
"arrowColorBottom"].is_array() && j[
"UIWidgets"][
"arrowColorBottom"].size() == 4) {
590 s.arrowColorBottom = {
static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorBottom"][0]),
591 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorBottom"][1]),
592 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorBottom"][2]),
593 static_cast<Uint8
>(j[
"UIWidgets"][
"arrowColorBottom"][3])};
595 s.showScrollbar = j.value(
"UIWidgets", nlohmann::json{}).value(
"showScrollbar", s.showScrollbar);
596 s.scrollbarWidth = j.value(
"UIWidgets", nlohmann::json{}).value(
"scrollbarWidth", s.scrollbarWidth);
597 s.thumbWidth = j.value(
"UIWidgets", nlohmann::json{}).value(
"thumbWidth", s.thumbWidth);
598 s.scrollbarLength = j.value(
"UIWidgets", nlohmann::json{}).value(
"scrollbarLength", s.scrollbarLength);
599 if (j.value(
"UIWidgets", nlohmann::json{}).contains(
"scrollbarColor") && j[
"UIWidgets"][
"scrollbarColor"].is_array() && j[
"UIWidgets"][
"scrollbarColor"].size() == 4) {
600 s.scrollbarColor = {
static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarColor"][0]),
601 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarColor"][1]),
602 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarColor"][2]),
603 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarColor"][3])};
605 if (j.value(
"UIWidgets", nlohmann::json{}).contains(
"scrollbarThumbColor") && j[
"UIWidgets"][
"scrollbarThumbColor"].is_array() && j[
"UIWidgets"][
"scrollbarThumbColor"].size() == 4) {
606 s.scrollbarThumbColor = {
static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarThumbColor"][0]),
607 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarThumbColor"][1]),
608 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarThumbColor"][2]),
609 static_cast<Uint8
>(j[
"UIWidgets"][
"scrollbarThumbColor"][3])};
613 s.showWheel = j.value(
"TitleDisplay", nlohmann::json{}).value(
"showWheel", s.showWheel);
614 s.wheelWindow = j.value(
"TitleDisplay", nlohmann::json{}).value(
"wheelWindow", s.wheelWindow);
615 s.showTitle = j.value(
"TitleDisplay", nlohmann::json{}).value(
"showTitle", s.showTitle);
616 s.titleWindow = j.value(
"TitleDisplay", nlohmann::json{}).value(
"titleWindow", s.titleWindow);
617 s.fontPath = j.value(
"TitleDisplay", nlohmann::json{}).value(
"fontPath", s.fontPath);
618 if (j.value(
"TitleDisplay", nlohmann::json{}).contains(
"fontColor") && j[
"TitleDisplay"][
"fontColor"].is_array() && j[
"TitleDisplay"][
"fontColor"].size() == 4) {
619 s.fontColor = {
static_cast<Uint8
>(j[
"TitleDisplay"][
"fontColor"][0]),
620 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontColor"][1]),
621 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontColor"][2]),
622 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontColor"][3])};
624 if (j.value(
"TitleDisplay", nlohmann::json{}).contains(
"fontBgColor") && j[
"TitleDisplay"][
"fontBgColor"].is_array() && j[
"TitleDisplay"][
"fontBgColor"].size() == 4) {
625 s.fontBgColor = {
static_cast<Uint8
>(j[
"TitleDisplay"][
"fontBgColor"][0]),
626 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontBgColor"][1]),
627 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontBgColor"][2]),
628 static_cast<Uint8
>(j[
"TitleDisplay"][
"fontBgColor"][3])};
630 s.fontSize = j.value(
"TitleDisplay", nlohmann::json{}).value(
"fontSize", s.fontSize);
631 s.titleX = j.value(
"TitleDisplay", nlohmann::json{}).value(
"titleX", s.titleX);
632 s.titleY = j.value(
"TitleDisplay", nlohmann::json{}).value(
"titleY", s.titleY);
635 s.forceImagesOnly = j.value(
"MediaDimensions", nlohmann::json{}).value(
"forceImagesOnly", s.forceImagesOnly);
636 s.wheelMediaHeight = j.value(
"MediaDimensions", nlohmann::json{}).value(
"wheelMediaHeight", s.wheelMediaHeight);
637 s.wheelMediaWidth = j.value(
"MediaDimensions", nlohmann::json{}).value(
"wheelMediaWidth", s.wheelMediaWidth);
638 s.wheelMediaX = j.value(
"MediaDimensions", nlohmann::json{}).value(
"wheelMediaX", s.wheelMediaX);
639 s.wheelMediaY = j.value(
"MediaDimensions", nlohmann::json{}).value(
"wheelMediaY", s.wheelMediaY);
640 s.playfieldMediaWidth = j.value(
"MediaDimensions", nlohmann::json{}).value(
"playfieldMediaWidth", s.playfieldMediaWidth);
641 s.playfieldMediaHeight = j.value(
"MediaDimensions", nlohmann::json{}).value(
"playfieldMediaHeight", s.playfieldMediaHeight);
642 s.playfieldMediaX = j.value(
"MediaDimensions", nlohmann::json{}).value(
"playfieldMediaX", s.playfieldMediaX);
643 s.playfieldMediaY = j.value(
"MediaDimensions", nlohmann::json{}).value(
"playfieldMediaY", s.playfieldMediaY);
644 s.playfieldRotation = j.value(
"MediaDimensions", nlohmann::json{}).value(
"playfieldRotation", s.playfieldRotation);
645 s.backglassMediaWidth = j.value(
"MediaDimensions", nlohmann::json{}).value(
"backglassMediaWidth", s.backglassMediaWidth);
646 s.backglassMediaHeight = j.value(
"MediaDimensions", nlohmann::json{}).value(
"backglassMediaHeight", s.backglassMediaHeight);
647 s.backglassMediaX = j.value(
"MediaDimensions", nlohmann::json{}).value(
"backglassMediaX", s.backglassMediaX);
648 s.backglassMediaY = j.value(
"MediaDimensions", nlohmann::json{}).value(
"backglassMediaY", s.backglassMediaY);
649 s.backglassRotation = j.value(
"MediaDimensions", nlohmann::json{}).value(
"backglassRotation", s.backglassRotation);
650 s.dmdMediaWidth = j.value(
"MediaDimensions", nlohmann::json{}).value(
"dmdMediaWidth", s.dmdMediaWidth);
651 s.dmdMediaHeight = j.value(
"MediaDimensions", nlohmann::json{}).value(
"dmdMediaHeight", s.dmdMediaHeight);
652 s.dmdMediaX = j.value(
"MediaDimensions", nlohmann::json{}).value(
"dmdMediaX", s.dmdMediaX);
653 s.dmdMediaY = j.value(
"MediaDimensions", nlohmann::json{}).value(
"dmdMediaY", s.dmdMediaY);
654 s.dmdRotation = j.value(
"MediaDimensions", nlohmann::json{}).value(
"dmdRotation", s.dmdRotation);
655 s.topperMediaWidth = j.value(
"MediaDimensions", nlohmann::json{}).value(
"topperMediaWidth", s.topperMediaWidth);
656 s.topperMediaHeight = j.value(
"MediaDimensions", nlohmann::json{}).value(
"topperMediaHeight", s.topperMediaHeight);
657 s.topperMediaX = j.value(
"MediaDimensions", nlohmann::json{}).value(
"topperMediaX", s.topperMediaX);
658 s.topperMediaY = j.value(
"MediaDimensions", nlohmann::json{}).value(
"topperMediaY", s.topperMediaY);
659 s.topperRotation = j.value(
"MediaDimensions", nlohmann::json{}).value(
"topperRotation", s.topperRotation);
662 s.masterMute = j.value(
"AudioSettings", nlohmann::json{}).value(
"masterMute", s.masterMute);
663 s.masterVol = j.value(
"AudioSettings", nlohmann::json{}).value(
"masterVol", s.masterVol);
664 s.mediaAudioMute = j.value(
"AudioSettings", nlohmann::json{}).value(
"mediaAudioMute", s.mediaAudioMute);
665 s.mediaAudioVol = j.value(
"AudioSettings", nlohmann::json{}).value(
"mediaAudioVol", s.mediaAudioVol);
666 s.tableMusicMute = j.value(
"AudioSettings", nlohmann::json{}).value(
"tableMusicMute", s.tableMusicMute);
667 s.tableMusicVol = j.value(
"AudioSettings", nlohmann::json{}).value(
"tableMusicVol", s.tableMusicVol);
668 s.interfaceAudioMute = j.value(
"AudioSettings", nlohmann::json{}).value(
"interfaceAudioMute", s.interfaceAudioMute);
669 s.interfaceAudioVol = j.value(
"AudioSettings", nlohmann::json{}).value(
"interfaceAudioVol", s.interfaceAudioVol);
670 s.interfaceAmbienceMute = j.value(
"AudioSettings", nlohmann::json{}).value(
"interfaceAmbienceMute", s.interfaceAmbienceMute);
671 s.interfaceAmbienceVol = j.value(
"AudioSettings", nlohmann::json{}).value(
"interfaceAmbienceVol", s.interfaceAmbienceVol);
674 s.scrollNormalSound = j.value(
"UISounds", nlohmann::json{}).value(
"scrollNormalSound", s.scrollNormalSound);
675 s.scrollFastSound = j.value(
"UISounds", nlohmann::json{}).value(
"scrollFastSound", s.scrollFastSound);
676 s.scrollJumpSound = j.value(
"UISounds", nlohmann::json{}).value(
"scrollJumpSound", s.scrollJumpSound);
677 s.scrollRandomSound = j.value(
"UISounds", nlohmann::json{}).value(
"scrollRandomSound", s.scrollRandomSound);
678 s.launchTableSound = j.value(
"UISounds", nlohmann::json{}).value(
"launchTableSound", s.launchTableSound);
679 s.launchScreenshotSound = j.value(
"UISounds", nlohmann::json{}).value(
"launchScreenshotSound", s.launchScreenshotSound);
680 s.panelToggleSound = j.value(
"UISounds", nlohmann::json{}).value(
"panelToggleSound", s.panelToggleSound);
681 s.screenshotTakeSound = j.value(
"UISounds", nlohmann::json{}).value(
"screenshotTakeSound", s.screenshotTakeSound);
682 s.ambienceSound = j.value(
"UISounds", nlohmann::json{}).value(
"ambienceSound", s.ambienceSound);
685 s.exeDir = j.value(
"Internal", nlohmann::json{}).value(
"exeDir", s.exeDir);
686 s.vpxSubCmd = j.value(
"Internal", nlohmann::json{}).value(
"vpxSubCmd", s.vpxSubCmd);
687 s.vpsDbPath = j.value(
"Internal", nlohmann::json{}).value(
"vpsDbPath", s.vpsDbPath);
688 s.vpsDbUpdateFrequency = j.value(
"Internal", nlohmann::json{}).value(
"vpsDbUpdateFrequency", s.vpsDbUpdateFrequency);
689 s.vpsDbLastUpdated = j.value(
"Internal", nlohmann::json{}).value(
"vpsDbLastUpdated", s.vpsDbLastUpdated);
690 s.vpxtoolIndex = j.value(
"Internal", nlohmann::json{}).value(
"vpxtoolIndex", s.vpxtoolIndex);
691 s.vpxtoolBin = j.value(
"Internal", nlohmann::json{}).value(
"vpxtoolBin", s.vpxtoolBin);
692 s.indexPath = j.value(
"Internal", nlohmann::json{}).value(
"indexPath", s.indexPath);
693 s.configUIWidth = j.value(
"Internal", nlohmann::json{}).value(
"configUIWidth", s.configUIWidth);
694 s.configUIHeight = j.value(
"Internal", nlohmann::json{}).value(
"configUIHeight", s.configUIHeight);
695 s.screenshotWait = j.value(
"Internal", nlohmann::json{}).value(
"screenshotWait", s.screenshotWait);
698 if (j.contains(
"Keybinds") && j[
"Keybinds"].is_object()) {
700 for (
auto& [key, value] : j[
"Keybinds"].items()) {
701 if (value.is_string()) {
702 s.keybinds_[key] = value.get<std::string>();