From e6a799cd4ce971755dcad8c206a7eb84bfded192 Mon Sep 17 00:00:00 2001 From: falkTX Date: Sun, 21 May 2023 04:39:27 +0200 Subject: [PATCH] Tweak wasm build, add persistent storage Signed-off-by: falkTX --- dpf | 2 +- plugins/Cardinal/src/AIDA-X.cpp | 6 +-- plugins/Cardinal/src/AudioFile.cpp | 4 +- src/CardinalCommon.cpp | 75 ++++++++++++++++++++++++++---- src/CardinalCommon.hpp | 1 + src/CardinalPlugin.cpp | 14 ++++++ src/CardinalUI.cpp | 11 ++++- src/Makefile.cardinal.mk | 1 + src/override/MenuBar.cpp | 72 +++++++++++++++++++--------- src/override/Scene.cpp | 2 - 10 files changed, 149 insertions(+), 39 deletions(-) diff --git a/dpf b/dpf index b4460be..802e446 160000 --- a/dpf +++ b/dpf @@ -1 +1 @@ -Subproject commit b4460beb094502c868dda5991e356623b13ce658 +Subproject commit 802e4460844b75b4c2a96c5a9f9baa791209f74e diff --git a/plugins/Cardinal/src/AIDA-X.cpp b/plugins/Cardinal/src/AIDA-X.cpp index eecb162..0e294a9 100644 --- a/plugins/Cardinal/src/AIDA-X.cpp +++ b/plugins/Cardinal/src/AIDA-X.cpp @@ -892,8 +892,8 @@ struct AidaWidget : ModuleWidgetWithSideScrews<23> { heightPedal, cornerRadius, cornerRadius, - nvgRGBA(0,0,0,1.f), - nvgRGBA(0,0,0,0.f))); + nvgRGBAf(0,0,0,1.f), + nvgRGBAf(0,0,0,0.f))); nvgFill(args.vg); // .rt-neural .grid @@ -916,7 +916,7 @@ struct AidaWidget : ModuleWidgetWithSideScrews<23> { nvgFill(args.vg); // extra - nvgStrokeColor(args.vg, nvgRGBA(150, 150, 150, 0.25f)); + nvgStrokeColor(args.vg, nvgRGBA(150, 150, 150, 60)); nvgStroke(args.vg); drawOutputJacksArea(args.vg); diff --git a/plugins/Cardinal/src/AudioFile.cpp b/plugins/Cardinal/src/AudioFile.cpp index c52b4db..908ba91 100644 --- a/plugins/Cardinal/src/AudioFile.cpp +++ b/plugins/Cardinal/src/AudioFile.cpp @@ -471,10 +471,10 @@ struct AudioFileListWidget : ImGuiWidget { selectedFile = (size_t)-1; static constexpr const char* const supportedExtensions[] = { - #ifdef HAVE_SNDFILE + #ifdef HAVE_SNDFILE ".aif",".aifc",".aiff",".au",".bwf",".flac",".htk",".iff",".mat4",".mat5",".oga",".ogg",".opus", ".paf",".pvf",".pvf5",".sd2",".sf",".snd",".svx",".vcc",".w64",".wav",".xi", - #endif + #endif ".mp3" }; diff --git a/src/CardinalCommon.cpp b/src/CardinalCommon.cpp index 16c04d1..24eb93f 100644 --- a/src/CardinalCommon.cpp +++ b/src/CardinalCommon.cpp @@ -89,9 +89,9 @@ #ifdef DISTRHO_OS_WASM # if CARDINAL_VARIANT_MINI -# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm-mini.vcv" +# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm-mini" # else -# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm.vcv" +# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm" # endif #endif @@ -374,6 +374,17 @@ static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv, } #endif +// ----------------------------------------------------------------------------------------------------------- + +#ifdef DISTRHO_OS_WASM +static void WebBrowserDataLoaded(void* const data) +{ + static_cast(data)->loadSettings(true); +} +#endif + +// ----------------------------------------------------------------------------------------------------------- + Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalBaseUI* const ui) { using namespace rack; @@ -490,7 +501,17 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB #endif if (isRealInstance) + { + #ifdef DISTRHO_OS_WASM + EM_ASM({ + Module.FS.mkdir('/userfiles'); + Module.FS.mount(Module.IDBFS, {}, '/userfiles'); + Module.FS.syncfs(true, function(err) { if (!err) { dynCall('vi', $0, [$1]) } }); + }, WebBrowserDataLoaded, this); + #else system::createDirectory(asset::userDir); + #endif + } } #ifndef CARDINAL_COMMON_DSP_ONLY @@ -513,13 +534,11 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB if (settings::settingsPath.empty()) settings::settingsPath = asset::config(CARDINAL_VARIANT_NAME ".json"); - const std::string patchesPath = asset::patchesPath(); + templatePath = asset::user("templates/" CARDINAL_VARIANT_NAME ".vcv"); #ifdef DISTRHO_OS_WASM - templatePath = system::join(patchesPath, CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME ".vcv"); - factoryTemplatePath = system::join(patchesPath, "templates/" CARDINAL_VARIANT_NAME ".vcv"); + factoryTemplatePath = system::join(asset::patchesPath(), CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME ".vcv"); #else - templatePath = asset::user("templates/" CARDINAL_VARIANT_NAME ".vcv"); - factoryTemplatePath = system::join(patchesPath, "templates/" CARDINAL_VARIANT_NAME ".vcv"); + factoryTemplatePath = system::join(asset::patchesPath(), "templates/" CARDINAL_VARIANT_NAME ".vcv"); #endif // Log environment @@ -672,7 +691,8 @@ bool isMini() bool isStandalone() { - return std::strstr(getPluginFormatName(), "Standalone") != nullptr; + static const bool standalone = std::strstr(getPluginFormatName(), "Standalone") != nullptr; + return standalone; } #ifdef ARCH_WIN @@ -712,6 +732,15 @@ std::string getSpecialPath(const SpecialPath type) char* patchFromURL = nullptr; char* patchRemoteURL = nullptr; char* patchStorageSlug = nullptr; + +void syncfs() +{ + settings::save(); + + EM_ASM({ + Module.FS.syncfs(false, function(){} ); + }); +} #endif std::string homeDir() @@ -783,6 +812,10 @@ void loadPathDialog(const std::string& path, const bool asTemplate) APP->history->setSaved(); } + #ifdef DISTRHO_OS_WASM + syncfs(); + #endif + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) if (remoteDetails->autoDeploy) remoteUtils::sendFullPatchToRemote(remoteDetails); @@ -812,6 +845,10 @@ void loadSelectionDialog() std::free(pathC); + #ifdef DISTRHO_OS_WASM + syncfs(); + #endif + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) if (remoteDetails->autoDeploy) remoteUtils::sendFullPatchToRemote(remoteDetails); @@ -839,6 +876,10 @@ void loadTemplate(const bool factory) APP->patch->path.clear(); APP->history->setSaved(); + #ifdef DISTRHO_OS_WASM + syncfs(); + #endif + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) if (remoteDetails->autoDeploy) remoteUtils::sendFullPatchToRemote(remoteDetails); @@ -862,6 +903,10 @@ void revertDialog() promptClear("Revert patch to the last saved state?", []{ APP->patch->loadAction(APP->patch->path); + #ifdef DISTRHO_OS_WASM + syncfs(); + #endif + if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) if (remoteDetails->autoDeploy) remoteUtils::sendFullPatchToRemote(remoteDetails); @@ -886,6 +931,14 @@ void saveDialog(const std::string& path) asyncDialog::create(string::f("Could not save patch: %s", e.what()).c_str()); return; } + + APP->patch->pushRecentPath(path); + + #ifdef DISTRHO_OS_WASM + syncfs(); + #else + rack::settings::save(); + #endif #endif } @@ -944,7 +997,11 @@ void saveTemplateDialog() catch (Exception& e) { asyncDialog::create(string::f("Could not save template patch: %s", e.what()).c_str()); return; - } + } + + #ifdef DISTRHO_OS_WASM + syncfs(); + #endif }); } diff --git a/src/CardinalCommon.hpp b/src/CardinalCommon.hpp index 6fa736f..a1693a4 100644 --- a/src/CardinalCommon.hpp +++ b/src/CardinalCommon.hpp @@ -53,6 +53,7 @@ std::string getSpecialPath(SpecialPath type); extern char* patchFromURL; extern char* patchRemoteURL; extern char* patchStorageSlug; +void syncfs(); #endif std::string homeDir(); diff --git a/src/CardinalPlugin.cpp b/src/CardinalPlugin.cpp index db5ab1a..7155f9a 100644 --- a/src/CardinalPlugin.cpp +++ b/src/CardinalPlugin.cpp @@ -66,6 +66,11 @@ namespace app { rack::widget::Widget* createMenuBar() { return new rack::widget::Widget; } } #endif +#ifdef DISTRHO_OS_WASM +namespace asset { +std::string patchesPath(); +} +#endif namespace engine { void Engine_setAboutToClose(Engine*); } @@ -312,6 +317,15 @@ public: context->scene->rackScroll->reset(); } + #ifdef DISTRHO_OS_WASM + // switch factory template to regular one after first load + #if CARDINAL_VARIANT_MINI + context->patch->factoryTemplatePath = rack::system::join(rack::asset::patchesPath(), "templates/mini.vcv"); + #else + context->patch->factoryTemplatePath = rack::system::join(rack::asset::patchesPath(), "templates/main.vcv"); + #endif + #endif + #ifdef CARDINAL_INIT_OSC_THREAD fInitializer->remotePluginInstance = this; #endif diff --git a/src/CardinalUI.cpp b/src/CardinalUI.cpp index b28f216..f5131f4 100644 --- a/src/CardinalUI.cpp +++ b/src/CardinalUI.cpp @@ -62,6 +62,11 @@ #endif namespace rack { +#ifdef DISTRHO_OS_WASM +namespace asset { +std::string patchesPath(); +} +#endif namespace engine { void Engine_setAboutToClose(Engine*); void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); @@ -246,7 +251,7 @@ static void downloadRemotePatchFailed(const char* const filename) } using namespace rack; - context->patch->templatePath = system::join(asset::systemDir, "init/wasm.vcv"); // FIXME + context->patch->templatePath = rack::system::join(asset::patchesPath(), "templates/main.vcv"); context->patch->loadTemplate(); context->scene->rackScroll->reset(); } @@ -1228,7 +1233,11 @@ protected: context->patch->pushRecentPath(sfilename); context->history->setSaved(); + #ifdef DISTRHO_OS_WASM + rack::syncfs(); + #else rack::settings::save(); + #endif } #if 0 diff --git a/src/Makefile.cardinal.mk b/src/Makefile.cardinal.mk index c7140ee..4003ddd 100644 --- a/src/Makefile.cardinal.mk +++ b/src/Makefile.cardinal.mk @@ -283,6 +283,7 @@ LINK_FLAGS += -O3 LINK_FLAGS += -sALLOW_MEMORY_GROWTH LINK_FLAGS += -sINITIAL_MEMORY=64Mb LINK_FLAGS += -sLZ4=1 +LINK_FLAGS += -lidbfs.js ifeq ($(CARDINAL_VARIANT),mini) LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources diff --git a/src/override/MenuBar.cpp b/src/override/MenuBar.cpp index 1ae8c99..d273997 100644 --- a/src/override/MenuBar.cpp +++ b/src/override/MenuBar.cpp @@ -56,6 +56,11 @@ #include "DistrhoPlugin.hpp" #include "DistrhoStandaloneUtils.hpp" +#ifdef DISTRHO_OS_WASM +# include +# undef HAVE_LIBLO +#endif + #ifdef HAVE_LIBLO # include #endif @@ -98,6 +103,28 @@ struct FileButton : MenuButton { const bool isStandalone; std::vector demoPatches; +#ifdef DISTRHO_OS_WASM + static void WebBrowserDataSaved(const int err) + { + err ? async_dialog_message("Error, could not save web browser data!") + : async_dialog_message("Web browser data saved!"); + } + + static void wasmSaveAs() + { + async_dialog_text_input("Filename", nullptr, [](char* const filename) { + if (filename == nullptr) + return; + APP->patch->path = "/userfiles/"; + APP->patch->path += filename; + if (rack::system::getExtension(filename) != ".vcv") + APP->patch->path += ".vcv"; + patchUtils::saveDialog(APP->patch->path); + std::free(filename); + }); + } +#endif + FileButton(const bool standalone) : MenuButton(), isStandalone(standalone) { @@ -131,7 +158,6 @@ struct FileButton : MenuButton { })); #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS -#ifndef DISTRHO_OS_WASM menu->addChild(createMenuItem("New (factory template)", "", []() { patchUtils::loadTemplateDialog(true); })); @@ -149,6 +175,11 @@ struct FileButton : MenuButton { } }, settings::recentPatchPaths.empty())); + menu->addChild(createMenuItem("Import selection...", "", [=]() { + patchUtils::loadSelectionDialog(); + }, false, true)); + +#ifndef DISTRHO_OS_WASM menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { // NOTE: will do nothing if path is empty, intentionally patchUtils::saveDialog(APP->patch->path); @@ -158,13 +189,16 @@ struct FileButton : MenuButton { patchUtils::saveAsDialog(); })); #else - menu->addChild(createMenuItem("Import patch...", RACK_MOD_CTRL_NAME "+O", []() { - patchUtils::loadDialog(); + menu->addChild(createMenuItem("Save", "", []() { + if (APP->patch->path.empty()) + wasmSaveAs(); + else + patchUtils::saveDialog(APP->patch->path); })); - menu->addChild(createMenuItem("Import selection...", "", [=]() { - patchUtils::loadSelectionDialog(); - }, false, true)); + menu->addChild(createMenuItem("Save as", "", []() { + wasmSaveAs(); + })); menu->addChild(createMenuItem("Save and download compressed", RACK_MOD_CTRL_NAME "+Shift+S", []() { patchUtils::saveAsDialog(); @@ -184,6 +218,17 @@ struct FileButton : MenuButton { patchUtils::saveTemplateDialog(); })); +#ifdef DISTRHO_OS_WASM + menu->addChild(new ui::MenuSeparator); + + menu->addChild(createMenuItem("Save persistent browser data", "", []() { + settings::save(); + EM_ASM({ + Module.FS.syncfs(false, function(err){ dynCall('vi', $0, [!!err]) }); + }, WebBrowserDataSaved); + })); +#endif + #if defined(HAVE_LIBLO) || ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS #ifdef __MOD_DEVICES__ #define REMOTE_NAME "MOD" @@ -213,21 +258,6 @@ struct FileButton : MenuButton { } #endif -#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS -#ifndef DISTRHO_OS_WASM - menu->addChild(new ui::MenuSeparator); - - // Load selection - menu->addChild(createMenuItem("Import selection...", "", [=]() { - patchUtils::loadSelectionDialog(); - }, false, true)); - - menu->addChild(createMenuItem("Export uncompressed json...", "", []() { - patchUtils::saveAsDialogUncompressed(); - })); -#endif -#endif - if (!demoPatches.empty()) { menu->addChild(new ui::MenuSeparator); diff --git a/src/override/Scene.cpp b/src/override/Scene.cpp index fcb2317..5ddf14d 100644 --- a/src/override/Scene.cpp +++ b/src/override/Scene.cpp @@ -276,13 +276,11 @@ void Scene::onHoverKey(const HoverKeyEvent& e) { patchUtils::revertDialog(); e.consume(this); } -#ifndef DISTRHO_OS_WASM if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { // NOTE: will do nothing if path is empty, intentionally patchUtils::saveDialog(APP->patch->path); e.consume(this); } -#endif if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { patchUtils::saveAsDialog(); e.consume(this);