reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

config.cpp (7365B)


      1 /* ReaPack: Package manager for REAPER
      2  * Copyright (C) 2015-2025  Christian Fillion
      3  *
      4  * This program is free software: you can redistribute it and/or modify
      5  * it under the terms of the GNU Lesser General Public License as published by
      6  * the Free Software Foundation, either version 3 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12  * GNU Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public License
     15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16  */
     17 
     18 #include "config.hpp"
     19 
     20 #include "path.hpp"
     21 #include "win32.hpp"
     22 
     23 #include <algorithm>
     24 
     25 #ifdef _WIN32
     26 #  include <windows.h>
     27 #else
     28 #  include <swell/swell.h>
     29 #endif
     30 
     31 static const char *GENERAL_GRP = "general";
     32 static const char *VERSION_KEY = "version";
     33 
     34 static const char *INSTALL_GRP = "install";
     35 static const char *AUTOINSTALL_KEY = "autoinstall";
     36 static const char *PRERELEASES_KEY = "prereleases";
     37 static const char *PROMPTOBSOLETE_KEY = "promptobsolete";
     38 
     39 static const char *ABOUT_GRP = "about";
     40 static const char *MANAGER_GRP = "manager";
     41 
     42 static const char *BROWSER_GRP = "browser";
     43 static const char *STATE_KEY = "state";
     44 static const char *SYNONYMS_KEY = "synonyms";
     45 
     46 static const char *NETWORK_GRP = "network";
     47 static const char *PROXY_KEY = "proxy";
     48 static const char *VERIFYPEER_KEY = "verifypeer";
     49 static const char *STALETHRSH_KEY = "stalethreshold";
     50 
     51 static const char *SIZE_KEY = "size";
     52 
     53 static const char *REMOTES_GRP = "remotes";
     54 static const char *REMOTE_KEY  = "remote";
     55 
     56 static std::string nKey(const char *key, const unsigned int i)
     57 {
     58   return key + std::to_string(i);
     59 }
     60 
     61 Config::Config(const Path &path)
     62   : m_path(path.join()), m_isFirstRun(false), m_version(0), m_remotesIniSize(0)
     63 {
     64   resetOptions();
     65   read();
     66 }
     67 
     68 Config::~Config()
     69 {
     70   write();
     71 }
     72 
     73 void Config::resetOptions()
     74 {
     75   install = {false, false, true};
     76   network = {"", true, NetworkOpts::OneWeekThreshold};
     77   filter  = {true};
     78   windowState = {};
     79 }
     80 
     81 void Config::restoreSelfRemote()
     82 {
     83   const std::string name = "ReaPack";
     84   const std::string url = "https://reapack.com/index.xml";
     85 
     86   Remote remote = remotes.get(name);
     87   remote.setName(name);
     88   remote.setUrl(url);
     89   remote.protect();
     90 
     91   remotes.add(remote);
     92 }
     93 
     94 void Config::restoreDefaultRemotes()
     95 {
     96   Remote self = remotes.get("ReaPack");
     97   self.setEnabled(true);
     98   remotes.add(self);
     99 
    100   const Remote repos[] {
    101     {"ReaTeam Scripts",
    102       "https://github.com/ReaTeam/ReaScripts/raw/master/index.xml"},
    103     {"ReaTeam JSFX",
    104       "https://github.com/ReaTeam/JSFX/raw/master/index.xml"},
    105     {"ReaTeam Themes",
    106       "https://github.com/ReaTeam/Themes/raw/master/index.xml"},
    107     {"ReaTeam LangPacks",
    108       "https://github.com/ReaTeam/LangPacks/raw/master/index.xml"},
    109     {"ReaTeam Extensions",
    110       "https://github.com/ReaTeam/Extensions/raw/master/index.xml"},
    111 
    112     {"MPL Scripts",
    113       "https://github.com/MichaelPilyavskiy/ReaScripts/raw/master/index.xml"},
    114     {"X-Raym Scripts",
    115       "https://github.com/X-Raym/REAPER-ReaScripts/raw/master/index.xml"},
    116   };
    117 
    118   for(const Remote &repo : repos)
    119     remotes.add(repo);
    120 }
    121 
    122 void Config::migrate()
    123 {
    124   const unsigned int version = getUInt(GENERAL_GRP, VERSION_KEY);
    125 
    126   switch(version) {
    127   case 0: // v1.0
    128   case 1: // v1.1rc3
    129   case 2: // v1.1
    130   case 3: // v1.2rc2: added ReaTeam/Extensions
    131     m_isFirstRun = true;
    132     restoreDefaultRemotes();
    133     break;
    134   default:
    135     // configuration is up-to-date, don't write anything now
    136     // keep the version intact in case it comes from a newer version of ReaPack
    137     m_version = version;
    138     return;
    139   };
    140 
    141   m_version = 4;
    142   write();
    143 }
    144 
    145 void Config::read()
    146 {
    147   install.autoInstall = getBool(INSTALL_GRP, AUTOINSTALL_KEY, install.autoInstall);
    148   install.bleedingEdge = getBool(INSTALL_GRP, PRERELEASES_KEY, install.bleedingEdge);
    149   install.promptObsolete = getBool(INSTALL_GRP, PROMPTOBSOLETE_KEY, install.promptObsolete);
    150 
    151   network.proxy = getString(NETWORK_GRP, PROXY_KEY, network.proxy);
    152   network.verifyPeer = getBool(NETWORK_GRP, VERIFYPEER_KEY, network.verifyPeer);
    153   network.staleThreshold = static_cast<time_t>(getUInt(NETWORK_GRP,
    154     STALETHRSH_KEY, static_cast<unsigned int>(network.staleThreshold)));
    155 
    156   filter.expandSynonyms = getBool(BROWSER_GRP, SYNONYMS_KEY, filter.expandSynonyms);
    157 
    158   windowState.about = getString(ABOUT_GRP, STATE_KEY, windowState.about);
    159   windowState.browser = getString(BROWSER_GRP, STATE_KEY, windowState.browser);
    160   windowState.manager = getString(MANAGER_GRP, STATE_KEY, windowState.manager);
    161 
    162   readRemotes();
    163   restoreSelfRemote();
    164   migrate();
    165 }
    166 
    167 void Config::write()
    168 {
    169   setUInt(GENERAL_GRP, VERSION_KEY, m_version);
    170 
    171   setUInt(INSTALL_GRP, AUTOINSTALL_KEY, install.autoInstall);
    172   setUInt(INSTALL_GRP, PRERELEASES_KEY, install.bleedingEdge);
    173   setUInt(INSTALL_GRP, PROMPTOBSOLETE_KEY, install.promptObsolete);
    174 
    175   setString(NETWORK_GRP, PROXY_KEY, network.proxy);
    176   setUInt(NETWORK_GRP, VERIFYPEER_KEY, network.verifyPeer);
    177   setUInt(NETWORK_GRP, STALETHRSH_KEY, static_cast<unsigned int>(network.staleThreshold));
    178 
    179   setUInt(BROWSER_GRP, SYNONYMS_KEY, filter.expandSynonyms);
    180 
    181   setString(ABOUT_GRP, STATE_KEY, windowState.about);
    182   setString(BROWSER_GRP, STATE_KEY, windowState.browser);
    183   setString(MANAGER_GRP, STATE_KEY, windowState.manager);
    184 
    185   writeRemotes();
    186 }
    187 
    188 void Config::readRemotes()
    189 {
    190   m_remotesIniSize = getUInt(REMOTES_GRP, SIZE_KEY);
    191 
    192   for(unsigned int i = 0; i < m_remotesIniSize; i++) {
    193     const std::string data = getString(REMOTES_GRP, nKey(REMOTE_KEY, i).c_str());
    194 
    195     remotes.add(Remote::fromString(data));
    196   }
    197 }
    198 
    199 void Config::writeRemotes()
    200 {
    201   m_remotesIniSize = std::max(static_cast<unsigned int>(remotes.size()), m_remotesIniSize);
    202 
    203   unsigned int i = 0;
    204   for(auto it = remotes.begin(); it != remotes.end(); it++, i++)
    205     setString(REMOTES_GRP, nKey(REMOTE_KEY, i).c_str(), it->toString());
    206 
    207   cleanupArray(REMOTES_GRP, REMOTE_KEY, i, m_remotesIniSize);
    208 
    209   setUInt(REMOTES_GRP, SIZE_KEY, m_remotesIniSize = i);
    210 }
    211 
    212 std::string Config::getString(const char *group, const char *key, const std::string &fallback) const
    213 {
    214   return Win32::getPrivateProfileString(group, key, fallback.c_str(), m_path.c_str());
    215 }
    216 
    217 void Config::setString(const char *group, const char *key, const std::string &val) const
    218 {
    219   Win32::writePrivateProfileString(group, key, val.c_str(), m_path.c_str());
    220 }
    221 
    222 unsigned int Config::getUInt(const char *group,
    223   const char *key, const unsigned int fallback) const
    224 {
    225   return Win32::getPrivateProfileInt(group, key, fallback, m_path.c_str());
    226 }
    227 
    228 bool Config::getBool(const char *group, const char *key, const bool fallback) const
    229 {
    230   return getUInt(group, key, fallback) > 0;
    231 }
    232 
    233 void Config::setUInt(const char *group, const char *key, const unsigned int val) const
    234 {
    235   setString(group, key, std::to_string(val));
    236 }
    237 
    238 void Config::deleteKey(const char *group, const char *key) const
    239 {
    240   Win32::writePrivateProfileString(group, key, nullptr, m_path.c_str());
    241 }
    242 
    243 void Config::cleanupArray(const char *group, const char *key,
    244   const unsigned int begin, const unsigned int end) const
    245 {
    246   for(unsigned int i = begin; i < end; i++)
    247     deleteKey(group, nKey(key, i).c_str());
    248 }