LCOV - code coverage report
Current view: top level - src/presets - preset_manager.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 100.0 % 79 79
Test Date: 2026-06-07 15:51:50 Functions: 100.0 % 9 9

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

Generated by: LCOV version 2.0-1