Line data Source code
1 : #include "preset_manager.h"
2 : #include "preset_manager_impl.h"
3 : #include <iostream>
4 : #include <ctime>
5 : #include <sys/stat.h>
6 : #include <cstdlib>
7 : #include <cstring>
8 : #include <filesystem>
9 :
10 : #ifdef _WIN32
11 : #include <direct.h>
12 : #include <io.h>
13 : #include <windows.h>
14 : #define MKDIR(path) _mkdir(path)
15 : #define STAT_STRUCT struct _stat
16 : #define STAT_FN _stat
17 : #elif defined(__APPLE__)
18 : #include <dirent.h>
19 : #include <mach-o/dyld.h>
20 : #define MKDIR(path) mkdir(path, 0755)
21 : #define STAT_STRUCT struct stat
22 : #define STAT_FN stat
23 : #else
24 : #include <dirent.h>
25 : #define MKDIR(path) mkdir(path, 0755)
26 : #define STAT_STRUCT struct stat
27 : #define STAT_FN stat
28 : #endif
29 :
30 : namespace Amplitron {
31 :
32 2 : std::string PresetManager::last_error_;
33 2 : std::string PresetManager::custom_presets_dir_;
34 :
35 931 : bool dir_exists(const std::string& path) {
36 309 : STAT_STRUCT st;
37 1514 : return STAT_FN(path.c_str(), &st) == 0 &&
38 : #ifdef _WIN32
39 294 : (st.st_mode & _S_IFDIR);
40 : #else
41 894 : S_ISDIR(st.st_mode);
42 : #endif
43 : }
44 :
45 39 : std::string PresetManager::get_system_presets_dir() {
46 : #ifdef _WIN32
47 13 : const char* pd = std::getenv("ProgramData");
48 26 : return pd ? std::string(pd) + "\\Amplitron\\presets" : "";
49 : #elif defined(__APPLE__)
50 13 : return "/Library/Application Support/Amplitron/presets";
51 : #else
52 26 : return "/usr/share/amplitron/presets";
53 : #endif
54 : }
55 :
56 60 : std::string PresetManager::get_config_path() {
57 : #ifdef _WIN32
58 20 : const char* appdata = std::getenv("APPDATA");
59 20 : if (!appdata) return "amplitron_config.json";
60 34 : std::string dir = std::string(appdata) + "\\Amplitron";
61 17 : MKDIR(dir.c_str());
62 17 : return dir + "\\config.json";
63 : #else
64 40 : const char* home = std::getenv("HOME");
65 46 : if (!home) return "amplitron_config.json";
66 34 : std::string config_dir = std::string(home) + "/.config/amplitron";
67 : try {
68 36 : std::filesystem::create_directories(config_dir);
69 19 : } catch (...) {}
70 34 : return config_dir + "/config.json";
71 : #endif
72 56 : }
73 :
74 16 : std::string get_user_presets_dir() {
75 : #ifdef _WIN32
76 4 : const char* appdata = std::getenv("APPDATA");
77 4 : if (!appdata) return "";
78 6 : return std::string(appdata) + "\\Amplitron\\presets";
79 : #elif defined(__APPLE__)
80 6 : const char* home = std::getenv("HOME");
81 6 : if (!home) return "";
82 5 : return std::string(home) + "/Library/Application Support/Amplitron/presets";
83 : #else
84 6 : const char* home = std::getenv("HOME");
85 8 : if (!home) return "";
86 10 : return std::string(home) + "/.config/amplitron/presets";
87 : #endif
88 6 : }
89 :
90 : // Clean, robust string migration implementation (No JSON header dependencies)
91 24 : std::string PresetManager::apply_migrations(const std::string& raw_json_string) {
92 : // Find the absolute root opening of the JSON payload
93 24 : size_t root_start = raw_json_string.find('{');
94 24 : if (root_start == std::string::npos) {
95 6 : return raw_json_string;
96 : }
97 :
98 : // Look for a "version" key strictly near the root area (e.g., within the first 100 characters)
99 : // This stops nested effect parameters from accidentally triggering a false positive bypass.
100 18 : size_t version_pos = raw_json_string.find("\"version\"");
101 18 : bool is_root_version = (version_pos != std::string::npos && (version_pos - root_start) < 100);
102 :
103 16 : if (!is_root_version) {
104 12 : std::cout << "[Preset Migration] Upgrading legacy unversioned preset format to Version "
105 12 : << CURRENT_PRESET_VERSION << std::endl;
106 :
107 12 : std::string patched = raw_json_string;
108 12 : size_t last_bracket = patched.find_last_of('}');
109 :
110 12 : if (last_bracket != std::string::npos && last_bracket > root_start) {
111 : // Find out if there is any content between the root brackets to avoid trailing comma bugs
112 12 : size_t content_check = patched.find_first_not_of(" \t\n\r", root_start + 1);
113 12 : bool is_empty_json = (content_check == last_bracket);
114 :
115 : // Construct the exact version upgrade block using our header constant dynamically
116 12 : std::string migration_patch;
117 12 : if (!is_empty_json) {
118 6 : migration_patch += ",\n";
119 2 : }
120 20 : migration_patch += " \"version\": " + std::to_string(CURRENT_PRESET_VERSION) + ",\n";
121 12 : migration_patch += " \"input_gain\": 0.7,\n";
122 12 : migration_patch += " \"output_gain\": 0.8\n";
123 :
124 12 : patched.insert(last_bracket, migration_patch);
125 12 : return patched;
126 12 : }
127 12 : }
128 :
129 6 : return raw_json_string;
130 8 : }
131 :
132 : } // namespace Amplitron
|