Signed-off-by: falkTX <falktx@falktx.com>tags/23.07
@@ -1 +1 @@ | |||||
Subproject commit b4460beb094502c868dda5991e356623b13ce658 | |||||
Subproject commit 802e4460844b75b4c2a96c5a9f9baa791209f74e |
@@ -892,8 +892,8 @@ struct AidaWidget : ModuleWidgetWithSideScrews<23> { | |||||
heightPedal, | heightPedal, | ||||
cornerRadius, | cornerRadius, | ||||
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); | nvgFill(args.vg); | ||||
// .rt-neural .grid | // .rt-neural .grid | ||||
@@ -916,7 +916,7 @@ struct AidaWidget : ModuleWidgetWithSideScrews<23> { | |||||
nvgFill(args.vg); | nvgFill(args.vg); | ||||
// extra | // extra | ||||
nvgStrokeColor(args.vg, nvgRGBA(150, 150, 150, 0.25f)); | |||||
nvgStrokeColor(args.vg, nvgRGBA(150, 150, 150, 60)); | |||||
nvgStroke(args.vg); | nvgStroke(args.vg); | ||||
drawOutputJacksArea(args.vg); | drawOutputJacksArea(args.vg); | ||||
@@ -471,10 +471,10 @@ struct AudioFileListWidget : ImGuiWidget { | |||||
selectedFile = (size_t)-1; | selectedFile = (size_t)-1; | ||||
static constexpr const char* const supportedExtensions[] = { | 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", | ".aif",".aifc",".aiff",".au",".bwf",".flac",".htk",".iff",".mat4",".mat5",".oga",".ogg",".opus", | ||||
".paf",".pvf",".pvf5",".sd2",".sf",".snd",".svx",".vcc",".w64",".wav",".xi", | ".paf",".pvf",".pvf5",".sd2",".sf",".snd",".svx",".vcc",".w64",".wav",".xi", | ||||
#endif | |||||
#endif | |||||
".mp3" | ".mp3" | ||||
}; | }; | ||||
@@ -89,9 +89,9 @@ | |||||
#ifdef DISTRHO_OS_WASM | #ifdef DISTRHO_OS_WASM | ||||
# if CARDINAL_VARIANT_MINI | # if CARDINAL_VARIANT_MINI | ||||
# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm-mini.vcv" | |||||
# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm-mini" | |||||
# else | # else | ||||
# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm.vcv" | |||||
# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm" | |||||
# endif | # endif | ||||
#endif | #endif | ||||
@@ -374,6 +374,17 @@ static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv, | |||||
} | } | ||||
#endif | #endif | ||||
// ----------------------------------------------------------------------------------------------------------- | |||||
#ifdef DISTRHO_OS_WASM | |||||
static void WebBrowserDataLoaded(void* const data) | |||||
{ | |||||
static_cast<Initializer*>(data)->loadSettings(true); | |||||
} | |||||
#endif | |||||
// ----------------------------------------------------------------------------------------------------------- | |||||
Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalBaseUI* const ui) | Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalBaseUI* const ui) | ||||
{ | { | ||||
using namespace rack; | using namespace rack; | ||||
@@ -490,7 +501,17 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB | |||||
#endif | #endif | ||||
if (isRealInstance) | 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); | system::createDirectory(asset::userDir); | ||||
#endif | |||||
} | |||||
} | } | ||||
#ifndef CARDINAL_COMMON_DSP_ONLY | #ifndef CARDINAL_COMMON_DSP_ONLY | ||||
@@ -513,13 +534,11 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB | |||||
if (settings::settingsPath.empty()) | if (settings::settingsPath.empty()) | ||||
settings::settingsPath = asset::config(CARDINAL_VARIANT_NAME ".json"); | 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 | #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 | #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 | #endif | ||||
// Log environment | // Log environment | ||||
@@ -672,7 +691,8 @@ bool isMini() | |||||
bool isStandalone() | bool isStandalone() | ||||
{ | { | ||||
return std::strstr(getPluginFormatName(), "Standalone") != nullptr; | |||||
static const bool standalone = std::strstr(getPluginFormatName(), "Standalone") != nullptr; | |||||
return standalone; | |||||
} | } | ||||
#ifdef ARCH_WIN | #ifdef ARCH_WIN | ||||
@@ -712,6 +732,15 @@ std::string getSpecialPath(const SpecialPath type) | |||||
char* patchFromURL = nullptr; | char* patchFromURL = nullptr; | ||||
char* patchRemoteURL = nullptr; | char* patchRemoteURL = nullptr; | ||||
char* patchStorageSlug = nullptr; | char* patchStorageSlug = nullptr; | ||||
void syncfs() | |||||
{ | |||||
settings::save(); | |||||
EM_ASM({ | |||||
Module.FS.syncfs(false, function(){} ); | |||||
}); | |||||
} | |||||
#endif | #endif | ||||
std::string homeDir() | std::string homeDir() | ||||
@@ -783,6 +812,10 @@ void loadPathDialog(const std::string& path, const bool asTemplate) | |||||
APP->history->setSaved(); | APP->history->setSaved(); | ||||
} | } | ||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#endif | |||||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | ||||
if (remoteDetails->autoDeploy) | if (remoteDetails->autoDeploy) | ||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | remoteUtils::sendFullPatchToRemote(remoteDetails); | ||||
@@ -812,6 +845,10 @@ void loadSelectionDialog() | |||||
std::free(pathC); | std::free(pathC); | ||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#endif | |||||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | ||||
if (remoteDetails->autoDeploy) | if (remoteDetails->autoDeploy) | ||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | remoteUtils::sendFullPatchToRemote(remoteDetails); | ||||
@@ -839,6 +876,10 @@ void loadTemplate(const bool factory) | |||||
APP->patch->path.clear(); | APP->patch->path.clear(); | ||||
APP->history->setSaved(); | APP->history->setSaved(); | ||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#endif | |||||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | ||||
if (remoteDetails->autoDeploy) | if (remoteDetails->autoDeploy) | ||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | remoteUtils::sendFullPatchToRemote(remoteDetails); | ||||
@@ -862,6 +903,10 @@ void revertDialog() | |||||
promptClear("Revert patch to the last saved state?", []{ | promptClear("Revert patch to the last saved state?", []{ | ||||
APP->patch->loadAction(APP->patch->path); | APP->patch->loadAction(APP->patch->path); | ||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#endif | |||||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) | ||||
if (remoteDetails->autoDeploy) | if (remoteDetails->autoDeploy) | ||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | 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()); | asyncDialog::create(string::f("Could not save patch: %s", e.what()).c_str()); | ||||
return; | return; | ||||
} | } | ||||
APP->patch->pushRecentPath(path); | |||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#else | |||||
rack::settings::save(); | |||||
#endif | |||||
#endif | #endif | ||||
} | } | ||||
@@ -944,7 +997,11 @@ void saveTemplateDialog() | |||||
catch (Exception& e) { | catch (Exception& e) { | ||||
asyncDialog::create(string::f("Could not save template patch: %s", e.what()).c_str()); | asyncDialog::create(string::f("Could not save template patch: %s", e.what()).c_str()); | ||||
return; | return; | ||||
} | |||||
} | |||||
#ifdef DISTRHO_OS_WASM | |||||
syncfs(); | |||||
#endif | |||||
}); | }); | ||||
} | } | ||||
@@ -53,6 +53,7 @@ std::string getSpecialPath(SpecialPath type); | |||||
extern char* patchFromURL; | extern char* patchFromURL; | ||||
extern char* patchRemoteURL; | extern char* patchRemoteURL; | ||||
extern char* patchStorageSlug; | extern char* patchStorageSlug; | ||||
void syncfs(); | |||||
#endif | #endif | ||||
std::string homeDir(); | std::string homeDir(); | ||||
@@ -66,6 +66,11 @@ namespace app { | |||||
rack::widget::Widget* createMenuBar() { return new rack::widget::Widget; } | rack::widget::Widget* createMenuBar() { return new rack::widget::Widget; } | ||||
} | } | ||||
#endif | #endif | ||||
#ifdef DISTRHO_OS_WASM | |||||
namespace asset { | |||||
std::string patchesPath(); | |||||
} | |||||
#endif | |||||
namespace engine { | namespace engine { | ||||
void Engine_setAboutToClose(Engine*); | void Engine_setAboutToClose(Engine*); | ||||
} | } | ||||
@@ -312,6 +317,15 @@ public: | |||||
context->scene->rackScroll->reset(); | 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 | #ifdef CARDINAL_INIT_OSC_THREAD | ||||
fInitializer->remotePluginInstance = this; | fInitializer->remotePluginInstance = this; | ||||
#endif | #endif | ||||
@@ -62,6 +62,11 @@ | |||||
#endif | #endif | ||||
namespace rack { | namespace rack { | ||||
#ifdef DISTRHO_OS_WASM | |||||
namespace asset { | |||||
std::string patchesPath(); | |||||
} | |||||
#endif | |||||
namespace engine { | namespace engine { | ||||
void Engine_setAboutToClose(Engine*); | void Engine_setAboutToClose(Engine*); | ||||
void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); | void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); | ||||
@@ -246,7 +251,7 @@ static void downloadRemotePatchFailed(const char* const filename) | |||||
} | } | ||||
using namespace rack; | 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->patch->loadTemplate(); | ||||
context->scene->rackScroll->reset(); | context->scene->rackScroll->reset(); | ||||
} | } | ||||
@@ -1228,7 +1233,11 @@ protected: | |||||
context->patch->pushRecentPath(sfilename); | context->patch->pushRecentPath(sfilename); | ||||
context->history->setSaved(); | context->history->setSaved(); | ||||
#ifdef DISTRHO_OS_WASM | |||||
rack::syncfs(); | |||||
#else | |||||
rack::settings::save(); | rack::settings::save(); | ||||
#endif | |||||
} | } | ||||
#if 0 | #if 0 | ||||
@@ -283,6 +283,7 @@ LINK_FLAGS += -O3 | |||||
LINK_FLAGS += -sALLOW_MEMORY_GROWTH | LINK_FLAGS += -sALLOW_MEMORY_GROWTH | ||||
LINK_FLAGS += -sINITIAL_MEMORY=64Mb | LINK_FLAGS += -sINITIAL_MEMORY=64Mb | ||||
LINK_FLAGS += -sLZ4=1 | LINK_FLAGS += -sLZ4=1 | ||||
LINK_FLAGS += -lidbfs.js | |||||
ifeq ($(CARDINAL_VARIANT),mini) | ifeq ($(CARDINAL_VARIANT),mini) | ||||
LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources | LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources | ||||
@@ -56,6 +56,11 @@ | |||||
#include "DistrhoPlugin.hpp" | #include "DistrhoPlugin.hpp" | ||||
#include "DistrhoStandaloneUtils.hpp" | #include "DistrhoStandaloneUtils.hpp" | ||||
#ifdef DISTRHO_OS_WASM | |||||
# include <emscripten/emscripten.h> | |||||
# undef HAVE_LIBLO | |||||
#endif | |||||
#ifdef HAVE_LIBLO | #ifdef HAVE_LIBLO | ||||
# include <lo/lo.h> | # include <lo/lo.h> | ||||
#endif | #endif | ||||
@@ -98,6 +103,28 @@ struct FileButton : MenuButton { | |||||
const bool isStandalone; | const bool isStandalone; | ||||
std::vector<std::string> demoPatches; | std::vector<std::string> 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) | FileButton(const bool standalone) | ||||
: MenuButton(), isStandalone(standalone) | : MenuButton(), isStandalone(standalone) | ||||
{ | { | ||||
@@ -131,7 +158,6 @@ struct FileButton : MenuButton { | |||||
})); | })); | ||||
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | #if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
#ifndef DISTRHO_OS_WASM | |||||
menu->addChild(createMenuItem("New (factory template)", "", []() { | menu->addChild(createMenuItem("New (factory template)", "", []() { | ||||
patchUtils::loadTemplateDialog(true); | patchUtils::loadTemplateDialog(true); | ||||
})); | })); | ||||
@@ -149,6 +175,11 @@ struct FileButton : MenuButton { | |||||
} | } | ||||
}, settings::recentPatchPaths.empty())); | }, 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", []() { | menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { | ||||
// NOTE: will do nothing if path is empty, intentionally | // NOTE: will do nothing if path is empty, intentionally | ||||
patchUtils::saveDialog(APP->patch->path); | patchUtils::saveDialog(APP->patch->path); | ||||
@@ -158,13 +189,16 @@ struct FileButton : MenuButton { | |||||
patchUtils::saveAsDialog(); | patchUtils::saveAsDialog(); | ||||
})); | })); | ||||
#else | #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", []() { | menu->addChild(createMenuItem("Save and download compressed", RACK_MOD_CTRL_NAME "+Shift+S", []() { | ||||
patchUtils::saveAsDialog(); | patchUtils::saveAsDialog(); | ||||
@@ -184,6 +218,17 @@ struct FileButton : MenuButton { | |||||
patchUtils::saveTemplateDialog(); | 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 | #if defined(HAVE_LIBLO) || ! DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | ||||
#ifdef __MOD_DEVICES__ | #ifdef __MOD_DEVICES__ | ||||
#define REMOTE_NAME "MOD" | #define REMOTE_NAME "MOD" | ||||
@@ -213,21 +258,6 @@ struct FileButton : MenuButton { | |||||
} | } | ||||
#endif | #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()) | if (!demoPatches.empty()) | ||||
{ | { | ||||
menu->addChild(new ui::MenuSeparator); | menu->addChild(new ui::MenuSeparator); | ||||
@@ -276,13 +276,11 @@ void Scene::onHoverKey(const HoverKeyEvent& e) { | |||||
patchUtils::revertDialog(); | patchUtils::revertDialog(); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
#ifndef DISTRHO_OS_WASM | |||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
// NOTE: will do nothing if path is empty, intentionally | // NOTE: will do nothing if path is empty, intentionally | ||||
patchUtils::saveDialog(APP->patch->path); | patchUtils::saveDialog(APP->patch->path); | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
#endif | |||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { | ||||
patchUtils::saveAsDialog(); | patchUtils::saveAsDialog(); | ||||
e.consume(this); | e.consume(this); | ||||