More mini details, fake audio runs, set host param values

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2022-12-29 23:58:16 +00:00
parent d0eba9e1ae
commit 5e73b8c227
No known key found for this signature in database
GPG key ID: CDBAA37ABC74FBA0
14 changed files with 427 additions and 127 deletions

View file

@ -16,4 +16,4 @@
*/
#define CARDINAL_COMMON_UI_ONLY
#include "CardinalCommon.cpp"
#include "../CardinalCommon.cpp"

View file

@ -39,8 +39,8 @@
#define DISTRHO_UI_FILE_BROWSER 1
#define DISTRHO_UI_USE_NANOVG 1
#define DISTRHO_UI_USER_RESIZABLE 1
#define DISTRHO_UI_DEFAULT_WIDTH 1228
#define DISTRHO_UI_DEFAULT_HEIGHT 666
#define DISTRHO_UI_DEFAULT_WIDTH 1000
#define DISTRHO_UI_DEFAULT_HEIGHT 600
#define DISTRHO_PLUGIN_IS_SYNTH 0
#define DISTRHO_PLUGIN_NUM_INPUTS CARDINAL_NUM_AUDIO_INPUTS
#define DISTRHO_PLUGIN_NUM_OUTPUTS CARDINAL_NUM_AUDIO_OUTPUTS

View file

