wasm: config support
This commit is contained in:
@@ -2,11 +2,35 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <emscripten.h>
|
||||||
|
|
||||||
|
// ── WASM: persist settings via browser localStorage ─────────────────────────
|
||||||
|
|
||||||
|
EM_JS(char*, js_loadSettings, (), {
|
||||||
|
var s = localStorage.getItem("baudline_settings");
|
||||||
|
if (!s) return 0;
|
||||||
|
var len = lengthBytesUTF8(s) + 1;
|
||||||
|
var buf = _malloc(len);
|
||||||
|
stringToUTF8(s, buf, len);
|
||||||
|
return buf;
|
||||||
|
});
|
||||||
|
|
||||||
|
EM_JS(void, js_saveSettings, (const char* data), {
|
||||||
|
localStorage.setItem("baudline_settings", UTF8ToString(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
#else
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace baudline {
|
namespace baudline {
|
||||||
|
|
||||||
std::string Config::defaultPath() {
|
std::string Config::defaultPath() {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
return "";
|
||||||
|
#else
|
||||||
const char* xdg = std::getenv("XDG_CONFIG_HOME");
|
const char* xdg = std::getenv("XDG_CONFIG_HOME");
|
||||||
std::string base;
|
std::string base;
|
||||||
if (xdg && xdg[0]) {
|
if (xdg && xdg[0]) {
|
||||||
@@ -16,6 +40,7 @@ std::string Config::defaultPath() {
|
|||||||
base = home ? std::string(home) + "/.config" : ".";
|
base = home ? std::string(home) + "/.config" : ".";
|
||||||
}
|
}
|
||||||
return base + "/baudline/settings.ini";
|
return base + "/baudline/settings.ini";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Config::resolvedPath(const std::string& path) const {
|
std::string Config::resolvedPath(const std::string& path) const {
|
||||||
@@ -23,8 +48,16 @@ std::string Config::resolvedPath(const std::string& path) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Config::load(const std::string& path) {
|
bool Config::load(const std::string& path) {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
char* raw = js_loadSettings();
|
||||||
|
if (!raw) return false;
|
||||||
|
std::string content(raw);
|
||||||
|
free(raw);
|
||||||
|
std::istringstream f(content);
|
||||||
|
#else
|
||||||
std::ifstream f(resolvedPath(path));
|
std::ifstream f(resolvedPath(path));
|
||||||
if (!f.is_open()) return false;
|
if (!f.is_open()) return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
data_.clear();
|
data_.clear();
|
||||||
std::string line;
|
std::string line;
|
||||||
@@ -42,6 +75,7 @@ bool Config::load(const std::string& path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __EMSCRIPTEN__
|
||||||
static void ensureDir(const std::string& path) {
|
static void ensureDir(const std::string& path) {
|
||||||
// Create parent directories.
|
// Create parent directories.
|
||||||
auto lastSlash = path.rfind('/');
|
auto lastSlash = path.rfind('/');
|
||||||
@@ -57,8 +91,17 @@ static void ensureDir(const std::string& path) {
|
|||||||
}
|
}
|
||||||
mkdir(dir.c_str(), 0755);
|
mkdir(dir.c_str(), 0755);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Config::save(const std::string& path) const {
|
bool Config::save(const std::string& path) const {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
std::ostringstream f;
|
||||||
|
f << "# Baudline settings\n";
|
||||||
|
for (const auto& [k, v] : data_)
|
||||||
|
f << k << " = " << v << "\n";
|
||||||
|
js_saveSettings(f.str().c_str());
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
std::string p = resolvedPath(path);
|
std::string p = resolvedPath(path);
|
||||||
ensureDir(p);
|
ensureDir(p);
|
||||||
std::ofstream f(p);
|
std::ofstream f(p);
|
||||||
@@ -68,6 +111,7 @@ bool Config::save(const std::string& path) const {
|
|||||||
for (const auto& [k, v] : data_)
|
for (const auto& [k, v] : data_)
|
||||||
f << k << " = " << v << "\n";
|
f << k << " = " << v << "\n";
|
||||||
return true;
|
return true;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::setString(const std::string& key, const std::string& value) { data_[key] = value; }
|
void Config::setString(const std::string& key, const std::string& value) { data_[key] = value; }
|
||||||
|
|||||||
@@ -1414,9 +1414,6 @@ void Application::renderMathPanel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::loadConfig() {
|
void Application::loadConfig() {
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
return; // No filesystem config on WASM
|
|
||||||
#endif
|
|
||||||
config_.load();
|
config_.load();
|
||||||
fftSizeIdx_ = config_.getInt("fft_size_idx", fftSizeIdx_);
|
fftSizeIdx_ = config_.getInt("fft_size_idx", fftSizeIdx_);
|
||||||
overlapPct_ = config_.getFloat("overlap_pct", overlapPct_);
|
overlapPct_ = config_.getFloat("overlap_pct", overlapPct_);
|
||||||
@@ -1458,9 +1455,6 @@ void Application::loadConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::saveConfig() const {
|
void Application::saveConfig() const {
|
||||||
#ifdef __EMSCRIPTEN__
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
Config cfg;
|
Config cfg;
|
||||||
cfg.setInt("fft_size_idx", fftSizeIdx_);
|
cfg.setInt("fft_size_idx", fftSizeIdx_);
|
||||||
cfg.setFloat("overlap_pct", overlapPct_);
|
cfg.setFloat("overlap_pct", overlapPct_);
|
||||||
|
|||||||
Reference in New Issue
Block a user