diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aae13d9..03ad112e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -448,6 +448,7 @@ src/engine/brrUtils.c src/engine/safeReader.cpp src/engine/safeWriter.cpp src/engine/config.cpp +src/engine/configEngine.cpp src/engine/dispatchContainer.cpp src/engine/engine.cpp src/engine/fileOps.cpp diff --git a/src/engine/config.cpp b/src/engine/config.cpp index 38cb2b04..f98c82a4 100644 --- a/src/engine/config.cpp +++ b/src/engine/config.cpp @@ -17,101 +17,13 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "engine.h" +#include "config.h" #include "../ta-log.h" #include "../fileutils.h" #include -#ifdef _WIN32 -#include "winStuff.h" -#define CONFIG_FILE "\\furnace.cfg" -#else -#ifdef __HAIKU__ -#include -#include -#endif -#include -#include -#include -#define CONFIG_FILE "/furnace.cfg" -#endif - -#ifdef IS_MOBILE -#ifdef HAVE_SDL2 -#include -#else -#error "Furnace mobile requires SDL2!" -#endif -#endif - -void DivEngine::initConfDir() { -#ifdef _WIN32 - // maybe move this function in here instead? - configPath=getWinConfigPath(); -#elif defined(IS_MOBILE) - configPath=SDL_GetPrefPath("tildearrow","furnace"); -#else -#ifdef __HAIKU__ - char userSettingsDir[PATH_MAX]; - status_t findUserDir = find_directory(B_USER_SETTINGS_DIRECTORY,0,true,userSettingsDir,PATH_MAX); - if (findUserDir==B_OK) { - configPath=userSettingsDir; - } else { - logW("unable to find/create user settings directory (%s)!",strerror(findUserDir)); - configPath="."; - return; - } -#else - // TODO this should check XDG_CONFIG_HOME first - char* home=getenv("HOME"); - if (home==NULL) { - int uid=getuid(); - struct passwd* entry=getpwuid(uid); - if (entry==NULL) { - logW("unable to determine home directory (%s)!",strerror(errno)); - configPath="."; - return; - } else { - configPath=entry->pw_dir; - } - } else { - configPath=home; - } -#ifdef __APPLE__ - configPath+="/Library/Application Support"; -#else - // FIXME this doesn't honour XDG_CONFIG_HOME *at all* - configPath+="/.config"; -#endif // __APPLE__ -#endif // __HAIKU__ -#ifdef __APPLE__ - configPath+="/Furnace"; -#else - configPath+="/furnace"; -#endif // __APPLE__ - struct stat st; - std::string pathSep="/"; - configPath+=pathSep; - size_t sepPos=configPath.find(pathSep,1); - while (sepPos!=std::string::npos) { - std::string subpath=configPath.substr(0,sepPos++); - if (stat(subpath.c_str(),&st)!=0) { - logI("creating config path element %s ...",subpath.c_str()); - if (mkdir(subpath.c_str(),0755)!=0) { - logW("could not create config path element %s! (%s)",subpath.c_str(),strerror(errno)); - configPath="."; - return; - } - } - sepPos=configPath.find(pathSep,sepPos); - } - configPath.resize(configPath.length()-pathSep.length()); -#endif // _WIN32 -} - -bool DivEngine::saveConf() { - configFile=configPath+String(CONFIG_FILE); - FILE* f=ps_fopen(configFile.c_str(),"wb"); +bool DivConfig::save(const char* path) { + FILE* f=ps_fopen(path,"wb"); if (f==NULL) { logW("could not write config file! %s",strerror(errno)); return false; @@ -128,13 +40,12 @@ bool DivEngine::saveConf() { return true; } -bool DivEngine::loadConf() { +bool DivConfig::loadFromFile(const char* path, bool createOnFail) { char line[4096]; - configFile=configPath+String(CONFIG_FILE); - FILE* f=ps_fopen(configFile.c_str(),"rb"); + FILE* f=ps_fopen(path,"rb"); if (f==NULL) { logI("creating default config."); - return saveConf(); + return save(path); } logI("loading config."); while (!feof(f)) { @@ -164,7 +75,7 @@ bool DivEngine::loadConf() { return true; } -bool DivEngine::getConfBool(String key, bool fallback) { +bool DivConfig::getConfBool(String key, bool fallback) { try { String val=conf.at(key); if (val=="true") { @@ -177,7 +88,7 @@ bool DivEngine::getConfBool(String key, bool fallback) { return fallback; } -int DivEngine::getConfInt(String key, int fallback) { +int DivConfig::getConfInt(String key, int fallback) { try { String val=conf.at(key); int ret=std::stoi(val); @@ -188,7 +99,7 @@ int DivEngine::getConfInt(String key, int fallback) { return fallback; } -float DivEngine::getConfFloat(String key, float fallback) { +float DivConfig::getConfFloat(String key, float fallback) { try { String val=conf.at(key); float ret=std::stof(val); @@ -199,7 +110,7 @@ float DivEngine::getConfFloat(String key, float fallback) { return fallback; } -double DivEngine::getConfDouble(String key, double fallback) { +double DivConfig::getConfDouble(String key, double fallback) { try { String val=conf.at(key); double ret=std::stod(val); @@ -210,7 +121,7 @@ double DivEngine::getConfDouble(String key, double fallback) { return fallback; } -String DivEngine::getConfString(String key, String fallback) { +String DivConfig::getConfString(String key, String fallback) { try { String val=conf.at(key); return val; @@ -219,7 +130,7 @@ String DivEngine::getConfString(String key, String fallback) { return fallback; } -void DivEngine::setConf(String key, bool value) { +void DivConfig::setConf(String key, bool value) { if (value) { conf[key]="true"; } else { @@ -227,22 +138,22 @@ void DivEngine::setConf(String key, bool value) { } } -void DivEngine::setConf(String key, int value) { +void DivConfig::setConf(String key, int value) { conf[key]=fmt::sprintf("%d",value); } -void DivEngine::setConf(String key, float value) { +void DivConfig::setConf(String key, float value) { conf[key]=fmt::sprintf("%f",value); } -void DivEngine::setConf(String key, double value) { +void DivConfig::setConf(String key, double value) { conf[key]=fmt::sprintf("%f",value); } -void DivEngine::setConf(String key, const char* value) { +void DivConfig::setConf(String key, const char* value) { conf[key]=String(value); } -void DivEngine::setConf(String key, String value) { +void DivConfig::setConf(String key, String value) { conf[key]=value; } diff --git a/src/engine/config.h b/src/engine/config.h new file mode 100644 index 00000000..c33494a9 --- /dev/null +++ b/src/engine/config.h @@ -0,0 +1,51 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef _DIVCONFIG_H +#define _DIVCONFIG_H + +#include "../ta-utils.h" +#include + +class DivConfig { + std::map conf; + public: + // config loading/saving + bool loadFromMemory(const char* buf); + bool loadFromFile(const char* path, bool createOnFail=true); + String toString(); + bool save(const char* path); + + // get a config value + bool getConfBool(String key, bool fallback); + int getConfInt(String key, int fallback); + float getConfFloat(String key, float fallback); + double getConfDouble(String key, double fallback); + String getConfString(String key, String fallback); + + // set a config value + void setConf(String key, bool value); + void setConf(String key, int value); + void setConf(String key, float value); + void setConf(String key, double value); + void setConf(String key, const char* value); + void setConf(String key, String value); +}; + +#endif \ No newline at end of file diff --git a/src/engine/configEngine.cpp b/src/engine/configEngine.cpp new file mode 100644 index 00000000..df93cc95 --- /dev/null +++ b/src/engine/configEngine.cpp @@ -0,0 +1,162 @@ +/** + * Furnace Tracker - multi-system chiptune tracker + * Copyright (C) 2021-2022 tildearrow and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "engine.h" +#include "../ta-log.h" + +#ifdef _WIN32 +#include "winStuff.h" +#define CONFIG_FILE "\\furnace.cfg" +#else +#ifdef __HAIKU__ +#include +#include +#endif +#include +#include +#include +#define CONFIG_FILE "/furnace.cfg" +#endif + +#ifdef IS_MOBILE +#ifdef HAVE_SDL2 +#include +#else +#error "Furnace mobile requires SDL2!" +#endif +#endif + +void DivEngine::initConfDir() { +#ifdef _WIN32 + // maybe move this function in here instead? + configPath=getWinConfigPath(); +#elif defined(IS_MOBILE) + configPath=SDL_GetPrefPath("tildearrow","furnace"); +#else +#ifdef __HAIKU__ + char userSettingsDir[PATH_MAX]; + status_t findUserDir = find_directory(B_USER_SETTINGS_DIRECTORY,0,true,userSettingsDir,PATH_MAX); + if (findUserDir==B_OK) { + configPath=userSettingsDir; + } else { + logW("unable to find/create user settings directory (%s)!",strerror(findUserDir)); + configPath="."; + return; + } +#else + // TODO this should check XDG_CONFIG_HOME first + char* home=getenv("HOME"); + if (home==NULL) { + int uid=getuid(); + struct passwd* entry=getpwuid(uid); + if (entry==NULL) { + logW("unable to determine home directory (%s)!",strerror(errno)); + configPath="."; + return; + } else { + configPath=entry->pw_dir; + } + } else { + configPath=home; + } +#ifdef __APPLE__ + configPath+="/Library/Application Support"; +#else + // FIXME this doesn't honour XDG_CONFIG_HOME *at all* + configPath+="/.config"; +#endif // __APPLE__ +#endif // __HAIKU__ +#ifdef __APPLE__ + configPath+="/Furnace"; +#else + configPath+="/furnace"; +#endif // __APPLE__ + struct stat st; + std::string pathSep="/"; + configPath+=pathSep; + size_t sepPos=configPath.find(pathSep,1); + while (sepPos!=std::string::npos) { + std::string subpath=configPath.substr(0,sepPos++); + if (stat(subpath.c_str(),&st)!=0) { + logI("creating config path element %s ...",subpath.c_str()); + if (mkdir(subpath.c_str(),0755)!=0) { + logW("could not create config path element %s! (%s)",subpath.c_str(),strerror(errno)); + configPath="."; + return; + } + } + sepPos=configPath.find(pathSep,sepPos); + } + configPath.resize(configPath.length()-pathSep.length()); +#endif // _WIN32 +} + +bool DivEngine::saveConf() { + configFile=configPath+String(CONFIG_FILE); + return conf.save(configFile.c_str()); +} + +bool DivEngine::loadConf() { + configFile=configPath+String(CONFIG_FILE); + return conf.loadFromFile(configFile.c_str()); +} + +bool DivEngine::getConfBool(String key, bool fallback) { + return conf.getConfBool(key,fallback); +} + +int DivEngine::getConfInt(String key, int fallback) { + return conf.getConfInt(key,fallback); +} + +float DivEngine::getConfFloat(String key, float fallback) { + return conf.getConfFloat(key,fallback); +} + +double DivEngine::getConfDouble(String key, double fallback) { + return conf.getConfDouble(key,fallback); +} + +String DivEngine::getConfString(String key, String fallback) { + return conf.getConfString(key,fallback); +} + +void DivEngine::setConf(String key, bool value) { + conf.setConf(key,value); +} + +void DivEngine::setConf(String key, int value) { + conf.setConf(key,value); +} + +void DivEngine::setConf(String key, float value) { + conf.setConf(key,value); +} + +void DivEngine::setConf(String key, double value) { + conf.setConf(key,value); +} + +void DivEngine::setConf(String key, const char* value) { + conf.setConf(key,value); +} + +void DivEngine::setConf(String key, String value) { + conf.setConf(key,value); +} \ No newline at end of file diff --git a/src/engine/engine.h b/src/engine/engine.h index 0cc05eef..895a89ea 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -19,6 +19,7 @@ #ifndef _ENGINE_H #define _ENGINE_H +#include "config.h" #include "instrument.h" #include "song.h" #include "dispatch.h" @@ -366,7 +367,7 @@ class DivEngine { DivAudioEngines audioEngine; DivAudioExportModes exportMode; double exportFadeOut; - std::map conf; + DivConfig conf; std::deque pendingNotes; // bitfield unsigned char walked[8192];