@ -52,7 +52,7 @@
static const constexpr uint kCardinalStateBaseCount = 3; // patch, screenshot, comment
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
# include "extra/ScopedValueSetter.hpp"
# include "WindowParameters.hpp"
static const constexpr uint kCardinalStateCount = kCardinalStateBaseCount + 2; // moduleInfos, windowSize
@ -163,7 +163,7 @@ class CardinalPlugin : public CardinalBasePlugin
struct {
String comment;
String screenshot;
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
String windowSize;
#endif
} fState;
@ -172,7 +172,7 @@ class CardinalPlugin : public CardinalBasePlugin
bool fWasBypassed;
MidiEvent bypassMidiEvents[16];
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
// real values, not VCV interpreted ones
float fWindowParameters[kWindowParameterCount];
#endif
@ -191,7 +191,7 @@ public:
fNextExpectedFrame(0),
fWasBypassed(false)
{
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
fWindowParameters[kWindowParameterShowTooltips] = 1.0f;
fWindowParameters[kWindowParameterCableOpacity] = 50.0f;
fWindowParameters[kWindowParameterCableTension] = 75.0f;
@ -290,7 +290,7 @@ public:
context->patch->clear();
// do a little dance to prevent context scene deletion from saving to temp dir
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
const ScopedValueSetter<bool> svs(rack::settings::headless, true);
#endif
Engine_setAboutToClose(context->engine);
@ -419,6 +419,10 @@ protected:
parameter.symbol += String(index + 1);
parameter.unit = "v";
parameter.hints = kParameterIsAutomatable;
#if CARDINAL_VARIANT_MINI
// TODO is hidden
// parameter.hints |= kParameterIsAutomatable;
#endif
parameter.ranges.def = 0.0f;
parameter.ranges.min = 0.0f;
parameter.ranges.max = 10.0f;
@ -431,7 +435,7 @@ protected:
return;
}
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
switch (index - kModuleParameters - 1)
{
case kWindowParameterShowTooltips:
@ -610,7 +614,11 @@ protected:
switch (index)
{
case 0:
#if CARDINAL_VARIANT_MINI
state.hints = kStateIsHostWritable;
#else
state.hints = kStateIsBase64Blob;
#endif
#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
state.hints |= kStateIsOnlyForDSP;
#endif
@ -620,11 +628,16 @@ protected:
if (const long fileSize = std::ftell(f))
{
std::fseek(f, 0, SEEK_SET);
char* const fileContent = new char[fileSize];
char* const fileContent = new char[fileSize+1];
if (std::fread(fileContent, fileSize, 1, f) == 1)
{
fileContent[fileSize] = '\0';
#if CARDINAL_VARIANT_MINI
state.defaultValue = fileContent;
#else
state.defaultValue = String::asBase64(fileContent, fileSize);
#endif
}
delete[] fileContent;
@ -675,7 +688,7 @@ protected:
if (index == kModuleParameters)
return context->bypassed ? 1.0f : 0.0f;
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
// window related parameters
index -= kModuleParameters + 1;
@ -702,7 +715,7 @@ protected:
return;
}
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
// window related parameters
index -= kModuleParameters + 1;
@ -716,7 +729,7 @@ protected:
String getState(const char* const key) const override
{
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
if (std::strcmp(key, "moduleInfos") == 0)
{
json_t* const rootJ = json_object();
@ -784,9 +797,12 @@ protected:
context->patch->cleanAutosave();
// context->history->setSaved();
#if CARDINAL_VARIANT_MINI
#else
try {
data = rack::system::archiveDirectory(fAutosavePath, 1);
} DISTRHO_SAFE_EXCEPTION_RETURN("getState archiveDirectory", String());
#endif
}
return String::asBase64(data.data(), data.size());
@ -797,10 +813,10 @@ protected:
#if CARDINAL_VARIANT_MINI
if (std::strcmp(key, "param") == 0)
{
int64_t moduleId = 0;
longlong moduleId = 0;
int paramId = 0;
float paramValue = 0.f;
std::sscanf(value, "%lu:%d:%f", &moduleId, &paramId, &paramValue);
std::sscanf(value, "%lld:%d:%f", &moduleId, &paramId, &paramValue);
rack::engine::Module* const module = context->engine->getModule(moduleId);
DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,);
@ -810,7 +826,7 @@ protected:
}
#endif
#ifndef HEADLESS
#if CARDINAL_VARIANT_MINI || !defined(HEADLESS)
if (std::strcmp(key, "moduleInfos") == 0)
{
json_error_t error;
@ -869,6 +885,16 @@ protected:
if (fAutosavePath.empty())
return;
#if CARDINAL_VARIANT_MINI
FILE* const f = std::fopen(rack::system::join(fAutosavePath, "patch.json").c_str(), "w");
DISTRHO_SAFE_ASSERT_RETURN(f != nullptr,);
rack::system::removeRecursively(fAutosavePath);
rack::system::createDirectories(fAutosavePath);
std::fwrite(value, std::strlen(value)+1, 1, f);
std::fclose(f);
#else
const std::vector<uint8_t> data(d_getChunkFromBase64String(value));
DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,);
@ -892,6 +918,7 @@ protected:
rack::system::unarchiveToDirectory(data, fAutosavePath);
} DISTRHO_SAFE_EXCEPTION_RETURN("setState unarchiveToDirectory",);
}
#endif
const ScopedContext sc(this);

View file

