Allow wasm fetch patchstorage thigns, set system factory template
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
e389ca7469
commit
3af971534c
7 changed files with 248 additions and 38 deletions
|
@ -17,6 +17,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#define GHC_OS_DETECTED
|
||||
#define GHC_OS_LINUX
|
||||
#endif
|
||||
|
||||
#include_next <ghc/filesystem.hpp>
|
||||
|
|
|
@ -100,6 +100,10 @@ std::string getSpecialPath(const SpecialPath type)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
char* patchStorageSlug = nullptr;
|
||||
#endif
|
||||
|
||||
std::string homeDir()
|
||||
{
|
||||
# ifdef ARCH_WIN
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
# define REMOTE_HOST_PORT "2228"
|
||||
#endif
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
# define CARDINAL_IMPORTED_TEMPLATE_FILENAME "/imported.vcv"
|
||||
#endif
|
||||
|
||||
extern const std::string CARDINAL_VERSION;
|
||||
|
||||
namespace rack {
|
||||
|
@ -53,6 +57,10 @@ enum SpecialPath {
|
|||
std::string getSpecialPath(SpecialPath type);
|
||||
#endif
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
extern char* patchStorageSlug;
|
||||
#endif
|
||||
|
||||
} // namespace rack
|
||||
|
||||
namespace patchUtils {
|
||||
|
|
|
@ -34,24 +34,38 @@
|
|||
# undef DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBLO
|
||||
# ifdef HEADLESS
|
||||
# include <lo/lo.h>
|
||||
# include "extra/Thread.hpp"
|
||||
# endif
|
||||
# include "CardinalCommon.hpp"
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
# include <lo/lo.h>
|
||||
# include "extra/Thread.hpp"
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "CardinalCommon.hpp"
|
||||
#include "DistrhoPluginUtils.hpp"
|
||||
#include "PluginContext.hpp"
|
||||
#include "extra/Base64.hpp"
|
||||
|
||||
#ifndef DISTRHO_OS_WASM
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
# include <emscripten/emscripten.h>
|
||||
#else
|
||||
# include "extra/SharedResourcePointer.hpp"
|
||||
#endif
|
||||
|
||||
#if CARDINAL_VARIANT_FX
|
||||
# define CARDINAL_FACTORY_TEMPLATE_NAME "template-fx.vcv"
|
||||
#elif CARDINAL_VARIANT_SYNTH
|
||||
# define CARDINAL_FACTORY_TEMPLATE_NAME "template-synth.vcv"
|
||||
#else
|
||||
# define CARDINAL_FACTORY_TEMPLATE_NAME "template.vcv"
|
||||
#endif
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
# define CARDINAL_TEMPLATE_NAME "template-wasm.vcv"
|
||||
#else
|
||||
# define CARDINAL_TEMPLATE_NAME CARDINAL_FACTORY_TEMPLATE_NAME
|
||||
#endif
|
||||
|
||||
static const constexpr uint kCardinalStateBaseCount = 3; // patch, screenshot, comment
|
||||
|
||||
#ifndef HEADLESS
|
||||
|
@ -63,14 +77,6 @@ static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount + 2; /
|
|||
static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount;
|
||||
#endif
|
||||
|
||||
#if CARDINAL_VARIANT_FX
|
||||
# define CARDINAL_TEMPLATE_NAME "template-fx.vcv"
|
||||
#elif CARDINAL_VARIANT_SYNTH
|
||||
# define CARDINAL_TEMPLATE_NAME "template-synth.vcv"
|
||||
#else
|
||||
# define CARDINAL_TEMPLATE_NAME "template.vcv"
|
||||
#endif
|
||||
|
||||
namespace rack {
|
||||
namespace engine {
|
||||
void Engine_setAboutToClose(Engine*);
|
||||
|
@ -97,6 +103,21 @@ bool d_isDiffHigherThanLimit(const T& v1, const T& v2, const T& limit)
|
|||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
EM_JS(char*, getPatchStorageSlug, (), {
|
||||
var searchParams = new URLSearchParams(window.location.search);
|
||||
var patch = searchParams.get('patchstorage');
|
||||
if (!patch)
|
||||
return null;
|
||||
var length = lengthBytesUTF8(patch) + 1;
|
||||
var str = _malloc(length);
|
||||
stringToUTF8(patch, str, length);
|
||||
return str;
|
||||
});
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct Initializer
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
: public Thread
|
||||
|
@ -107,6 +128,7 @@ struct Initializer
|
|||
CardinalBasePlugin* oscPlugin = nullptr;
|
||||
#endif
|
||||
std::string templatePath;
|
||||
std::string factoryTemplatePath;
|
||||
|
||||
Initializer(const CardinalBasePlugin* const plugin)
|
||||
{
|
||||
|
@ -158,6 +180,7 @@ struct Initializer
|
|||
asset::bundlePath = system::join(resourcePath, "PluginManifests");
|
||||
asset::systemDir = resourcePath;
|
||||
templatePath = system::join(asset::systemDir, CARDINAL_TEMPLATE_NAME);
|
||||
factoryTemplatePath = system::join(asset::systemDir, CARDINAL_FACTORY_TEMPLATE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,6 +193,7 @@ struct Initializer
|
|||
if (system::exists(system::join(asset::systemDir, "res")))
|
||||
{
|
||||
templatePath = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR CARDINAL_TEMPLATE_NAME;
|
||||
factoryTemplatePath = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR CARDINAL_FACTORY_TEMPLATE_NAME;
|
||||
}
|
||||
// If source code dir does not exist use install target prefix as system dir
|
||||
else
|
||||
|
@ -187,17 +211,20 @@ struct Initializer
|
|||
asset::systemDir = CARDINAL_PLUGIN_PREFIX "/share/cardinal";
|
||||
#endif
|
||||
|
||||
if (! asset::systemDir.empty())
|
||||
{
|
||||
asset::bundlePath = system::join(asset::systemDir, "PluginManifests");
|
||||
templatePath = system::join(asset::systemDir, CARDINAL_TEMPLATE_NAME);
|
||||
}
|
||||
asset::bundlePath = system::join(asset::systemDir, "PluginManifests");
|
||||
templatePath = system::join(asset::systemDir, CARDINAL_TEMPLATE_NAME);
|
||||
factoryTemplatePath = system::join(asset::systemDir, CARDINAL_FACTORY_TEMPLATE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
asset::userDir = asset::systemDir;
|
||||
}
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
if ((patchStorageSlug = getPatchStorageSlug()) != nullptr)
|
||||
templatePath = CARDINAL_IMPORTED_TEMPLATE_FILENAME;
|
||||
#endif
|
||||
|
||||
// Log environment
|
||||
INFO("%s %s v%s", APP_NAME.c_str(), APP_EDITION.c_str(), APP_VERSION.c_str());
|
||||
INFO("%s", system::getOperatingSystemInfo().c_str());
|
||||
|
@ -206,6 +233,7 @@ struct Initializer
|
|||
INFO("System directory: %s", asset::systemDir.c_str());
|
||||
INFO("User directory: %s", asset::userDir.c_str());
|
||||
INFO("Template patch: %s", templatePath.c_str());
|
||||
INFO("System template patch: %s", factoryTemplatePath.c_str());
|
||||
|
||||
// Report to user if something is wrong with the installation
|
||||
if (asset::systemDir.empty())
|
||||
|
@ -564,6 +592,7 @@ public:
|
|||
context->patch = new rack::patch::Manager;
|
||||
context->patch->autosavePath = fAutosavePath;
|
||||
context->patch->templatePath = fInitializer->templatePath;
|
||||
context->patch->factoryTemplatePath = fInitializer->factoryTemplatePath;
|
||||
|
||||
context->event = new rack::widget::EventState;
|
||||
context->scene = new rack::app::Scene;
|
||||
|
@ -572,28 +601,33 @@ public:
|
|||
if (! isDummyInstance())
|
||||
context->window = new rack::window::Window;
|
||||
|
||||
context->patch->loadTemplate();
|
||||
context->scene->rackScroll->reset();
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
if (rack::patchStorageSlug == nullptr)
|
||||
#endif
|
||||
{
|
||||
context->patch->loadTemplate();
|
||||
context->scene->rackScroll->reset();
|
||||
}
|
||||
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
fInitializer->oscPlugin = this;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
~CardinalPlugin() override
|
||||
{
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
#if defined(HAVE_LIBLO) && defined(HEADLESS)
|
||||
fInitializer->oscPlugin = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{
|
||||
const ScopedContext sc(this);
|
||||
context->patch->clear();
|
||||
|
||||
// do a little dance to prevent context scene deletion from saving to temp dir
|
||||
#ifndef HEADLESS
|
||||
#ifndef HEADLESS
|
||||
const ScopedValueSetter<bool> svs(rack::settings::headless, true);
|
||||
#endif
|
||||
#endif
|
||||
Engine_setAboutToClose(context->engine);
|
||||
delete context;
|
||||
}
|
||||
|
|
|
@ -31,11 +31,12 @@
|
|||
#include <window/Window.hpp>
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
#include <ui/Button.hpp>
|
||||
#include <ui/Label.hpp>
|
||||
#include <ui/MenuOverlay.hpp>
|
||||
#include <ui/SequentialLayout.hpp>
|
||||
#include "CardinalCommon.hpp"
|
||||
# include <ui/Button.hpp>
|
||||
# include <ui/Label.hpp>
|
||||
# include <ui/MenuOverlay.hpp>
|
||||
# include <ui/SequentialLayout.hpp>
|
||||
# include "CardinalCommon.hpp"
|
||||
# include <emscripten/emscripten.h>
|
||||
#endif
|
||||
|
||||
#ifdef NDEBUG
|
||||
|
@ -189,6 +190,104 @@ struct WasmWelcomeDialog : rack::widget::OpaqueWidget
|
|||
Widget::draw(args);
|
||||
}
|
||||
};
|
||||
|
||||
struct WasmPatchStorageLoadingDialog : rack::widget::OpaqueWidget
|
||||
{
|
||||
static const constexpr float margin = 10;
|
||||
|
||||
rack::ui::MenuOverlay* overlay;
|
||||
|
||||
WasmPatchStorageLoadingDialog()
|
||||
{
|
||||
using rack::ui::Label;
|
||||
using rack::ui::MenuOverlay;
|
||||
using rack::ui::SequentialLayout;
|
||||
|
||||
box.size = rack::math::Vec(300, 50);
|
||||
|
||||
SequentialLayout* const layout = new SequentialLayout;
|
||||
layout->box.pos = rack::math::Vec(0, 0);
|
||||
layout->box.size = box.size;
|
||||
layout->orientation = SequentialLayout::VERTICAL_ORIENTATION;
|
||||
layout->margin = rack::math::Vec(margin, margin);
|
||||
layout->spacing = rack::math::Vec(margin, margin);
|
||||
layout->wrap = false;
|
||||
addChild(layout);
|
||||
|
||||
Label* const label = new Label;
|
||||
label->box.size.x = box.size.x - 2*margin;
|
||||
label->box.size.y = box.size.y - 2*margin - 40;
|
||||
label->fontSize = 16;
|
||||
label->text = "Load patch from PatchStorage...\n";
|
||||
layout->addChild(label);
|
||||
|
||||
overlay = new MenuOverlay;
|
||||
overlay->bgColor = nvgRGBAf(0, 0, 0, 0.33);
|
||||
overlay->addChild(this);
|
||||
APP->scene->addChild(overlay);
|
||||
}
|
||||
|
||||
void step() override
|
||||
{
|
||||
OpaqueWidget::step();
|
||||
box.pos = parent->box.size.minus(box.size).div(2).round();
|
||||
}
|
||||
|
||||
void draw(const DrawArgs& args) override
|
||||
{
|
||||
bndMenuBackground(args.vg, 0.0, 0.0, box.size.x, box.size.y, 0);
|
||||
Widget::draw(args);
|
||||
}
|
||||
};
|
||||
|
||||
static void downloadPatchStorageFailed(const char* const filename)
|
||||
{
|
||||
d_stdout("downloadPatchStorageFailed %s", filename);
|
||||
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
|
||||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context->ui);
|
||||
|
||||
if (ui->psDialog != nullptr)
|
||||
{
|
||||
ui->psDialog->overlay->requestDelete();
|
||||
asyncDialog::create("Failed to fetch patch from PatchStorage");
|
||||
}
|
||||
|
||||
using namespace rack;
|
||||
context->patch->templatePath = system::join(asset::systemDir, "template-synth.vcv"); // FIXME
|
||||
context->patch->loadTemplate();
|
||||
context->scene->rackScroll->reset();
|
||||
}
|
||||
|
||||
static void downloadPatchStorageSucceeded(const char* const filename)
|
||||
{
|
||||
d_stdout("downloadPatchStorageSucceeded %s | %s", filename, APP->patch->templatePath.c_str());
|
||||
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
|
||||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context->ui);
|
||||
|
||||
ui->psDialog->overlay->requestDelete();
|
||||
ui->psDialog = nullptr;
|
||||
|
||||
if (FILE* f = fopen(filename, "r"))
|
||||
{
|
||||
uint8_t buf[8] = {};
|
||||
fread(buf, 8, 1, f);
|
||||
d_stdout("read patch %x %x %x %x %x %x %x %x",
|
||||
buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7]);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
try {
|
||||
context->patch->load(CARDINAL_IMPORTED_TEMPLATE_FILENAME);
|
||||
} catch (rack::Exception& e) {
|
||||
const std::string message = rack::string::f("Could not load patch: %s", e.what());
|
||||
asyncDialog::create(message.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
context->scene->rackScroll->reset();
|
||||
context->patch->path = "";
|
||||
context->history->setSaved();
|
||||
}
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
@ -288,7 +387,21 @@ public:
|
|||
}
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
new WasmWelcomeDialog();
|
||||
if (rack::patchStorageSlug != nullptr)
|
||||
{
|
||||
std::string url("/patchstorage.php?slug=");
|
||||
url += rack::patchStorageSlug;
|
||||
std::free(rack::patchStorageSlug);
|
||||
rack::patchStorageSlug = nullptr;
|
||||
|
||||
psDialog = new WasmPatchStorageLoadingDialog();
|
||||
emscripten_async_wget(url.c_str(), context->patch->templatePath.c_str(),
|
||||
downloadPatchStorageSucceeded, downloadPatchStorageFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
new WasmWelcomeDialog();
|
||||
}
|
||||
#endif
|
||||
|
||||
context->window->step();
|
||||
|
|
|
@ -122,10 +122,6 @@ void handleHostParameterDrag(const CardinalPluginContext* pcontext, uint index,
|
|||
|
||||
// -----------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct CardinalAudioDevice;
|
||||
struct CardinalMidiInputDevice;
|
||||
struct CardinalMidiOutputDevice;
|
||||
|
||||
CardinalPluginContext* getRackContextFromPlugin(void* ptr);
|
||||
|
||||
class CardinalBasePlugin : public Plugin {
|
||||
|
@ -139,12 +135,18 @@ public:
|
|||
};
|
||||
|
||||
#ifndef HEADLESS
|
||||
struct WasmPatchStorageLoadingDialog;
|
||||
|
||||
class CardinalBaseUI : public UI {
|
||||
public:
|
||||
CardinalPluginContext* const context;
|
||||
bool saving;
|
||||
bool savingUncompressed;
|
||||
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
WasmPatchStorageLoadingDialog* psDialog;
|
||||
#endif
|
||||
|
||||
// for 3rd party modules
|
||||
std::function<void(char* path)> filebrowseraction;
|
||||
FileBrowserHandle filebrowserhandle;
|
||||
|
@ -154,6 +156,9 @@ public:
|
|||
context(getRackContextFromPlugin(getPluginInstancePointer())),
|
||||
saving(false),
|
||||
savingUncompressed(false),
|
||||
#ifdef DISTRHO_OS_WASM
|
||||
psDialog(nullptr),
|
||||
#endif
|
||||
filebrowseraction(),
|
||||
filebrowserhandle(nullptr)
|
||||
{
|
||||
|
|
43
src/emscripten/patchstorage.php
Normal file
43
src/emscripten/patchstorage.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
$slug = filter_input(INPUT_GET, 'slug', FILTER_SANITIZE_ENCODED);
|
||||
if (!$slug) { http_response_code(404); die(); }
|
||||
|
||||
$api = 'https://patchstorage.com/api/alpha';
|
||||
|
||||
$search = file_get_contents($api.'/patches?platform=7834&slug='.$slug);
|
||||
if (!$search) { http_response_code(404); die(); }
|
||||
|
||||
$searchJ = json_decode($search, true);
|
||||
if (!$searchJ) { http_response_code(404); die(); }
|
||||
if (!$searchJ[0]) { http_response_code(404); die(); }
|
||||
|
||||
$patchId = $searchJ[0]['id'];
|
||||
if (!$patchId) { http_response_code(404); die(); }
|
||||
|
||||
$patchDetails = file_get_contents($api.'/patches/'.$patchId);
|
||||
if (!$patchDetails) { http_response_code(404); die(); }
|
||||
|
||||
$patchDetailsJ = json_decode($patchDetails, true);
|
||||
if (!$patchDetailsJ) { http_response_code(404); die(); }
|
||||
|
||||
$patchFiles = $patchDetailsJ['files'];
|
||||
if (!$patchFiles) { http_response_code(404); die(); }
|
||||
|
||||
$patchFileDetails = $patchFiles[0];
|
||||
if (!$patchFileDetails) { http_response_code(404); die(); }
|
||||
if (!$patchFileDetails['filename']) { http_response_code(404); die(); }
|
||||
if (!$patchFileDetails['url']) { http_response_code(404); die(); }
|
||||
|
||||
$contents = file_get_contents($patchFileDetails['url']);
|
||||
if (!$contents) { http_response_code(404); die(); }
|
||||
|
||||
header('Content-Description: File Transfer');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="'.$patchFileDetails['filename'].'"');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate');
|
||||
header('Pragma: public');
|
||||
header('Content-Length: ' . strlen($contents));
|
||||
flush();
|
||||
die($contents);
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue