From 4ab933a0733785095654b6c212dc2d1add19a583 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 30 Dec 2022 16:06:52 +0000 Subject: [PATCH] Regen patches Signed-off-by: falkTX --- src/override/diffs/Engine.cpp.diff | 133 +++-- src/override/diffs/MenuBar.cpp.diff | 122 +++-- src/override/diffs/Model.cpp.diff | 4 +- src/override/diffs/ModuleWidget.cpp.diff | 4 +- src/override/diffs/OpenGlWidget.cpp.diff | 4 +- src/override/diffs/Scene.cpp.diff | 188 ++----- src/override/diffs/Window.cpp.diff | 626 ++++++++++++++--------- src/override/diffs/blendish.c.diff | 4 +- src/override/diffs/common.cpp.diff | 23 +- src/override/diffs/context.cpp.diff | 4 +- src/override/diffs/minblep.cpp.diff | 4 +- src/override/diffs/plugin.cpp.diff | 4 +- 12 files changed, 603 insertions(+), 517 deletions(-) diff --git a/src/override/diffs/Engine.cpp.diff b/src/override/diffs/Engine.cpp.diff index 89c13e4..b3609d4 100644 --- a/src/override/diffs/Engine.cpp.diff +++ b/src/override/diffs/Engine.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/engine/Engine.cpp 2022-09-21 20:25:53.592040301 +0100 -+++ Engine.cpp 2022-11-29 19:49:19.196926572 +0000 +--- ../Rack/src/engine/Engine.cpp 2022-09-21 19:49:12.200540736 +0100 ++++ Engine.cpp 2022-12-29 16:15:36.061769776 +0000 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin @@ -31,7 +31,7 @@ #include #include #include -@@ -6,183 +33,38 @@ +@@ -6,183 +33,39 @@ #include #include #include @@ -98,6 +98,7 @@ - }); - } -}; ++#include "../CardinalRemote.hpp" +#include "DistrhoUtils.hpp" @@ -227,7 +228,7 @@ // moduleId std::map modulesCache; -@@ -198,7 +80,9 @@ +@@ -198,7 +81,9 @@ int64_t blockFrame = 0; double blockTime = 0.0; int blockFrames = 0; @@ -237,7 +238,7 @@ // Meter int meterCount = 0; double meterTotal = 0.0; -@@ -206,6 +90,7 @@ +@@ -206,33 +91,21 @@ double meterLastTime = -INFINITY; double meterLastAverage = 0.0; double meterLastMax = 0.0; @@ -245,7 +246,14 @@ // Parameter smoothing Module* smoothModule = NULL; -@@ -217,22 +102,6 @@ + int smoothParamId = 0; + float smoothValue = 0.f; + ++ // Remote control ++ remoteUtils::RemoteDetails* remoteDetails = nullptr; ++ + /** Mutex that guards the Engine state, such as settings, Modules, and Cables. + Writers lock when mutating the engine's state or stepping the block. Readers lock when using the engine's state. */ SharedMutex mutex; @@ -268,7 +276,7 @@ }; -@@ -260,76 +129,11 @@ +@@ -260,76 +133,11 @@ } @@ -346,7 +354,7 @@ // Copy all voltages from output to input for (int c = 0; c < channels; c++) { float v = output->voltages[c]; -@@ -346,6 +150,53 @@ +@@ -346,6 +154,53 @@ } @@ -400,7 +408,28 @@ /** Steps a single frame */ static void Engine_stepFrame(Engine* that) { -@@ -372,13 +223,8 @@ +@@ -358,10 +213,16 @@ + float smoothValue = internal->smoothValue; + Param* smoothParam = &smoothModule->params[smoothParamId]; + float value = smoothParam->value; +- // Use decay rate of roughly 1 graphics frame +- const float smoothLambda = 60.f; +- float newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime; +- if (value == newValue) { ++ float newValue; ++ if (internal->remoteDetails != nullptr) { ++ newValue = value; ++ sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value); ++ } else { ++ // Use decay rate of roughly 1 graphics frame ++ const float smoothLambda = 60.f; ++ newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime; ++ } ++ if (d_isEqual(value, newValue)) { + // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats) + smoothParam->setValue(smoothValue); + internal->smoothModule = NULL; +@@ -372,13 +233,8 @@ } } @@ -415,7 +444,7 @@ if (module->leftExpander.messageFlipRequested) { std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage); module->leftExpander.messageFlipRequested = false; -@@ -389,13 +235,32 @@ +@@ -389,13 +245,32 @@ } } @@ -454,7 +483,7 @@ } -@@ -414,35 +279,119 @@ +@@ -414,35 +289,119 @@ } @@ -585,7 +614,7 @@ } -@@ -460,37 +409,23 @@ +@@ -460,37 +419,23 @@ Engine::Engine() { internal = new Internal; @@ -631,7 +660,7 @@ delete internal; } -@@ -519,18 +454,22 @@ +@@ -519,18 +464,22 @@ removeModule_NoLock(module); delete module; } @@ -657,7 +686,7 @@ random::init(); internal->blockFrame = internal->frame; -@@ -543,18 +482,14 @@ +@@ -543,18 +492,14 @@ Engine_updateExpander_NoLock(this, module, true); } @@ -677,7 +706,7 @@ // Stop timer double endTime = system::getTime(); double meter = (endTime - startTime) / (frames * internal->sampleTime); -@@ -572,47 +507,20 @@ +@@ -572,47 +517,20 @@ internal->meterTotal = 0.0; internal->meterMax = 0.0; } @@ -727,7 +756,7 @@ } -@@ -635,20 +543,13 @@ +@@ -635,20 +553,13 @@ for (Module* module : internal->modules) { module->onSampleRateChange(e); } @@ -751,7 +780,7 @@ } -@@ -658,7 +559,6 @@ +@@ -658,7 +569,6 @@ void Engine::yieldWorkers() { @@ -759,7 +788,7 @@ } -@@ -698,17 +598,25 @@ +@@ -698,17 +608,25 @@ double Engine::getMeterAverage() { @@ -786,7 +815,7 @@ } -@@ -718,8 +626,12 @@ +@@ -718,8 +636,12 @@ for (Module* m : internal->modules) { if (i >= len) break; @@ -801,7 +830,7 @@ } return i; } -@@ -728,27 +640,43 @@ +@@ -728,27 +650,43 @@ std::vector Engine::getModuleIds() { SharedLock lock(internal->mutex); std::vector moduleIds; @@ -849,7 +878,7 @@ internal->modulesCache[module->id] = module; // Dispatch AddEvent Module::AddEvent eAdd; -@@ -763,6 +691,9 @@ +@@ -763,6 +701,9 @@ if (paramHandle->moduleId == module->id) paramHandle->module = module; } @@ -859,7 +888,7 @@ } -@@ -772,11 +703,11 @@ +@@ -772,11 +713,11 @@ } @@ -876,7 +905,7 @@ // Dispatch RemoveEvent Module::RemoveEvent eRemove; module->onRemove(eRemove); -@@ -785,18 +716,14 @@ +@@ -785,18 +726,14 @@ if (paramHandle->moduleId == module->id) paramHandle->module = NULL; } @@ -897,7 +926,7 @@ } // Update expanders of other modules for (Module* m : internal->modules) { -@@ -809,14 +736,31 @@ +@@ -809,14 +746,31 @@ m->rightExpander.module = NULL; } } @@ -932,7 +961,7 @@ } -@@ -824,7 +768,8 @@ +@@ -824,7 +778,8 @@ SharedLock lock(internal->mutex); // TODO Performance could be improved by searching modulesCache, but more testing would be needed to make sure it's always valid. auto it = std::find(internal->modules.begin(), internal->modules.end(), module); @@ -942,7 +971,7 @@ } -@@ -844,7 +789,7 @@ +@@ -844,7 +799,7 @@ void Engine::resetModule(Module* module) { std::lock_guard lock(internal->mutex); @@ -951,7 +980,7 @@ Module::ResetEvent eReset; module->onReset(eReset); -@@ -853,7 +798,7 @@ +@@ -853,7 +808,7 @@ void Engine::randomizeModule(Module* module) { std::lock_guard lock(internal->mutex); @@ -960,7 +989,7 @@ Module::RandomizeEvent eRandomize; module->onRandomize(eRandomize); -@@ -861,7 +806,7 @@ +@@ -861,7 +816,7 @@ void Engine::bypassModule(Module* module, bool bypassed) { @@ -969,7 +998,7 @@ if (module->isBypassed() == bypassed) return; -@@ -907,11 +852,17 @@ +@@ -907,11 +862,17 @@ void Engine::prepareSave() { @@ -987,7 +1016,7 @@ } -@@ -946,16 +897,16 @@ +@@ -946,16 +907,16 @@ void Engine::addCable(Cable* cable) { std::lock_guard lock(internal->mutex); @@ -1009,7 +1038,7 @@ // Get connected status of output, to decide whether we need to call a PortChangeEvent. // It's best to not trust `cable->outputModule->outputs[cable->outputId]->isConnected()` if (cable2->outputModule == cable->outputModule && cable2->outputId == cable->outputId) -@@ -969,6 +920,8 @@ +@@ -969,6 +930,8 @@ // Add the cable internal->cables.push_back(cable); internal->cablesCache[cable->id] = cable; @@ -1018,7 +1047,7 @@ Engine_updateConnected(this); // Dispatch input port event { -@@ -996,10 +949,12 @@ +@@ -996,10 +959,12 @@ void Engine::removeCable_NoLock(Cable* cable) { @@ -1033,7 +1062,17 @@ // Remove the cable internal->cablesCache.erase(cable->id); internal->cables.erase(it); -@@ -1085,11 +1040,11 @@ +@@ -1053,6 +1018,9 @@ + internal->smoothModule = NULL; + internal->smoothParamId = 0; + } ++ if (internal->remoteDetails != nullptr) { ++ sendParamChangeToRemote(internal->remoteDetails, module->id, paramId, value); ++ } + module->params[paramId].value = value; + } + +@@ -1085,11 +1053,11 @@ std::lock_guard lock(internal->mutex); // New ParamHandles must be blank. // This means we don't have to refresh the cache. @@ -1047,7 +1086,7 @@ // Add it internal->paramHandles.insert(paramHandle); -@@ -1106,7 +1061,7 @@ +@@ -1106,7 +1074,7 @@ void Engine::removeParamHandle_NoLock(ParamHandle* paramHandle) { // Check that the ParamHandle is already added auto it = internal->paramHandles.find(paramHandle); @@ -1056,7 +1095,7 @@ // Remove it paramHandle->module = NULL; -@@ -1143,7 +1098,7 @@ +@@ -1143,7 +1111,7 @@ void Engine::updateParamHandle_NoLock(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) { // Check that it exists auto it = internal->paramHandles.find(paramHandle); @@ -1065,7 +1104,7 @@ // Set IDs paramHandle->moduleId = moduleId; -@@ -1187,6 +1142,10 @@ +@@ -1187,6 +1155,10 @@ json_t* moduleJ = module->toJson(); json_array_append_new(modulesJ, moduleJ); } @@ -1076,7 +1115,7 @@ json_object_set_new(rootJ, "modules", modulesJ); // cables -@@ -1197,11 +1156,6 @@ +@@ -1197,11 +1169,6 @@ } json_object_set_new(rootJ, "cables", cablesJ); @@ -1088,7 +1127,7 @@ return rootJ; } -@@ -1225,14 +1179,20 @@ +@@ -1225,14 +1192,20 @@ } catch (Exception& e) { WARN("Cannot load model: %s", e.what()); @@ -1113,7 +1152,7 @@ try { // This doesn't need a lock because the Module is not added to the Engine yet. -@@ -1248,7 +1208,8 @@ +@@ -1248,7 +1221,8 @@ } catch (Exception& e) { WARN("Cannot load module: %s", e.what()); @@ -1123,7 +1162,7 @@ delete module; continue; } -@@ -1285,67 +1246,15 @@ +@@ -1285,67 +1259,20 @@ continue; } } @@ -1134,9 +1173,9 @@ - Module* masterModule = getModule(json_integer_value(masterModuleIdJ)); - setMasterModule(masterModule); - } --} -- -- + } + + -void EngineWorker::run() { - // Configure thread - contextSet(engine->internal->context); @@ -1151,6 +1190,7 @@ - Engine_stepWorker(engine, id); - engine->internal->workerBarrier.wait(); - } ++void Engine::startFallbackThread() { } @@ -1179,7 +1219,8 @@ - }); - } - } -+void Engine::startFallbackThread() { ++void Engine_setAboutToClose(Engine* const engine) { ++ engine->internal->aboutToClose = true; } @@ -1189,8 +1230,8 @@ - - internal->fallbackRunning = true; - internal->fallbackThread = std::thread(Engine_fallbackRun, this); -+void Engine_setAboutToClose(Engine* const engine) { -+ engine->internal->aboutToClose = true; ++void Engine_setRemoteDetails(Engine* const engine, remoteUtils::RemoteDetails* const remoteDetails) { ++ engine->internal->remoteDetails = remoteDetails; } diff --git a/src/override/diffs/MenuBar.cpp.diff b/src/override/diffs/MenuBar.cpp.diff index ece100e..e34016e 100644 --- a/src/override/diffs/MenuBar.cpp.diff +++ b/src/override/diffs/MenuBar.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/app/MenuBar.cpp 2022-09-21 20:25:53.590040258 +0100 -+++ MenuBar.cpp 2022-11-29 19:49:19.196926572 +0000 +--- ../Rack/src/app/MenuBar.cpp 2022-09-21 19:49:12.198540676 +0100 ++++ MenuBar.cpp 2022-12-30 14:50:06.801891005 +0000 @@ -1,8 +1,33 @@ +/* + * DISTRHO Cardinal Plugin @@ -44,11 +44,13 @@ #include #include #include -@@ -25,8 +51,24 @@ +@@ -25,8 +51,28 @@ #include #include +#include "../CardinalCommon.hpp" ++#include "../CardinalRemote.hpp" ++#include "DistrhoPlugin.hpp" +#include "DistrhoStandaloneUtils.hpp" + +#ifdef HAVE_LIBLO @@ -61,7 +63,9 @@ +namespace asset { +std::string patchesPath(); +} -+ ++namespace engine { ++void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); ++} +namespace plugin { +void updateStaticPluginsDarkMode(); +} @@ -69,7 +73,7 @@ namespace app { namespace menuBar { -@@ -48,79 +90,152 @@ +@@ -48,79 +94,160 @@ }; @@ -93,14 +97,14 @@ struct FileButton : MenuButton { + const bool isStandalone; -+#if !(defined(DISTRHO_OS_WASM) && defined(STATIC_BUILD)) ++#if ! CARDINAL_VARIANT_MINI + std::vector demoPatches; +#endif + + FileButton(const bool standalone) + : MenuButton(), isStandalone(standalone) + { -+#if !(defined(DISTRHO_OS_WASM) && defined(STATIC_BUILD)) ++#if ! CARDINAL_VARIANT_MINI + const std::string patchesDir = asset::patchesPath() + DISTRHO_OS_SEP_STR "examples"; + + if (system::isDirectory(patchesDir)) @@ -131,6 +135,7 @@ - menu->addChild(createMenuItem("Open", RACK_MOD_CTRL_NAME "+O", []() { - APP->patch->loadDialog(); ++#if ! CARDINAL_VARIANT_MINI +#ifndef DISTRHO_OS_WASM + menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() { + patchUtils::loadDialog(); @@ -174,6 +179,7 @@ + menu->addChild(createMenuItem("Save and download uncompressed", "", []() { + patchUtils::saveAsDialogUncompressed(); })); ++#endif +#endif menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { @@ -185,26 +191,31 @@ - menu->addChild(createMenuItem("Overwrite template", "", []() { - APP->patch->saveTemplateDialog(); - })); -+#ifdef HAVE_LIBLO ++#if defined(HAVE_LIBLO) && ! CARDINAL_VARIANT_MINI + menu->addChild(new ui::MenuSeparator); + -+ if (patchUtils::isRemoteConnected()) { -+ menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { -+ patchUtils::deployToRemote(); ++ remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote(); ++ ++ if (remoteDetails != nullptr && remoteDetails->connected) { ++ menu->addChild(createMenuItem("Deploy to MOD", "F7", [remoteDetails]() { ++ remoteUtils::sendFullPatchToRemote(remoteDetails); + })); -+ const bool autoDeploy = patchUtils::isRemoteAutoDeployed(); + menu->addChild(createCheckMenuItem("Auto deploy to MOD", "", -+ [=]() {return autoDeploy;}, -+ [=]() {patchUtils::setRemoteAutoDeploy(!autoDeploy);} ++ [remoteDetails]() {return remoteDetails->autoDeploy;}, ++ [remoteDetails]() { ++ remoteDetails->autoDeploy = !remoteDetails->autoDeploy; ++ Engine_setRemoteDetails(APP->engine, remoteDetails->autoDeploy ? remoteDetails : nullptr); ++ } + )); + } else { + menu->addChild(createMenuItem("Connect to MOD", "", []() { -+ patchUtils::connectToRemote(); ++ DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote()); + })); + } +#endif + ++#if ! CARDINAL_VARIANT_MINI +#ifndef DISTRHO_OS_WASM menu->addChild(new ui::MenuSeparator); @@ -223,8 +234,9 @@ + patchUtils::saveAsDialogUncompressed(); })); +#endif ++#endif + -+#if !(defined(DISTRHO_OS_WASM) && defined(STATIC_BUILD)) ++#if ! CARDINAL_VARIANT_MINI + if (!demoPatches.empty()) + { + menu->addChild(new ui::MenuSeparator); @@ -264,7 +276,7 @@ } }; -@@ -166,7 +281,7 @@ +@@ -166,7 +293,7 @@ menu->addChild(new ui::MenuSeparator); @@ -273,7 +285,7 @@ } }; -@@ -256,7 +371,7 @@ +@@ -256,7 +383,7 @@ return settings::cableTension; } float getDefaultValue() override { @@ -282,7 +294,7 @@ } float getDisplayValue() override { return getValue() * 100; -@@ -393,36 +508,37 @@ +@@ -393,36 +520,37 @@ }; @@ -341,7 +353,7 @@ menu->addChild(createBoolPtrMenuItem("Show tooltips", "", &settings::tooltips)); ZoomSlider* zoomSlider = new ZoomSlider; -@@ -446,9 +562,18 @@ +@@ -446,9 +574,18 @@ menu->addChild(haloBrightnessSlider); menu->addChild(new ui::MenuSeparator); @@ -360,14 +372,13 @@ static const std::vector knobModeLabels = { "Linear", -@@ -473,11 +598,34 @@ +@@ -473,11 +610,34 @@ menu->addChild(knobScrollSensitivitySlider); menu->addChild(new ui::MenuSeparator); - menu->addChild(createMenuLabel("Module dragging")); + menu->addChild(createMenuLabel("Window")); - -- menu->addChild(createBoolPtrMenuItem("Lock positions", "", &settings::lockModules)); ++ +#ifdef DISTRHO_OS_WASM + const bool fullscreen = APP->window->isFullScreen(); + std::string rightText = "F11"; @@ -377,7 +388,8 @@ + APP->window->setFullScreen(!fullscreen); + })); +#endif -+ + +- menu->addChild(createBoolPtrMenuItem("Lock positions", "", &settings::lockModules)); + menu->addChild(createBoolPtrMenuItem("Invert zoom", "", &settings::invertZoom)); - menu->addChild(createBoolPtrMenuItem("Auto-squeeze algorithm (experimental)", "", &settings::squeezeModules)); @@ -398,7 +410,7 @@ } }; -@@ -487,47 +635,6 @@ +@@ -487,47 +647,6 @@ //////////////////// @@ -446,7 +458,7 @@ struct EngineButton : MenuButton { void onAction(const ActionEvent& e) override { ui::Menu* menu = createMenu(); -@@ -541,268 +648,46 @@ +@@ -541,268 +660,46 @@ settings::cpuMeter ^= true; })); @@ -602,10 +614,10 @@ + })); } - } -- + - MenuItem::step(); - } - +- - void onAction(const ActionEvent& e) override { - std::thread t([=] { - library::syncUpdate(slug); @@ -714,11 +726,11 @@ - }); - t.detach(); - } - +- - void step() override { - notification->box.pos = math::Vec(0, 0); - notification->visible = library::hasUpdates(); -- + - // Popup when updates finish downloading - if (library::restartRequested) { - library::restartRequested = false; @@ -748,7 +760,7 @@ } }; -@@ -813,65 +698,23 @@ +@@ -813,65 +710,23 @@ struct HelpButton : MenuButton { @@ -770,14 +782,14 @@ - - menu->addChild(createMenuItem("User manual", "F1", [=]() { - system::openBrowser("https://vcvrack.com/manual"); +- })); +- +- menu->addChild(createMenuItem("Support", "", [=]() { +- system::openBrowser("https://vcvrack.com/support"); + menu->addChild(createMenuItem("Rack User manual", "F1", [=]() { + patchUtils::openBrowser("https://vcvrack.com/manual"); })); -- menu->addChild(createMenuItem("Support", "", [=]() { -- system::openBrowser("https://vcvrack.com/support"); -- })); -- - menu->addChild(createMenuItem("VCVRack.com", "", [=]() { - system::openBrowser("https://vcvrack.com/"); + menu->addChild(createMenuItem("Cardinal Project page", "", [=]() { @@ -820,7 +832,22 @@ } }; -@@ -921,7 +764,9 @@ +@@ -910,9 +765,14 @@ + // 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(); + } + }; +@@ -921,7 +781,9 @@ struct MenuBar : widget::OpaqueWidget { MeterLabel* meterLabel; @@ -831,7 +858,7 @@ const float margin = 5; box.size.y = BND_WIDGET_HEIGHT + 2 * margin; -@@ -930,7 +775,7 @@ +@@ -930,7 +792,7 @@ layout->spacing = math::Vec(0, 0); addChild(layout); @@ -840,27 +867,28 @@ fileButton->text = "File"; layout->addChild(fileButton); -@@ -946,10 +791,6 @@ +@@ -942,13 +804,11 @@ + viewButton->text = "View"; + layout->addChild(viewButton); + ++#if ! CARDINAL_VARIANT_MINI + EngineButton* engineButton = new EngineButton; engineButton->text = "Engine"; layout->addChild(engineButton); - +- - LibraryButton* libraryButton = new LibraryButton; - libraryButton->text = "Library"; - layout->addChild(libraryButton); -- ++#endif + HelpButton* helpButton = new HelpButton; helpButton->text = "Help"; - layout->addChild(helpButton); -@@ -984,7 +825,11 @@ +@@ -984,7 +844,7 @@ widget::Widget* createMenuBar() { - menuBar::MenuBar* menuBar = new menuBar::MenuBar; -+ return new widget::Widget; -+} -+ -+widget::Widget* createMenuBar(const bool isStandalone) { -+ menuBar::MenuBar* menuBar = new menuBar::MenuBar(isStandalone); ++ menuBar::MenuBar* menuBar = new menuBar::MenuBar(isStandalone()); return menuBar; } diff --git a/src/override/diffs/Model.cpp.diff b/src/override/diffs/Model.cpp.diff index f1ad26c..1c251b2 100644 --- a/src/override/diffs/Model.cpp.diff +++ b/src/override/diffs/Model.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/plugin/Model.cpp 2022-09-21 20:25:53.592040301 +0100 -+++ Model.cpp 2022-09-21 20:18:50.294557597 +0100 +--- ../Rack/src/plugin/Model.cpp 2022-09-21 19:49:12.200540736 +0100 ++++ Model.cpp 2022-09-21 19:41:45.883648777 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin diff --git a/src/override/diffs/ModuleWidget.cpp.diff b/src/override/diffs/ModuleWidget.cpp.diff index c32ce74..b1e635d 100644 --- a/src/override/diffs/ModuleWidget.cpp.diff +++ b/src/override/diffs/ModuleWidget.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/app/ModuleWidget.cpp 2022-09-21 20:25:53.590040258 +0100 -+++ ModuleWidget.cpp 2022-12-01 20:41:02.583687336 +0000 +--- ../Rack/src/app/ModuleWidget.cpp 2022-09-21 19:49:12.198540676 +0100 ++++ ModuleWidget.cpp 2022-12-02 19:11:45.780215974 +0000 @@ -1,3 +1,32 @@ +/* + * DISTRHO Cardinal Plugin diff --git a/src/override/diffs/OpenGlWidget.cpp.diff b/src/override/diffs/OpenGlWidget.cpp.diff index 261123f..1fb7156 100644 --- a/src/override/diffs/OpenGlWidget.cpp.diff +++ b/src/override/diffs/OpenGlWidget.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/widget/OpenGlWidget.cpp 2022-09-21 20:25:53.593040323 +0100 -+++ OpenGlWidget.cpp 2022-09-21 20:18:50.294557597 +0100 +--- ../Rack/src/widget/OpenGlWidget.cpp 2022-09-21 19:49:12.201540766 +0100 ++++ OpenGlWidget.cpp 2022-09-21 19:41:45.883648777 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin diff --git a/src/override/diffs/Scene.cpp.diff b/src/override/diffs/Scene.cpp.diff index 4d1da9f..5520940 100644 --- a/src/override/diffs/Scene.cpp.diff +++ b/src/override/diffs/Scene.cpp.diff @@ -1,6 +1,9 @@ ---- ../Rack/src/app/Scene.cpp 2022-09-21 20:25:53.591040280 +0100 -+++ Scene.cpp 2022-09-21 20:18:50.294557597 +0100 -@@ -1,3 +1,30 @@ +--- ../Rack/src/app/Scene.cpp 2022-09-21 19:49:12.199540706 +0100 ++++ Scene.cpp 2022-12-30 14:50:06.801891005 +0000 +@@ -1,12 +1,36 @@ +-#include +- +-#include +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho @@ -27,11 +30,9 @@ + * published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + */ -+ - #include - #include -@@ -7,6 +34,7 @@ + #include + #include #include #include #include @@ -39,7 +40,7 @@ #include #include #include -@@ -14,6 +42,22 @@ +@@ -14,6 +38,13 @@ #include #include @@ -47,22 +48,13 @@ +# undef DEBUG +#endif + -+#ifdef STATIC_BUILD -+# undef HAVE_LIBLO -+#endif -+ -+#ifdef HAVE_LIBLO -+# include -+#endif -+ +#include "../CardinalCommon.hpp" -+#include "extra/Base64.hpp" -+#include "DistrhoUtils.hpp" ++#include "../CardinalRemote.hpp" + namespace rack { namespace app { -@@ -23,32 +67,94 @@ +@@ -23,32 +54,72 @@ math::Vec size; void draw(const DrawArgs& args) override { @@ -140,34 +132,12 @@ bool heldArrowKeys[4] = {}; + -+#ifdef HAVE_LIBLO + double lastSceneChangeTime = 0.0; + int historyActionIndex = -1; -+ -+ bool oscAutoDeploy = false; -+ bool oscConnected = false; -+ lo_server oscServer = nullptr; -+ -+ static int osc_handler(const char* const path, const char* const types, lo_arg** argv, const int argc, lo_message, void* const self) -+ { -+ d_stdout("osc_handler(\"%s\", \"%s\", %p, %i)", path, types, argv, argc); -+ -+ if (std::strcmp(path, "/resp") == 0 && argc == 2 && types[0] == 's' && types[1] == 's') { -+ d_stdout("osc_handler(\"%s\", ...) - got resp | '%s' '%s'", path, &argv[0]->s, &argv[1]->s); -+ if (std::strcmp(&argv[0]->s, "hello") == 0 && std::strcmp(&argv[1]->s, "ok") == 0) -+ static_cast(self)->oscConnected = true; -+ } -+ return 0; -+ } -+ -+ ~Internal() { -+ lo_server_free(oscServer); -+ } -+#endif }; -@@ -67,13 +173,11 @@ +@@ -67,13 +138,11 @@ browser->hide(); addChild(browser); @@ -184,7 +154,7 @@ addChild(internal->resizeHandle); } -@@ -99,22 +203,13 @@ +@@ -99,22 +168,13 @@ rackScroll->box.pos.y = menuBar->box.size.y; } @@ -209,31 +179,37 @@ // Scroll RackScrollWidget with arrow keys math::Vec arrowDelta; if (internal->heldArrowKeys[0]) { -@@ -143,6 +238,23 @@ +@@ -143,6 +203,29 @@ rackScroll->offset += arrowDelta * arrowSpeed; } -+#ifdef HAVE_LIBLO -+ if (internal->oscServer != nullptr) { -+ while (lo_server_recv_noblock(internal->oscServer, 0) != 0) {} ++ if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) { ++ idleRemote(remoteDetails); + -+ if (internal->oscAutoDeploy) { ++ if (remoteDetails->autoDeploy) { + const int actionIndex = APP->history->actionIndex; + const double time = system::getTime(); -+ if (internal->historyActionIndex != actionIndex && time - internal->lastSceneChangeTime >= 5.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()); ++ remoteUtils::sendFullPatchToRemote(remoteDetails); ++ window::generateScreenshot(); ++ } + internal->historyActionIndex = actionIndex; + internal->lastSceneChangeTime = time; -+ patchUtils::deployToRemote(); -+ window::generateScreenshot(); + } + } + } -+#endif + Widget::step(); } -@@ -172,7 +284,7 @@ +@@ -172,7 +255,7 @@ if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { // DEBUG("key '%d '%c' scancode %d '%c' keyName '%s'", e.key, e.key, e.scancode, e.scancode, e.keyName.c_str()); if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { @@ -242,7 +218,7 @@ e.consume(this); } if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { -@@ -180,19 +292,22 @@ +@@ -180,19 +263,22 @@ e.consume(this); } if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { @@ -269,7 +245,7 @@ e.consume(this); } if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { -@@ -220,24 +335,37 @@ +@@ -220,24 +306,38 @@ APP->scene->rackScroll->setZoom(std::pow(2.f, zoom)); e.consume(this); } @@ -292,7 +268,8 @@ e.consume(this); } + if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { -+ patchUtils::deployToRemote(); ++ if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) ++ remoteUtils::sendFullPatchToRemote(remoteDetails); + window::generateScreenshot(); + e.consume(this); + } @@ -311,7 +288,7 @@ // Module selections if (e.keyName == "a" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { -@@ -326,13 +454,6 @@ +@@ -326,13 +426,6 @@ // Key commands that can be overridden by children if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { @@ -325,7 +302,7 @@ if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { rack->pasteClipboardAction(); e.consume(this); -@@ -351,7 +472,7 @@ +@@ -351,7 +444,7 @@ std::string extension = system::getExtension(path); if (extension == ".vcv") { @@ -334,98 +311,3 @@ e.consume(this); return; } -@@ -368,3 +489,94 @@ - - } // namespace app - } // namespace rack -+ -+ -+namespace patchUtils { -+ -+ -+bool connectToRemote() { -+#ifdef HAVE_LIBLO -+ rack::app::Scene::Internal* const internal = APP->scene->internal; -+ -+ if (internal->oscServer == nullptr) { -+ const lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, nullptr); -+ DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr, false); -+ lo_server_add_method(oscServer, "/resp", nullptr, rack::app::Scene::Internal::osc_handler, internal); -+ internal->oscServer = oscServer; -+ } -+ -+ const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); -+ DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr, false); -+ lo_send(addr, "/hello", ""); -+ lo_address_free(addr); -+ -+ return true; -+#else -+ return false; -+#endif -+} -+ -+ -+bool isRemoteConnected() { -+#ifdef HAVE_LIBLO -+ return APP->scene->internal->oscConnected; -+#else -+ return false; -+#endif -+} -+ -+ -+bool isRemoteAutoDeployed() { -+#ifdef HAVE_LIBLO -+ return APP->scene->internal->oscAutoDeploy; -+#else -+ return false; -+#endif -+} -+ -+ -+void setRemoteAutoDeploy(bool autoDeploy) { -+#ifdef HAVE_LIBLO -+ APP->scene->internal->oscAutoDeploy = autoDeploy; -+#endif -+} -+ -+ -+void deployToRemote() { -+#ifdef HAVE_LIBLO -+ const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); -+ DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); -+ -+ APP->engine->prepareSave(); -+ APP->patch->saveAutosave(); -+ APP->patch->cleanAutosave(); -+ std::vector data(rack::system::archiveDirectory(APP->patch->autosavePath, 1)); -+ -+ if (const lo_blob blob = lo_blob_new(data.size(), data.data())) { -+ lo_send(addr, "/load", "b", blob); -+ lo_blob_free(blob); -+ } -+ -+ lo_address_free(addr); -+#endif -+} -+ -+ -+void sendScreenshotToRemote(const char* const screenshot) { -+#ifdef HAVE_LIBLO -+ const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); -+ DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); -+ -+ std::vector data(d_getChunkFromBase64String(screenshot)); -+ -+ if (const lo_blob blob = lo_blob_new(data.size(), data.data())) { -+ lo_send(addr, "/screenshot", "b", blob); -+ lo_blob_free(blob); -+ } -+ -+ lo_address_free(addr); -+#endif -+} -+ -+ -+} // namespace patchUtils diff --git a/src/override/diffs/Window.cpp.diff b/src/override/diffs/Window.cpp.diff index c9866e9..e71c075 100644 --- a/src/override/diffs/Window.cpp.diff +++ b/src/override/diffs/Window.cpp.diff @@ -1,6 +1,6 @@ ---- ../Rack/src/window/Window.cpp 2022-09-21 20:25:53.593040323 +0100 -+++ Window.cpp 2022-09-21 20:18:50.294557597 +0100 -@@ -1,33 +1,87 @@ +--- ../Rack/src/window/Window.cpp 2022-09-21 19:49:12.202540796 +0100 ++++ Window.cpp 2022-12-29 17:16:45.012337253 +0000 +@@ -1,33 +1,88 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho @@ -59,10 +59,10 @@ + +// comment out if wanting to generate a local screenshot.png +#define STBI_WRITE_NO_STDIO - ++ +// uncomment to generate screenshots without the rack rail background (ie, transparent) +// #define CARDINAL_TRANSPARENT_SCREENSHOTS -+ + +// used in Window::screenshot +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" @@ -71,6 +71,7 @@ +#include "Application.hpp" +#include "extra/String.hpp" +#include "../CardinalCommon.hpp" ++#include "../PluginContext.hpp" +#include "../WindowParameters.hpp" + +#ifndef DGL_NO_SHARED_RESOURCES @@ -101,7 +102,7 @@ Font::~Font() { -@@ -42,9 +96,8 @@ +@@ -42,9 +97,8 @@ // Transfer ownership of font data to font object uint8_t* data = system::readFile(filename, &size); // Don't use nvgCreateFont because it doesn't properly handle UTF-8 filenames on Windows. @@ -112,7 +113,7 @@ throw Exception("Failed to load font %s", filename.c_str()); } INFO("Loaded font %s", filename.c_str()); -@@ -79,375 +132,347 @@ +@@ -79,375 +133,489 @@ } @@ -133,14 +134,17 @@ - int lastWindowWidth = 0; - int lastWindowHeight = 0; + DISTRHO_NAMESPACE::UI* ui = nullptr; ++ DGL_NAMESPACE::NanoTopLevelWidget* tlw = nullptr; + DISTRHO_NAMESPACE::WindowParameters params; + DISTRHO_NAMESPACE::WindowParametersCallback* callback = nullptr; ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + DGL_NAMESPACE::Application hiddenApp; + DGL_NAMESPACE::Window hiddenWindow; + NVGcontext* r_vg = nullptr; + NVGcontext* r_fbVg = nullptr; + NVGcontext* o_vg = nullptr; + NVGcontext* o_fbVg = nullptr; ++#endif + + math::Vec size = WINDOW_SIZE_MIN; + @@ -168,16 +172,8 @@ bool fbDirtyOnSubpixelChange = true; int fbCount = 0; -+ -+ Internal() -+ : hiddenApp(false), -+ hiddenWindow(hiddenApp) -+ { -+ hiddenWindow.setIgnoringKeyRepeat(true); -+ hiddenApp.idle(); -+ } - }; - +-}; +- -static void windowPosCallback(GLFWwindow* win, int x, int y) { - if (glfwGetWindowAttrib(win, GLFW_MAXIMIZED)) @@ -189,14 +185,19 @@ - settings::windowPos = math::Vec(x, y); - // DEBUG("windowPosCallback %d %d", x, y); -} -+#ifndef DGL_NO_SHARED_RESOURCES -+static int loadFallbackFont(NVGcontext* const vg) -+{ -+ const int font = nvgFindFont(vg, NANOVG_DEJAVU_SANS_TTF); -+ if (font >= 0) -+ return font; ++ Internal() ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++ : hiddenApp(false), ++ hiddenWindow(hiddenApp) ++ { ++ hiddenWindow.setIgnoringKeyRepeat(true); ++ hiddenApp.idle(); ++ } ++#else ++ {} ++#endif ++}; -+ using namespace dpf_resources; -static void windowSizeCallback(GLFWwindow* win, int width, int height) { - if (glfwGetWindowAttrib(win, GLFW_MAXIMIZED)) @@ -207,21 +208,24 @@ - return; - settings::windowSize = math::Vec(width, height); - // DEBUG("windowSizeCallback %d %d", width, height); -+ return nvgCreateFontMem(vg, NANOVG_DEJAVU_SANS_TTF, -+ (uchar*)dejavusans_ttf, dejavusans_ttf_size, 0); - } -+#endif +-} ++#ifndef DGL_NO_SHARED_RESOURCES ++static int loadFallbackFont(NVGcontext* const vg) ++{ ++ const int font = nvgFindFont(vg, NANOVG_DEJAVU_SANS_TTF); ++ if (font >= 0) ++ return font; ++ using namespace dpf_resources; -static void windowMaximizeCallback(GLFWwindow* win, int maximized) { - settings::windowMaximized = maximized; - // DEBUG("windowMaximizeCallback %d", maximized); --} -+Window::Window() { -+ internal = new Internal; - -+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); - ++ return nvgCreateFontMem(vg, NANOVG_DEJAVU_SANS_TTF, ++ (uchar*)dejavusans_ttf, dejavusans_ttf_size, 0); + } +- +- -static void mouseButtonCallback(GLFWwindow* win, int button, int action, int mods) { - contextSet((Context*) glfwGetWindowUserPointer(win)); -#if defined ARCH_MAC @@ -234,19 +238,56 @@ - if (button == GLFW_MOUSE_BUTTON_LEFT && (mods & RACK_MOD_MASK) == (GLFW_MOD_CONTROL | GLFW_MOD_SHIFT)) { - button = GLFW_MOUSE_BUTTON_MIDDLE; - mods &= ~(GLFW_MOD_CONTROL | GLFW_MOD_SHIFT); +- } + #endif + +- APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods); +-} +- + +-static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { +- contextSet((Context*) glfwGetWindowUserPointer(win)); +- math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round(); +- math::Vec mouseDelta = mousePos.minus(APP->window->internal->lastMousePos); ++Window::Window() { ++ internal = new Internal; + +- // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. +- if (APP->window->internal->ignoreNextMouseDelta) { +- APP->window->internal->ignoreNextMouseDelta = false; +- mouseDelta = math::Vec(); - } + // Set up NanoVG + const int nvgFlags = NVG_ANTIALIAS; + +- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); +- (void) cursorMode; ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); + vg = nvgCreateGL(nvgFlags); ++#else ++ vg = static_cast(APP)->tlw->getContext(); ++#endif + DISTRHO_SAFE_ASSERT_RETURN(vg != nullptr,); + +-#if defined ARCH_MAC +- // Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own. +- // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. +- if (cursorMode == GLFW_CURSOR_HIDDEN) { +- // CGSetLocalEventsSuppressionInterval(0.0); +- glfwSetCursorPos(win, APP->window->internal->lastMousePos.x, APP->window->internal->lastMousePos.y); +- CGAssociateMouseAndMouseCursorPosition(true); +- mousePos = APP->window->internal->lastMousePos; +- } +- // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window +- glfwSetCursor(win, NULL); +#ifdef NANOVG_GLES2 + fbVg = nvgCreateSharedGLES2(vg, nvgFlags); +#else + fbVg = nvgCreateSharedGL2(vg, nvgFlags); #endif -- APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods); --} +- APP->window->internal->lastMousePos = mousePos; + // Load default Blendish font +#ifndef DGL_NO_SHARED_RESOURCES + uiFont = std::make_shared(); @@ -263,55 +304,51 @@ + uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); +#endif +- APP->event->handleHover(mousePos, mouseDelta); + if (uiFont != nullptr) + bndSetFont(uiFont->handle); --static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round(); -- math::Vec mouseDelta = mousePos.minus(APP->window->internal->lastMousePos); +- // Keyboard/mouse MIDI driver +- int width, height; +- glfwGetWindowSize(win, &width, &height); +- math::Vec scaledPos(xpos / width, ypos / height); +- keyboard::mouseMove(scaledPos); +#ifdef DISTRHO_OS_WASM + emscripten_lock_orientation(EMSCRIPTEN_ORIENTATION_LANDSCAPE_PRIMARY); +#endif -+} + } -- // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. -- if (APP->window->internal->ignoreNextMouseDelta) { -- APP->window->internal->ignoreNextMouseDelta = false; -- mouseDelta = math::Vec(); -+void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui) +- +-static void cursorEnterCallback(GLFWwindow* win, int entered) { +- contextSet((Context*) glfwGetWindowUserPointer(win)); +- if (!entered) { +- APP->event->handleLeave(); ++void WindowSetPluginRemote(Window* const window, NanoTopLevelWidget* const tlw) +{ + // if nanovg context failed, init only bare minimum + if (window->vg == nullptr) + { -+ if (ui != nullptr) ++ if (tlw != nullptr) + { -+ window->internal->ui = ui; -+ window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight()); ++ window->internal->tlw = tlw; ++ window->internal->size = rack::math::Vec(tlw->getWidth(), tlw->getHeight()); + } + else + { -+ window->internal->ui = nullptr; ++ window->internal->tlw = nullptr; + window->internal->callback = nullptr; + } + return; } +-} -- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); -- (void) cursorMode; - +-static void scrollCallback(GLFWwindow* win, double x, double y) { +- contextSet((Context*) glfwGetWindowUserPointer(win)); +- math::Vec scrollDelta = math::Vec(x, y); -#if defined ARCH_MAC -- // Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own. -- // This is not an ideal implementation. For example, if the user drags off the screen, the new mouse position will be clamped. -- if (cursorMode == GLFW_CURSOR_HIDDEN) { -- // CGSetLocalEventsSuppressionInterval(0.0); -- glfwSetCursorPos(win, APP->window->internal->lastMousePos.x, APP->window->internal->lastMousePos.y); -- CGAssociateMouseAndMouseCursorPosition(true); -- mousePos = APP->window->internal->lastMousePos; -- } -- // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window -- glfwSetCursor(win, NULL); -+ if (ui != nullptr) +- scrollDelta = scrollDelta.mult(10.0); ++ if (tlw != nullptr) + { + const GLubyte* vendor = glGetString(GL_VENDOR); + const GLubyte* renderer = glGetString(GL_RENDERER); @@ -319,18 +356,21 @@ + INFO("Renderer: %s %s", vendor, renderer); + INFO("OpenGL: %s", version); + -+ window->internal->ui = ui; -+ window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight()); ++ window->internal->tlw = tlw; ++ window->internal->size = rack::math::Vec(tlw->getWidth(), tlw->getHeight()); + ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + // Set up NanoVG -+ window->internal->r_vg = ui->getContext(); ++ window->internal->r_vg = tlw->getContext(); +#ifdef NANOVG_GLES2 + window->internal->r_fbVg = nvgCreateSharedGLES2(window->internal->r_vg, NVG_ANTIALIAS); -+#else + #else +- scrollDelta = scrollDelta.mult(50.0); + window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS); #endif -- APP->window->internal->lastMousePos = mousePos; +- APP->event->handleScroll(APP->window->internal->lastMousePos, scrollDelta); +-} + // swap contexts + window->internal->o_vg = window->vg; + window->internal->o_fbVg = window->fbVg; @@ -354,16 +394,15 @@ + image.second->handle = nvgCreateImage(window->vg, image.second->ofilename.c_str(), + NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); + } ++#endif -- APP->event->handleHover(mousePos, mouseDelta); + // Init settings + WindowParametersRestore(window); -- // Keyboard/mouse MIDI driver -- int width, height; -- glfwGetWindowSize(win, &width, &height); -- math::Vec scaledPos(xpos / width, ypos / height); -- keyboard::mouseMove(scaledPos); +-static void charCallback(GLFWwindow* win, unsigned int codepoint) { +- contextSet((Context*) glfwGetWindowUserPointer(win)); +- if (APP->event->handleText(APP->window->internal->lastMousePos, codepoint)) +- return; -} + widget::Widget::ContextCreateEvent e; + APP->scene->onContextCreate(e); @@ -372,7 +411,8 @@ + { + widget::Widget::ContextDestroyEvent e; + APP->scene->onContextDestroy(e); -+ + ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS + // swap contexts + window->uiFont->vg = window->internal->o_vg; + window->vg = window->internal->o_vg; @@ -396,75 +436,16 @@ + image.second->ohandle = -1; + } +-static void keyCallback(GLFWwindow* win, int key, int scancode, int action, int mods) { +- contextSet((Context*) glfwGetWindowUserPointer(win)); +- if (APP->event->handleKey(APP->window->internal->lastMousePos, key, scancode, action, mods)) +- return; +#if defined NANOVG_GLES2 + nvgDeleteGLES2(window->internal->r_fbVg); +#else + nvgDeleteGL2(window->internal->r_fbVg); +#endif - --static void cursorEnterCallback(GLFWwindow* win, int entered) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- if (!entered) { -- APP->event->handleLeave(); -+ window->internal->ui = nullptr; -+ window->internal->callback = nullptr; - } - } - -+void WindowSetMods(Window* const window, const int mods) -+{ -+ window->internal->mods = mods; -+} - --static void scrollCallback(GLFWwindow* win, double x, double y) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- math::Vec scrollDelta = math::Vec(x, y); --#if defined ARCH_MAC -- scrollDelta = scrollDelta.mult(10.0); -+Window::~Window() { -+ { -+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); -+ internal->hiddenWindow.close(); -+ internal->hiddenApp.idle(); -+ -+ // Fonts and Images in the cache must be deleted before the NanoVG context is deleted -+ internal->fontCache.clear(); -+ internal->imageCache.clear(); -+ -+ if (vg != nullptr) -+ { -+#if defined NANOVG_GLES2 -+ nvgDeleteGLES2(internal->o_fbVg != nullptr ? internal->o_fbVg : fbVg); -+ nvgDeleteGLES2(internal->o_vg != nullptr ? internal->o_vg : vg); - #else -- scrollDelta = scrollDelta.mult(50.0); -+ nvgDeleteGL2(internal->o_fbVg != nullptr ? internal->o_fbVg : fbVg); -+ nvgDeleteGL2(internal->o_vg != nullptr ? internal->o_vg : vg); - #endif -+ } -+ } - -- APP->event->handleScroll(APP->window->internal->lastMousePos, scrollDelta); -+ delete internal; - } - - --static void charCallback(GLFWwindow* win, unsigned int codepoint) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- if (APP->event->handleText(APP->window->internal->lastMousePos, codepoint)) -- return; -+math::Vec Window::getSize() { -+ return internal->size; - } - - --static void keyCallback(GLFWwindow* win, int key, int scancode, int action, int mods) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- if (APP->event->handleKey(APP->window->internal->lastMousePos, key, scancode, action, mods)) -- return; -+void Window::setSize(math::Vec size) { -+ size = size.max(WINDOW_SIZE_MIN); -+ internal->size = size; ++#endif - // Keyboard/mouse MIDI driver - if (action == GLFW_PRESS && (mods & RACK_MOD_MASK) == 0) { @@ -472,9 +453,9 @@ - } - if (action == GLFW_RELEASE) { - keyboard::release(key); -- } -+ if (DISTRHO_NAMESPACE::UI* const ui = internal->ui) -+ ui->setSize(internal->size.x, internal->size.y); ++ window->internal->tlw = nullptr; ++ window->internal->callback = nullptr; + } } - @@ -483,25 +464,56 @@ - std::vector pathsVec; - for (int i = 0; i < count; i++) { - pathsVec.push_back(paths[i]); -- } ++void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui) ++{ ++ // if nanovg context failed, init only bare minimum ++ if (window->vg == nullptr) ++ { ++ if (ui != nullptr) ++ { ++ window->internal->ui = ui; ++ window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight()); ++ } ++ else ++ { ++ window->internal->ui = nullptr; ++ window->internal->callback = nullptr; ++ } ++ return; + } - APP->event->handleDrop(APP->window->internal->lastMousePos, pathsVec); -+void WindowSetInternalSize(rack::window::Window* const window, math::Vec size) { -+ size = size.max(WINDOW_SIZE_MIN); -+ window->internal->size = size; - } - +-} +- -static void errorCallback(int error, const char* description) { - WARN("GLFW error %d: %s", error, description); -+void Window::run() { -+ internal->frame = 0; - } - - +-} +- +- -Window::Window() { - internal = new Internal; - int err; -- ++ if (ui != nullptr) ++ { ++ const GLubyte* vendor = glGetString(GL_VENDOR); ++ const GLubyte* renderer = glGetString(GL_RENDERER); ++ const GLubyte* version = glGetString(GL_VERSION); ++ INFO("Renderer: %s %s", vendor, renderer); ++ INFO("OpenGL: %s", version); ++ ++ window->internal->tlw = ui; ++ window->internal->ui = ui; ++ window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight()); ++ ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++ // Set up NanoVG ++ window->internal->r_vg = ui->getContext(); ++#ifdef NANOVG_GLES2 ++ window->internal->r_fbVg = nvgCreateSharedGLES2(window->internal->r_vg, NVG_ANTIALIAS); ++#else ++ window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS); ++#endif + - // Set window hints -#if defined NANOVG_GL2 - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); @@ -582,10 +594,36 @@ - const GLubyte* version = glGetString(GL_VERSION); - INFO("Renderer: %s %s", vendor, renderer); - INFO("OpenGL: %s", version); -- ++ // swap contexts ++ window->internal->o_vg = window->vg; ++ window->internal->o_fbVg = window->fbVg; ++ window->vg = window->internal->r_vg; ++ window->fbVg = window->internal->r_fbVg; ++ ++ // also for fonts and images ++ window->uiFont->vg = window->vg; ++ window->uiFont->handle = loadFallbackFont(window->vg); ++ for (auto& font : window->internal->fontCache) ++ { ++ font.second->vg = window->vg; ++ font.second->ohandle = font.second->handle; ++ font.second->handle = nvgCreateFont(window->vg, ++ font.second->ofilename.c_str(), font.second->ofilename.c_str()); ++ } ++ for (auto& image : window->internal->imageCache) ++ { ++ image.second->vg = window->vg; ++ image.second->ohandle = image.second->handle; ++ image.second->handle = nvgCreateImage(window->vg, image.second->ofilename.c_str(), ++ NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); ++ } ++#endif + - // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. - glGetError(); -- ++ // Init settings ++ WindowParametersRestore(window); + - // Set up NanoVG - int nvgFlags = NVG_ANTIALIAS; -#if defined NANOVG_GL2 @@ -599,15 +637,146 @@ - if (!vg) { - osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize NanoVG. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed."); - throw Exception("Could not initialize NanoVG"); -- } -- ++ widget::Widget::ContextCreateEvent e; ++ APP->scene->onContextCreate(e); + } ++ else ++ { ++ widget::Widget::ContextDestroyEvent e; ++ APP->scene->onContextDestroy(e); + - // Load default Blendish font - uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); - bndSetFont(uiFont->handle); -- ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++ // swap contexts ++ window->uiFont->vg = window->internal->o_vg; ++ window->vg = window->internal->o_vg; ++ window->fbVg = window->internal->o_fbVg; ++ window->internal->o_vg = nullptr; ++ window->internal->o_fbVg = nullptr; ++ ++ // also for fonts and images ++ window->uiFont->vg = window->vg; ++ window->uiFont->handle = loadFallbackFont(window->vg); ++ for (auto& font : window->internal->fontCache) ++ { ++ font.second->vg = window->vg; ++ font.second->handle = font.second->ohandle; ++ font.second->ohandle = -1; ++ } ++ for (auto& image : window->internal->imageCache) ++ { ++ image.second->vg = window->vg; ++ image.second->handle = image.second->ohandle; ++ image.second->ohandle = -1; ++ } + - if (APP->scene) { - widget::Widget::ContextCreateEvent e; - APP->scene->onContextCreate(e); ++#if defined NANOVG_GLES2 ++ nvgDeleteGLES2(window->internal->r_fbVg); ++#else ++ nvgDeleteGL2(window->internal->r_fbVg); ++#endif ++#endif ++ ++ window->internal->tlw = nullptr; ++ window->internal->ui = nullptr; ++ window->internal->callback = nullptr; + } + } + ++void WindowSetMods(Window* const window, const int mods) ++{ ++ window->internal->mods = mods; ++} + + Window::~Window() { +- if (APP->scene) { +- widget::Widget::ContextDestroyEvent e; +- APP->scene->onContextDestroy(e); +- } ++ { ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); ++ internal->hiddenWindow.close(); ++ internal->hiddenApp.idle(); ++#endif + +- // Fonts and Images in the cache must be deleted before the NanoVG context is deleted +- internal->fontCache.clear(); +- internal->imageCache.clear(); +- +- // nvgDeleteClone(fbVg); +- +-#if defined NANOVG_GL2 +- nvgDeleteGL2(vg); +- nvgDeleteGL2(fbVg); +-#elif defined NANOVG_GL3 +- nvgDeleteGL3(vg); +-#elif defined NANOVG_GLES2 +- nvgDeleteGLES2(vg); ++ // Fonts and Images in the cache must be deleted before the NanoVG context is deleted ++ internal->fontCache.clear(); ++ internal->imageCache.clear(); ++ ++ if (vg != nullptr) ++ { ++#if DISTRHO_PLUGIN_WANT_DIRECT_ACCESS ++#if defined NANOVG_GLES2 ++ nvgDeleteGLES2(internal->o_fbVg != nullptr ? internal->o_fbVg : fbVg); ++ nvgDeleteGLES2(internal->o_vg != nullptr ? internal->o_vg : vg); ++#else ++ nvgDeleteGL2(internal->o_fbVg != nullptr ? internal->o_fbVg : fbVg); ++ nvgDeleteGL2(internal->o_vg != nullptr ? internal->o_vg : vg); ++#endif ++#else ++#if defined NANOVG_GLES2 ++ nvgDeleteGLES2(fbVg); ++#else ++ nvgDeleteGL2(fbVg); ++#endif + #endif ++ } ++ } + +- glfwDestroyWindow(win); + delete internal; + } + + + math::Vec Window::getSize() { +- int width, height; +- glfwGetWindowSize(win, &width, &height); +- return math::Vec(width, height); ++ return internal->size; + } + + + void Window::setSize(math::Vec size) { + size = size.max(WINDOW_SIZE_MIN); +- glfwSetWindowSize(win, size.x, size.y); ++ internal->size = size; ++ ++ if (DGL_NAMESPACE::NanoTopLevelWidget* const tlw = internal->ui) ++ tlw->setSize(internal->size.x, internal->size.y); ++} ++ ++void WindowSetInternalSize(rack::window::Window* const window, math::Vec size) { ++ size = size.max(WINDOW_SIZE_MIN); ++ window->internal->size = size; + } + + + void Window::run() { + internal->frame = 0; +- while (!glfwWindowShouldClose(win)) { +- step(); ++} ++ ++ +#ifndef DGL_USE_GLES +static void Window__flipBitmap(uint8_t* pixels, const int width, const int height, const int depth) { + for (int y = 0; y < height / 2; y++) { @@ -620,10 +789,6 @@ } --Window::~Window() { -- if (APP->scene) { -- widget::Widget::ContextDestroyEvent e; -- APP->scene->onContextDestroy(e); +#ifdef STBI_WRITE_NO_STDIO +static void Window__downscaleBitmap(uint8_t* pixels, int& width, int& height) { + int targetWidth = width; @@ -650,62 +815,31 @@ + const int xs = static_cast(x * scale); + std::memmove(pixels + (width * y + x) * 3, pixels + (width * ys + xs) * 3, 3); + } - } - -- // Fonts and Images in the cache must be deleted before the NanoVG context is deleted -- internal->fontCache.clear(); -- internal->imageCache.clear(); -- -- // nvgDeleteClone(fbVg); -- --#if defined NANOVG_GL2 -- nvgDeleteGL2(vg); -- nvgDeleteGL2(fbVg); --#elif defined NANOVG_GL3 -- nvgDeleteGL3(vg); --#elif defined NANOVG_GLES2 -- nvgDeleteGLES2(vg); --#endif -- -- glfwDestroyWindow(win); -- delete internal; --} -- -- --math::Vec Window::getSize() { -- int width, height; -- glfwGetWindowSize(win, &width, &height); -- return math::Vec(width, height); ++ } ++ + width = targetWidth; + height = targetHeight; - } - -- --void Window::setSize(math::Vec size) { -- size = size.max(WINDOW_SIZE_MIN); -- glfwSetWindowSize(win, size.x, size.y); ++} ++ +static void Window__writeImagePNG(void* context, void* data, int size) { + USE_NAMESPACE_DISTRHO -+ UI* const ui = static_cast(context); -+ ui->setState("screenshot", String::asBase64(data, size).buffer()); - } ++ CardinalBaseUI* const ui = static_cast(context); ++ if (char* const screenshot = String::asBase64(data, size).getAndReleaseBuffer()) { ++ ui->setState("screenshot", screenshot); ++ remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); ++ std::free(screenshot); ++ } ++} +#endif +#endif - - --void Window::run() { -- internal->frame = 0; -- while (!glfwWindowShouldClose(win)) { -- step(); -- } --} -+void Window::step() { -+ DISTRHO_SAFE_ASSERT_RETURN(internal->ui != nullptr,); - ++ ++ + void Window::step() { ++ DISTRHO_SAFE_ASSERT_RETURN(internal->tlw != nullptr,); ++ + if (vg == nullptr) + return; - --void Window::step() { ++ double frameTime = system::getTime(); double lastFrameTime = internal->frameTime; internal->frameTime = frameTime; @@ -748,12 +882,12 @@ if (APP->patch->path != "") { windowTitle += " - "; if (!APP->history->isSaved()) -@@ -455,246 +480,189 @@ +@@ -455,246 +623,189 @@ windowTitle += system::getFilename(APP->patch->path); } if (windowTitle != internal->lastWindowTitle) { - glfwSetWindowTitle(win, windowTitle.c_str()); -+ internal->ui->getWindow().setTitle(windowTitle.c_str()); ++ internal->tlw->getWindow().setTitle(windowTitle.c_str()); internal->lastWindowTitle = windowTitle; } @@ -766,7 +900,7 @@ - glfwGetWindowContentScale(win, &newPixelRatio, NULL); - newPixelRatio = std::floor(newPixelRatio + 0.5); - } -+ float newPixelRatio = internal->ui->getScaleFactor(); ++ float newPixelRatio = internal->tlw->getScaleFactor(); if (newPixelRatio != pixelRatio) { pixelRatio = newPixelRatio; APP->event->handleDirty(); @@ -789,8 +923,8 @@ - glfwGetFramebufferSize(win, &fbWidth, &fbHeight); - int winWidth, winHeight; - glfwGetWindowSize(win, &winWidth, &winHeight); -+ int winWidth = internal->ui->getWidth(); -+ int winHeight = internal->ui->getHeight(); ++ int winWidth = internal->tlw->getWidth(); ++ int winHeight = internal->tlw->getHeight(); + int fbWidth = winWidth;// * newPixelRatio; + int fbHeight = winHeight;// * newPixelRatio; windowRatio = (float)fbWidth / winWidth; @@ -842,19 +976,6 @@ - if (frameDurationRemaining > 0.0) { - std::this_thread::sleep_for(std::chrono::duration(frameDurationRemaining)); - } -- -- // t5 = system::getTime(); -- -- // DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f", -- // (t1 - frameTime) * 1e3f, -- // (t2 - t1) * 1e3f, -- // (t3 - t2) * 1e3f, -- // (t4 - t2) * 1e3f, -- // (t5 - t4) * 1e3f, -- // (t5 - frameTime) * 1e3f -- // ); -- internal->frame++; --} +#ifndef DGL_USE_GLES + if (internal->generateScreenshotStep != kScreenshotStepNone) { + ++internal->generateScreenshotStep; @@ -867,16 +988,24 @@ + constexpr const int depth = 3; +#endif +- // t5 = system::getTime(); + // Allocate pixel color buffer + uint8_t* const pixels = new uint8_t[winHeight * winWidth * 4]; --void Window::activateContext() { -- glfwMakeContextCurrent(win); +- // DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f", +- // (t1 - frameTime) * 1e3f, +- // (t2 - t1) * 1e3f, +- // (t3 - t2) * 1e3f, +- // (t4 - t2) * 1e3f, +- // (t5 - t4) * 1e3f, +- // (t5 - frameTime) * 1e3f +- // ); +- internal->frame++; -} + // glReadPixels defaults to GL_BACK, but the back-buffer is unstable, so use the front buffer (what the user sees) + glReadBuffer(GL_FRONT); + glReadPixels(0, 0, winWidth, winHeight, depth == 3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE, pixels); -+ + + if (internal->generateScreenshotStep == kScreenshotStepSaving) + { + // Write pixels to PNG @@ -892,10 +1021,18 @@ + stbi_write_png("screenshot.png", winWidth, winHeight, depth, pixelsWithOffset, stride); +#endif +-void Window::activateContext() { +- glfwMakeContextCurrent(win); + internal->generateScreenshotStep = kScreenshotStepNone; + APP->scene->menuBar->show(); + APP->scene->rack->children.front()->show(); + } ++ ++ delete[] pixels; ++ } ++#endif + } + -static void flipBitmap(uint8_t* pixels, int width, int height, int depth) { - for (int y = 0; y < height / 2; y++) { @@ -904,9 +1041,8 @@ - std::memcpy(tmp, &pixels[y * width * depth], width * depth); - std::memcpy(&pixels[y * width * depth], &pixels[flipY * width * depth], width * depth); - std::memcpy(&pixels[flipY * width * depth], tmp, width * depth); -+ delete[] pixels; - } -+#endif +- } ++void Window::activateContext() { } @@ -975,7 +1111,7 @@ - nvgImageSize(vg, fbw->getImageHandle(), &width, &height); - uint8_t* pixels = new uint8_t[height * width * 4]; - glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); -+void Window::activateContext() { ++void Window::screenshot(const std::string&) { +} - // Write pixels to PNG @@ -988,19 +1124,15 @@ - delete fbw; - } - } -+void Window::screenshot(const std::string&) { -+} -+ -+ +void Window::screenshotModules(const std::string&, float) { } void Window::close() { - glfwSetWindowShouldClose(win, GLFW_TRUE); -+ DISTRHO_SAFE_ASSERT_RETURN(internal->ui != nullptr,); ++ DISTRHO_SAFE_ASSERT_RETURN(internal->tlw != nullptr,); + -+ internal->ui->getWindow().close(); ++ internal->tlw->getWindow().close(); } @@ -1013,7 +1145,7 @@ - glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); -#else - glfwSetInputMode(win, GLFW_CURSOR, GLFW_CURSOR_DISABLED); -+ emscripten_request_pointerlock(internal->ui->getWindow().getApp().getClassName(), false); ++ emscripten_request_pointerlock(internal->tlw->getWindow().getApp().getClassName(), false); #endif - internal->ignoreNextMouseDelta = true; } @@ -1071,7 +1203,7 @@ +void Window::setFullScreen(const bool fullscreen) { +#ifdef DISTRHO_OS_WASM + if (fullscreen) -+ emscripten_request_fullscreen(internal->ui->getWindow().getApp().getClassName(), false); ++ emscripten_request_fullscreen(internal->tlw->getWindow().getApp().getClassName(), false); + else + emscripten_exit_fullscreen(); +#endif @@ -1097,7 +1229,7 @@ double Window::getMonitorRefreshRate() { return internal->monitorRefreshRate; } -@@ -722,14 +690,15 @@ +@@ -722,14 +833,15 @@ return pair->second; // Load font @@ -1116,7 +1248,7 @@ } internal->fontCache[filename] = font; return font; -@@ -742,14 +711,15 @@ +@@ -742,14 +854,15 @@ return pair->second; // Load image @@ -1135,7 +1267,7 @@ } internal->imageCache[filename] = image; return image; -@@ -766,28 +736,156 @@ +@@ -766,28 +879,156 @@ } diff --git a/src/override/diffs/blendish.c.diff b/src/override/diffs/blendish.c.diff index d1c1b8a..90a2481 100644 --- a/src/override/diffs/blendish.c.diff +++ b/src/override/diffs/blendish.c.diff @@ -1,5 +1,5 @@ ---- ../Rack/dep/oui-blendish/blendish.c 2022-09-21 20:26:10.733413463 +0100 -+++ blendish.c 2022-09-21 20:18:50.294557597 +0100 +--- ../Rack/dep/oui-blendish/blendish.c 2022-09-21 19:49:29.973066921 +0100 ++++ blendish.c 2022-09-21 19:41:45.883648777 +0100 @@ -61,7 +61,7 @@ } diff --git a/src/override/diffs/common.cpp.diff b/src/override/diffs/common.cpp.diff index 2569432..5675f5a 100644 --- a/src/override/diffs/common.cpp.diff +++ b/src/override/diffs/common.cpp.diff @@ -1,6 +1,6 @@ ---- ../Rack/src/common.cpp 2022-09-21 20:25:53.591040280 +0100 -+++ common.cpp 2022-09-21 20:18:50.294557597 +0100 -@@ -1,33 +1,77 @@ +--- ../Rack/src/common.cpp 2022-09-21 19:49:12.199540706 +0100 ++++ common.cpp 2022-12-02 19:11:45.780215974 +0000 +@@ -1,12 +1,57 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho @@ -42,11 +42,14 @@ #include FILE* fopen_u8(const char* filename, const char* mode) { +- return _wfopen(rack::string::UTF8toUTF16(filename).c_str(), rack::string::UTF8toUTF16(mode).c_str()); ++ if (FILE* const f = _wfopen(rack::string::UTF8toUTF16(filename).c_str(), rack::string::UTF8toUTF16(mode).c_str())) ++ return f; + if (std::strncmp(filename, "\\\\?\\", 4) == 0 && std::getenv("CARDINAL_UNDER_WINE") != nullptr) -+ filename = "Z:\\dev\\null"; - return _wfopen(rack::string::UTF8toUTF16(filename).c_str(), rack::string::UTF8toUTF16(mode).c_str()); - } - ++ return _wfopen(L"Z:\\dev\\null", rack::string::UTF8toUTF16(mode).c_str()); ++ return nullptr; ++} ++ +#elif defined(DISTRHO_OS_WASM) +#include +#undef fopen @@ -54,10 +57,10 @@ +FILE* fopen_wasm(const char* filename, const char* mode) { + chmod(filename, 0777); + return std::fopen(filename, mode); -+} -+ - #endif + } + #endif +@@ -14,20 +59,21 @@ namespace rack { diff --git a/src/override/diffs/context.cpp.diff b/src/override/diffs/context.cpp.diff index d34fba3..8b6fa4d 100644 --- a/src/override/diffs/context.cpp.diff +++ b/src/override/diffs/context.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/context.cpp 2022-09-21 20:25:53.591040280 +0100 -+++ context.cpp 2022-09-21 20:18:50.294557597 +0100 +--- ../Rack/src/context.cpp 2022-09-21 19:49:12.199540706 +0100 ++++ context.cpp 2022-09-21 19:41:45.883648777 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin diff --git a/src/override/diffs/minblep.cpp.diff b/src/override/diffs/minblep.cpp.diff index 2af153a..5d549e8 100644 --- a/src/override/diffs/minblep.cpp.diff +++ b/src/override/diffs/minblep.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/dsp/minblep.cpp 2022-09-21 20:25:53.592040301 +0100 -+++ minblep.cpp 2022-09-21 20:18:50.295557620 +0100 +--- ../Rack/src/dsp/minblep.cpp 2022-09-21 19:49:12.200540736 +0100 ++++ minblep.cpp 2022-09-21 19:41:45.884648820 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin diff --git a/src/override/diffs/plugin.cpp.diff b/src/override/diffs/plugin.cpp.diff index c49eb23..2a68bf6 100644 --- a/src/override/diffs/plugin.cpp.diff +++ b/src/override/diffs/plugin.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/plugin.cpp 2022-09-21 20:25:53.592040301 +0100 -+++ plugin.cpp 2022-11-29 19:49:19.197926669 +0000 +--- ../Rack/src/plugin.cpp 2022-09-21 19:49:12.200540736 +0100 ++++ plugin.cpp 2022-11-25 18:24:09.485450570 +0000 @@ -1,342 +1,41 @@ -#include -#include