@ -139,7 +139,7 @@ void sendParamChangeToRemote(RemoteDetails* const remote, int64_t moduleId, int
{
#if CARDINAL_VARIANT_MINI
char paramBuf[512] = {};
std::snprintf(paramBuf, sizeof(paramBuf), "%lu:%d:%f", moduleId, paramId, value);
std::snprintf(paramBuf, sizeof(paramBuf), "%llu:%d:%f", (ulonglong)moduleId, paramId, value);
static_cast<CardinalBaseUI*>(remote->handle)->setState("param", paramBuf);
#elif defined(HAVE_LIBLO)
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
@ -159,17 +159,23 @@ void sendFullPatchToRemote(RemoteDetails* const remote)
context->engine->prepareSave();
context->patch->saveAutosave();
context->patch->cleanAutosave();
std::vector<uint8_t> data(rack::system::archiveDirectory(context->patch->autosavePath, 1));
std::vector<uint8_t> data;
using namespace rack::system;
#if CARDINAL_VARIANT_MINI
try {
data = readFile(join(context->patch->autosavePath, "patch.json"));
} DISTRHO_SAFE_EXCEPTION_RETURN("sendFullPatchToRemote",);
static_cast<CardinalBaseUI*>(remote->handle)->setState("patch", reinterpret_cast<const char*>(data.data()));
#elif defined(HAVE_LIBLO)
try {
data = archiveDirectory(context->patch->autosavePath, 1);
} DISTRHO_SAFE_EXCEPTION_RETURN("sendFullPatchToRemote",);
DISTRHO_SAFE_ASSERT_RETURN(data.size() >= 4,);
#if CARDINAL_VARIANT_MINI
if (char* const patch = String::asBase64(data.data(), data.size()).getAndReleaseBuffer())
{
static_cast<CardinalBaseUI*>(remote->handle)->setState("patch", patch);
std::free(patch);
}
#elif defined(HAVE_LIBLO)
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);
@ -180,7 +186,7 @@ void sendFullPatchToRemote(RemoteDetails* const remote)
}
lo_address_free(addr);
#endif
#endif
}
void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot)

View file

@ -298,7 +298,7 @@ class CardinalUI : public CardinalBaseUI,
rack::math::Vec lastMousePos;
WindowParameters windowParameters;
int rateLimitStep = 0;
#ifdef DISTRHO_OS_WASM
#if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI
int8_t counterForFirstIdlePoint = 0;
#endif
#ifdef DPF_RUNTIME_TESTING
@ -345,7 +345,7 @@ public:
rack::contextSet(context);
#if CARDINAL_VARIANT_MINI
remoteUtils::connectToRemote();
DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote());
// create unique temporary path for this instance
try {
@ -366,9 +366,17 @@ public:
}
} DISTRHO_SAFE_EXCEPTION("create unique temporary path");
const float sampleRate = getSampleRate();
const float sampleRate = 60; // fake audio running at 60 fps
rack::settings::sampleRate = sampleRate;
context->dataIns = new const float*[DISTRHO_PLUGIN_NUM_INPUTS];
context->dataOuts = new float*[DISTRHO_PLUGIN_NUM_OUTPUTS];
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_INPUTS;++i)
*const_cast<float**>(&context->dataIns[i]) = new float[1];
for (uint32_t i=0; i<DISTRHO_PLUGIN_NUM_OUTPUTS;++i)
context->dataOuts[i] = new float[1];
context->bufferSize = 1;
context->sampleRate = sampleRate;
@ -378,7 +386,7 @@ public:
context->history = new rack::history::State;
context->patch = new rack::patch::Manager;
context->patch->autosavePath = fAutosavePath;
context->patch->templatePath = context->patch->factoryTemplatePath = fInitializer->templatePath;
context->patch->templatePath = context->patch->factoryTemplatePath = fInitializer->factoryTemplatePath;
context->event = new rack::widget::EventState;
context->scene = new rack::app::Scene;
@ -386,6 +394,7 @@ public:
context->window = new rack::window::Window;
context->patch->loadTemplate();
context->scene->rackScroll->reset();
Engine_setRemoteDetails(context->engine, remoteDetails);
@ -563,7 +572,7 @@ public:
}
#endif
#ifdef DISTRHO_OS_WASM
#if defined(DISTRHO_OS_WASM) && ! CARDINAL_VARIANT_MINI
if (counterForFirstIdlePoint >= 0 && ++counterForFirstIdlePoint == 30)
{
counterForFirstIdlePoint = -1;
@ -606,7 +615,11 @@ public:
}
#if CARDINAL_VARIANT_MINI
context->engine->stepBlock(1);
{
const ScopedContext sc(this);
++context->processCounter;
context->engine->stepBlock(1);
}
#endif
if (windowParameters.rateLimit != 0 && ++rateLimitStep % (windowParameters.rateLimit * 2))
@ -702,9 +715,23 @@ protected:
*/
void parameterChanged(const uint32_t index, const float value) override
{
// host mapped parameters + bypass
if (index <= kModuleParameters)
// host mapped parameters
if (index < kModuleParameters)
{
#if CARDINAL_VARIANT_MINI
context->parameters[index] = value;
#endif
return;
}
// bypass
if (index == kModuleParameters)
{
#if CARDINAL_VARIANT_MINI
context->bypassed = value > 0.5f;
#endif
return;
}
switch (index - kModuleParameters - 1)
{

View file

@ -180,7 +180,7 @@ endif
# FIXME
ifeq ($(CARDINAL_VARIANT)$(CIBUILD)$(WASM),nativetruetrue)
ifneq ($(STATIC_BUILD),true)
ifneq ($(OLD_PATH),)
STATIC_CARLA_PLUGIN_LIBS = -lsndfile -lopus -lFLAC -lvorbisenc -lvorbis -logg -lm
endif
endif
@ -380,6 +380,7 @@ LINK_FLAGS += -sLZ4=1
ifeq ($(CARDINAL_VARIANT),mini)
LINK_FLAGS += --preload-file=../../bin/CardinalMini.lv2/resources@/resources
# LINK_FLAGS += -sEXPORTED_RUNTIME_METHODS=FS,cwrap
else
LINK_FLAGS += --shell-file=../emscripten/shell.html
ifneq ($(STATIC_BUILD),true)

View file

@ -135,6 +135,7 @@ struct FileButton : MenuButton {
patchUtils::loadTemplateDialog();
}));
#if ! CARDINAL_VARIANT_MINI
#ifndef DISTRHO_OS_WASM
menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() {
patchUtils::loadDialog();
@ -164,6 +165,7 @@ struct FileButton : MenuButton {
menu->addChild(createMenuItem("Save and download uncompressed", "", []() {
patchUtils::saveAsDialogUncompressed();
}));
#endif
#endif
menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() {
@ -194,6 +196,7 @@ struct FileButton : MenuButton {
}
#endif
#if ! CARDINAL_VARIANT_MINI
#ifndef DISTRHO_OS_WASM
menu->addChild(new ui::MenuSeparator);
@ -206,6 +209,7 @@ struct FileButton : MenuButton {
patchUtils::saveAsDialogUncompressed();
}));
#endif
#endif
#if ! CARDINAL_VARIANT_MINI
if (!demoPatches.empty())
@ -761,9 +765,14 @@ struct MeterLabel : ui::Label {
// uiLastTime = time;
// }
#if CARDINAL_VARIANT_MINI
text = string::f("%.1f fps", 1.0 / frameDurationAvg);
#else
double meterAverage = APP->engine->getMeterAverage();
double meterMax = APP->engine->getMeterMax();
text = string::f("%.1f fps %.1f%% avg %.1f%% max", 1.0 / frameDurationAvg, meterAverage * 100, meterMax * 100);
#endif
Label::step();
}
};
@ -795,9 +804,11 @@ struct MenuBar : widget::OpaqueWidget {
viewButton->text = "View";
layout->addChild(viewButton);
#if ! CARDINAL_VARIANT_MINI
EngineButton* engineButton = new EngineButton;
engineButton->text = "Engine";
layout->addChild(engineButton);
#endif
HelpButton* helpButton = new HelpButton;
helpButton->text = "Help";

View file

@ -212,7 +212,11 @@ void Scene::step() {
if (remoteDetails->autoDeploy) {
const int actionIndex = APP->history->actionIndex;
const double time = system::getTime();
if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) {
if (internal->historyActionIndex == -1) {
internal->historyActionIndex = actionIndex;
internal->lastSceneChangeTime = time;
} else if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) {
const std::string& name(APP->history->actions[actionIndex - 1]->name);
if (/*std::abs(internal->historyActionIndex = actionIndex) > 1 ||*/ name != "move knob") {
printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str());