From 5c26b531f65403c4bde423b02370d12294629134 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 8 Jul 2022 12:45:51 +0100 Subject: [PATCH] Regen source diffs vs Rack Signed-off-by: falkTX --- src/override/diffs/Engine.cpp.diff | 96 ++++---- src/override/diffs/MenuBar.cpp.diff | 245 ++++++++++++------- src/override/diffs/Model.cpp.diff | 93 ++++++- src/override/diffs/Scene.cpp.diff | 26 +- src/override/diffs/Window.cpp.diff | 365 +++++++++++++++------------- src/override/diffs/blendish.c.diff | 4 +- src/override/diffs/common.cpp.diff | 17 +- src/override/diffs/context.cpp.diff | 4 +- src/override/diffs/plugin.cpp.diff | 20 +- 9 files changed, 533 insertions(+), 337 deletions(-) diff --git a/src/override/diffs/Engine.cpp.diff b/src/override/diffs/Engine.cpp.diff index bd22378..adc19eb 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-02-05 22:30:09.253393116 +0000 -+++ Engine.cpp 2022-02-10 18:51:20.077011285 +0000 +--- ../Rack/src/engine/Engine.cpp 2022-06-04 19:14:19.947414815 +0100 ++++ Engine.cpp 2022-06-27 19:37:11.048290788 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin @@ -224,15 +224,17 @@ // moduleId std::map modulesCache; -@@ -199,6 +80,7 @@ +@@ -198,7 +79,9 @@ + int64_t blockFrame = 0; double blockTime = 0.0; int blockFrames = 0; ++ bool aboutToClose = false; +#ifndef HEADLESS // Meter int meterCount = 0; double meterTotal = 0.0; -@@ -206,6 +88,7 @@ +@@ -206,6 +89,7 @@ double meterLastTime = -INFINITY; double meterLastAverage = 0.0; double meterLastMax = 0.0; @@ -240,7 +242,7 @@ // Parameter smoothing Module* smoothModule = NULL; -@@ -217,22 +100,6 @@ +@@ -217,22 +101,6 @@ Readers lock when using the engine's state. */ SharedMutex mutex; @@ -263,7 +265,7 @@ }; -@@ -260,76 +127,11 @@ +@@ -260,76 +128,11 @@ } @@ -341,7 +343,7 @@ // Copy all voltages from output to input for (int c = 0; c < channels; c++) { float v = output->voltages[c]; -@@ -346,6 +148,53 @@ +@@ -346,6 +149,53 @@ } @@ -395,7 +397,7 @@ /** Steps a single frame */ static void Engine_stepFrame(Engine* that) { -@@ -372,13 +221,8 @@ +@@ -372,13 +222,8 @@ } } @@ -410,7 +412,7 @@ if (module->leftExpander.messageFlipRequested) { std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage); module->leftExpander.messageFlipRequested = false; -@@ -389,13 +233,32 @@ +@@ -389,13 +234,32 @@ } } @@ -449,7 +451,7 @@ } -@@ -416,32 +279,45 @@ +@@ -416,32 +280,45 @@ static void Engine_updateConnected(Engine* that) { // Find disconnected ports @@ -506,7 +508,7 @@ } } -@@ -460,37 +336,23 @@ +@@ -460,37 +337,23 @@ Engine::Engine() { internal = new Internal; @@ -552,7 +554,7 @@ delete internal; } -@@ -519,18 +381,22 @@ +@@ -519,18 +382,22 @@ removeModule_NoLock(module); delete module; } @@ -578,7 +580,7 @@ random::init(); internal->blockFrame = internal->frame; -@@ -543,18 +409,14 @@ +@@ -543,18 +410,14 @@ Engine_updateExpander_NoLock(this, module, true); } @@ -598,7 +600,7 @@ // Stop timer double endTime = system::getTime(); double meter = (endTime - startTime) / (frames * internal->sampleTime); -@@ -572,47 +434,20 @@ +@@ -572,47 +435,20 @@ internal->meterTotal = 0.0; internal->meterMax = 0.0; } @@ -648,7 +650,7 @@ } -@@ -635,20 +470,13 @@ +@@ -635,20 +471,13 @@ for (Module* module : internal->modules) { module->onSampleRateChange(e); } @@ -672,7 +674,7 @@ } -@@ -658,7 +486,6 @@ +@@ -658,7 +487,6 @@ void Engine::yieldWorkers() { @@ -680,7 +682,7 @@ } -@@ -698,17 +525,25 @@ +@@ -698,17 +526,25 @@ double Engine::getMeterAverage() { @@ -707,7 +709,7 @@ } -@@ -718,8 +553,12 @@ +@@ -718,8 +554,12 @@ for (Module* m : internal->modules) { if (i >= len) break; @@ -722,7 +724,7 @@ } return i; } -@@ -728,27 +567,43 @@ +@@ -728,27 +568,43 @@ std::vector Engine::getModuleIds() { SharedLock lock(internal->mutex); std::vector moduleIds; @@ -770,7 +772,7 @@ internal->modulesCache[module->id] = module; // Dispatch AddEvent Module::AddEvent eAdd; -@@ -772,11 +627,11 @@ +@@ -772,11 +628,11 @@ } @@ -787,7 +789,7 @@ // Dispatch RemoveEvent Module::RemoveEvent eRemove; module->onRemove(eRemove); -@@ -785,18 +640,14 @@ +@@ -785,18 +641,14 @@ if (paramHandle->moduleId == module->id) paramHandle->module = NULL; } @@ -808,7 +810,7 @@ } // Update expanders of other modules for (Module* m : internal->modules) { -@@ -809,14 +660,31 @@ +@@ -809,14 +661,31 @@ m->rightExpander.module = NULL; } } @@ -843,7 +845,7 @@ } -@@ -824,7 +692,8 @@ +@@ -824,7 +693,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); @@ -853,7 +855,7 @@ } -@@ -844,7 +713,7 @@ +@@ -844,7 +714,7 @@ void Engine::resetModule(Module* module) { std::lock_guard lock(internal->mutex); @@ -862,7 +864,7 @@ Module::ResetEvent eReset; module->onReset(eReset); -@@ -853,7 +722,7 @@ +@@ -853,7 +723,7 @@ void Engine::randomizeModule(Module* module) { std::lock_guard lock(internal->mutex); @@ -871,7 +873,7 @@ Module::RandomizeEvent eRandomize; module->onRandomize(eRandomize); -@@ -861,7 +730,7 @@ +@@ -861,7 +731,7 @@ void Engine::bypassModule(Module* module, bool bypassed) { @@ -880,7 +882,14 @@ if (module->isBypassed() == bypassed) return; -@@ -912,6 +781,10 @@ +@@ -907,11 +777,17 @@ + + + void Engine::prepareSave() { ++ if (internal->aboutToClose) ++ return; + SharedLock lock(internal->mutex); + for (Module* module : internal->modules) { Module::SaveEvent e; module->onSave(e); } @@ -891,7 +900,7 @@ } -@@ -946,16 +819,16 @@ +@@ -946,16 +822,16 @@ void Engine::addCable(Cable* cable) { std::lock_guard lock(internal->mutex); @@ -913,7 +922,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 +842,8 @@ +@@ -969,6 +845,8 @@ // Add the cable internal->cables.push_back(cable); internal->cablesCache[cable->id] = cable; @@ -922,7 +931,7 @@ Engine_updateConnected(this); // Dispatch input port event { -@@ -996,10 +871,12 @@ +@@ -996,10 +874,12 @@ void Engine::removeCable_NoLock(Cable* cable) { @@ -937,7 +946,7 @@ // Remove the cable internal->cablesCache.erase(cable->id); internal->cables.erase(it); -@@ -1085,11 +962,11 @@ +@@ -1085,11 +965,11 @@ std::lock_guard lock(internal->mutex); // New ParamHandles must be blank. // This means we don't have to refresh the cache. @@ -951,7 +960,7 @@ // Add it internal->paramHandles.insert(paramHandle); -@@ -1106,7 +983,7 @@ +@@ -1106,7 +986,7 @@ void Engine::removeParamHandle_NoLock(ParamHandle* paramHandle) { // Check that the ParamHandle is already added auto it = internal->paramHandles.find(paramHandle); @@ -960,7 +969,7 @@ // Remove it paramHandle->module = NULL; -@@ -1143,7 +1020,7 @@ +@@ -1143,7 +1023,7 @@ void Engine::updateParamHandle_NoLock(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) { // Check that it exists auto it = internal->paramHandles.find(paramHandle); @@ -969,7 +978,7 @@ // Set IDs paramHandle->moduleId = moduleId; -@@ -1187,6 +1064,10 @@ +@@ -1187,6 +1067,10 @@ json_t* moduleJ = module->toJson(); json_array_append_new(modulesJ, moduleJ); } @@ -980,7 +989,7 @@ json_object_set_new(rootJ, "modules", modulesJ); // cables -@@ -1197,11 +1078,6 @@ +@@ -1197,11 +1081,6 @@ } json_object_set_new(rootJ, "cables", cablesJ); @@ -992,7 +1001,7 @@ return rootJ; } -@@ -1225,14 +1101,20 @@ +@@ -1225,14 +1104,20 @@ } catch (Exception& e) { WARN("Cannot load model: %s", e.what()); @@ -1017,7 +1026,7 @@ try { // This doesn't need a lock because the Module is not added to the Engine yet. -@@ -1248,7 +1130,8 @@ +@@ -1248,7 +1133,8 @@ } catch (Exception& e) { WARN("Cannot load module: %s", e.what()); @@ -1027,7 +1036,7 @@ delete module; continue; } -@@ -1285,67 +1168,10 @@ +@@ -1285,67 +1171,15 @@ continue; } } @@ -1038,9 +1047,9 @@ - Module* masterModule = getModule(json_integer_value(masterModuleIdJ)); - setMasterModule(masterModule); - } --} -- -- + } + + -void EngineWorker::run() { - // Configure thread - contextSet(engine->internal->context); @@ -1083,15 +1092,18 @@ - }); - } - } ++void Engine::startFallbackThread() { } - void Engine::startFallbackThread() { +-void Engine::startFallbackThread() { - if (internal->fallbackThread.joinable()) - return; - - internal->fallbackRunning = true; - internal->fallbackThread = std::thread(Engine_fallbackRun, this); ++void Engine_setAboutToClose(Engine* const engine) { ++ engine->internal->aboutToClose = true; } diff --git a/src/override/diffs/MenuBar.cpp.diff b/src/override/diffs/MenuBar.cpp.diff index 36c6868..c08d090 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-02-26 23:08:06.697192725 +0000 -+++ MenuBar.cpp 2022-04-27 18:17:16.790097058 +0100 +--- ../Rack/src/app/MenuBar.cpp 2022-07-07 00:16:13.700491991 +0100 ++++ MenuBar.cpp 2022-07-08 12:33:18.481979775 +0100 @@ -1,8 +1,33 @@ +/* + * DISTRHO Cardinal Plugin @@ -36,7 +36,7 @@ #include #include #include -@@ -25,6 +50,11 @@ +@@ -25,8 +50,17 @@ #include #include @@ -47,8 +47,14 @@ +#include "../CardinalCommon.hpp" namespace rack { ++namespace asset { ++std::string patchesPath(); ++} ++ namespace app { -@@ -48,79 +78,79 @@ + namespace menuBar { + +@@ -48,79 +82,135 @@ }; @@ -72,9 +78,21 @@ struct FileButton : MenuButton { + const bool isStandalone; ++ std::vector demoPatches; + + FileButton(const bool standalone) -+ : MenuButton(), isStandalone(standalone) {} ++ : MenuButton(), isStandalone(standalone) ++ { ++ const std::string patchesDir = asset::patchesPath(); ++ ++ if (system::isDirectory(patchesDir)) ++ { ++ demoPatches = system::getEntries(patchesDir); ++ std::sort(demoPatches.begin(), demoPatches.end(), [](const std::string& a, const std::string& b){ ++ return string::lowercase(a) < string::lowercase(b); ++ }); ++ } ++ } + void onAction(const ActionEvent& e) override { ui::Menu* menu = createMenu(); @@ -88,6 +106,7 @@ - menu->addChild(createMenuItem("Open", RACK_MOD_CTRL_NAME "+O", []() { - APP->patch->loadDialog(); ++#ifndef DISTRHO_OS_WASM + menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() { + patchUtils::loadDialog(); })); @@ -103,35 +122,52 @@ - menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { - APP->patch->saveDialog(); -- })); + // NOTE: will do nothing if path is empty, intentionally + patchUtils::saveDialog(APP->patch->path); + }, APP->patch->path.empty())); ++ ++ menu->addChild(createMenuItem("Save as / Export...", RACK_MOD_CTRL_NAME "+Shift+S", []() { ++ patchUtils::saveAsDialog(); ++ })); ++#else ++ menu->addChild(createMenuItem("Import patch...", RACK_MOD_CTRL_NAME "+O", []() { ++ patchUtils::loadDialog(); + })); - menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() { - APP->patch->saveAsDialog(); -+ menu->addChild(createMenuItem("Save as / Export...", RACK_MOD_CTRL_NAME "+Shift+S", []() { ++ menu->addChild(createMenuItem("Import selection...", "", [=]() { ++ patchUtils::loadSelectionDialog(); ++ }, false, true)); ++ ++ menu->addChild(createMenuItem("Save and download compressed", RACK_MOD_CTRL_NAME "+Shift+S", []() { + patchUtils::saveAsDialog(); })); - menu->addChild(createMenuItem("Save a copy", "", []() { - APP->patch->saveAsDialog(false); -+ menu->addChild(createMenuItem("Export uncompressed json...", "", []() { ++ menu->addChild(createMenuItem("Save and download uncompressed", "", []() { + patchUtils::saveAsDialogUncompressed(); })); ++#endif -- menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { + menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { - APP->patch->revertDialog(); - }, APP->patch->path == "")); -+#ifdef HAVE_LIBLO -+ if (patchUtils::isRemoteConnected()) { -+ menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { -+ patchUtils::deployToRemote(); -+ })); ++ patchUtils::revertDialog(); ++ }, APP->patch->path.empty())); - menu->addChild(createMenuItem("Overwrite template", "", []() { - APP->patch->saveTemplateDialog(); - })); ++#ifdef HAVE_LIBLO ++ menu->addChild(new ui::MenuSeparator); + ++ if (patchUtils::isRemoteConnected()) { ++ menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { ++ patchUtils::deployToRemote(); ++ })); ++ + const bool autoDeploy = patchUtils::isRemoteAutoDeployed(); + menu->addChild(createCheckMenuItem("Auto deploy to MOD", "", + [=]() {return autoDeploy;}, @@ -144,33 +180,58 @@ + } +#endif + -+ menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() { -+ patchUtils::revertDialog(); -+ }, APP->patch->path.empty())); - ++#ifndef DISTRHO_OS_WASM menu->addChild(new ui::MenuSeparator); // Load selection - menu->addChild(createMenuItem("Import selection", "", [=]() { +- menu->addChild(createMenuItem("Import selection", "", [=]() { - APP->scene->rack->loadSelectionDialog(); ++ menu->addChild(createMenuItem("Import selection...", "", [=]() { + patchUtils::loadSelectionDialog(); }, false, true)); - menu->addChild(new ui::MenuSeparator); -+ if (isStandalone) { -+ menu->addChild(new ui::MenuSeparator); - +- - menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() { - APP->window->close(); -- })); ++ menu->addChild(createMenuItem("Export uncompressed json...", "", []() { ++ patchUtils::saveAsDialogUncompressed(); + })); ++#endif ++ ++ if (!demoPatches.empty()) ++ { ++ menu->addChild(new ui::MenuSeparator); ++ ++ menu->addChild(createSubmenuItem("Open Demo / Example project", "", [=](ui::Menu* const menu) { ++ for (std::string path : demoPatches) { ++ std::string label = system::getStem(path); ++ ++ for (size_t i=0, len=label.size(); iaddChild(createMenuItem(label, "", [path]() { ++ patchUtils::loadPathDialog(path, true); ++ })); ++ } ++ })); ++ } ++ ++#ifndef DISTRHO_OS_WASM ++ if (isStandalone) { ++ menu->addChild(new ui::MenuSeparator); ++ + menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() { + APP->window->close(); + })); -+ }; ++ } ++#endif } }; -@@ -166,7 +196,7 @@ +@@ -166,7 +256,7 @@ menu->addChild(new ui::MenuSeparator); @@ -179,7 +240,7 @@ } }; -@@ -256,7 +286,7 @@ +@@ -256,7 +346,7 @@ return settings::cableTension; } float getDefaultValue() override { @@ -188,10 +249,20 @@ } float getDisplayValue() override { return getValue() * 100; -@@ -421,28 +451,9 @@ - haloBrightnessSlider->box.size.x = 250.0; - menu->addChild(haloBrightnessSlider); +@@ -399,28 +489,6 @@ + menu->cornerFlags = BND_CORNER_TOP; + menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y)); +- menu->addChild(createMenuLabel("Window")); +- +- bool fullscreen = APP->window->isFullScreen(); +- std::string fullscreenText = "F11"; +- if (fullscreen) +- fullscreenText += " " CHECKMARK_STRING; +- menu->addChild(createMenuItem("Fullscreen", fullscreenText, [=]() { +- APP->window->setFullScreen(!fullscreen); +- })); +- - double frameRate = APP->window->getMonitorRefreshRate() / settings::frameSwapInterval; - menu->addChild(createSubmenuItem("Frame rate", string::f("%.0f Hz", frameRate), [=](ui::Menu* menu) { - for (int i = 1; i <= 6; i++) { @@ -203,35 +274,59 @@ - } - })); - -- bool fullscreen = APP->window->isFullScreen(); -- std::string fullscreenText = "F11"; -- if (fullscreen) -- fullscreenText += " " CHECKMARK_STRING; -- menu->addChild(createMenuItem("Fullscreen", fullscreenText, [=]() { -- APP->window->setFullScreen(!fullscreen); -- })); -- - menu->addChild(new ui::MenuSeparator); +- menu->addChild(new ui::MenuSeparator); + menu->addChild(createMenuLabel("Appearance")); -- menu->addChild(createBoolPtrMenuItem("Lock cursor while dragging params", "", &settings::allowCursorLock)); -+ // menu->addChild(createBoolPtrMenuItem("Hide cursor while dragging", "", &settings::allowCursorLock)); + menu->addChild(createBoolPtrMenuItem("Show tooltips", "", &settings::tooltips)); +@@ -446,9 +514,16 @@ + menu->addChild(haloBrightnessSlider); + + menu->addChild(new ui::MenuSeparator); ++ menu->addChild(createMenuLabel("Module dragging")); ++ ++ menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); ++ ++ menu->addChild(createBoolPtrMenuItem("Auto-squeeze modules when dragging", "", &settings::squeezeModules)); ++ ++ menu->addChild(new ui::MenuSeparator); + menu->addChild(createMenuLabel("Parameters")); + +- menu->addChild(createBoolPtrMenuItem("Lock cursor while dragging", "", &settings::allowCursorLock)); ++ // menu->addChild(createBoolPtrMenuItem("Lock cursor while dragging", "", &settings::allowCursorLock)); static const std::vector knobModeLabels = { "Linear", -@@ -467,56 +478,34 @@ +@@ -473,11 +548,24 @@ menu->addChild(knobScrollSensitivitySlider); - menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); -- } --}; -- + menu->addChild(new ui::MenuSeparator); +- menu->addChild(createMenuLabel("Module dragging")); ++ menu->addChild(createMenuLabel("Window")); --//////////////////// --// Engine --//////////////////// +- menu->addChild(createBoolPtrMenuItem("Lock positions", "", &settings::lockModules)); + menu->addChild(createBoolPtrMenuItem("Invert zoom", "", &settings::invertZoom)); -+ menu->addChild(new ui::MenuSeparator); +- menu->addChild(createBoolPtrMenuItem("Auto-squeeze algorithm (experimental)", "", &settings::squeezeModules)); ++ static const std::vector rateLimitLabels = { ++ "None", ++ "2x", ++ "4x", ++ }; ++ static const std::vector rateLimits = {0, 1, 2}; ++ menu->addChild(createSubmenuItem("Update rate limit", rateLimitLabels[settings::rateLimit], [=](ui::Menu* menu) { ++ for (int rateLimit : rateLimits) { ++ menu->addChild(createCheckMenuItem(rateLimitLabels[rateLimit], "", ++ [=]() {return settings::rateLimit == rateLimit;}, ++ [=]() {settings::rateLimit = rateLimit;} ++ )); ++ } ++ })); + } + }; + +@@ -487,47 +575,6 @@ + //////////////////// + -struct SampleRateItem : ui::MenuItem { - ui::Menu* createChildMenu() override { @@ -266,35 +361,18 @@ - menu->addChild(createCheckMenuItem(text, rightText, - [=]() {return settings::sampleRate == sampleRate;}, - [=]() {settings::sampleRate = sampleRate;} -+ static const std::vector rateLimitLabels = { -+ "None", -+ "2x", -+ "4x", -+ }; -+ static const std::vector rateLimits = {0, 1, 2}; -+ menu->addChild(createSubmenuItem("Update rate limit", rateLimitLabels[settings::rateLimit], [=](ui::Menu* menu) { -+ for (int rateLimit : rateLimits) { -+ menu->addChild(createCheckMenuItem(rateLimitLabels[rateLimit], "", -+ [=]() {return settings::rateLimit == rateLimit;}, -+ [=]() {settings::rateLimit = rateLimit;} - )); - } +- )); +- } - } - return menu; -+ })); - } - }; - - -+//////////////////// -+// Engine -+//////////////////// -+ -+ +- } +-}; +- +- struct EngineButton : MenuButton { void onAction(const ActionEvent& e) override { ui::Menu* menu = createMenu(); -@@ -529,269 +518,6 @@ +@@ -540,269 +587,6 @@ menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() { settings::cpuMeter ^= true; })); @@ -564,7 +642,7 @@ } }; -@@ -802,65 +528,23 @@ +@@ -813,65 +597,23 @@ struct HelpButton : MenuButton { @@ -582,13 +660,14 @@ - menu->addChild(createMenuItem("Tips", "", [=]() { - APP->scene->addChild(tipWindowCreate()); -- })); -- -- menu->addChild(createMenuItem("User manual", "F1", [=]() { + menu->addChild(createMenuItem("Rack User manual", "F1", [=]() { - system::openBrowser("https://vcvrack.com/manual"); ++ patchUtils::openBrowser("https://vcvrack.com/manual"); })); +- menu->addChild(createMenuItem("User manual", "F1", [=]() { +- system::openBrowser("https://vcvrack.com/manual"); +- })); +- - menu->addChild(createMenuItem("Support", "", [=]() { - system::openBrowser("https://vcvrack.com/support"); - })); @@ -596,7 +675,7 @@ - menu->addChild(createMenuItem("VCVRack.com", "", [=]() { - system::openBrowser("https://vcvrack.com/"); + menu->addChild(createMenuItem("Cardinal Project page", "", [=]() { -+ system::openBrowser("https://github.com/DISTRHO/Cardinal/"); ++ patchUtils::openBrowser("https://github.com/DISTRHO/Cardinal/"); })); menu->addChild(new ui::MenuSeparator); @@ -635,7 +714,7 @@ } }; -@@ -910,7 +594,9 @@ +@@ -921,7 +663,9 @@ struct MenuBar : widget::OpaqueWidget { MeterLabel* meterLabel; @@ -646,7 +725,7 @@ const float margin = 5; box.size.y = BND_WIDGET_HEIGHT + 2 * margin; -@@ -919,7 +605,7 @@ +@@ -930,7 +674,7 @@ layout->spacing = math::Vec(0, 0); addChild(layout); @@ -655,7 +734,7 @@ fileButton->text = "File"; layout->addChild(fileButton); -@@ -935,10 +621,6 @@ +@@ -946,10 +690,6 @@ engineButton->text = "Engine"; layout->addChild(engineButton); @@ -666,7 +745,7 @@ HelpButton* helpButton = new HelpButton; helpButton->text = "Help"; layout->addChild(helpButton); -@@ -973,7 +655,11 @@ +@@ -984,7 +724,11 @@ widget::Widget* createMenuBar() { diff --git a/src/override/diffs/Model.cpp.diff b/src/override/diffs/Model.cpp.diff index fa36753..69df973 100644 --- a/src/override/diffs/Model.cpp.diff +++ b/src/override/diffs/Model.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/plugin/Model.cpp 2021-10-17 13:57:23.257633662 +0100 -+++ Model.cpp 2022-04-27 18:17:16.790097058 +0100 +--- ../Rack/src/plugin/Model.cpp 2022-07-07 00:16:13.701492001 +0100 ++++ Model.cpp 2022-07-05 16:34:56.679860788 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin @@ -31,7 +31,17 @@ #include #include -@@ -17,7 +44,7 @@ +@@ -10,7 +37,8 @@ + #include + #include + #include +-#include ++ ++#include "../CardinalCommon.hpp" + + + namespace rack { +@@ -18,7 +46,7 @@ void Model::fromJson(json_t* rootJ) { @@ -40,7 +50,7 @@ json_t* nameJ = json_object_get(rootJ, "name"); if (nameJ) -@@ -54,11 +81,6 @@ +@@ -55,11 +83,6 @@ if (manualUrlJ) manualUrl = json_string_value(manualUrlJ); @@ -52,7 +62,7 @@ // hidden json_t* hiddenJ = json_object_get(rootJ, "hidden"); // Use `disabled` as an alias which was deprecated in Rack 2.0 -@@ -73,7 +95,7 @@ +@@ -74,7 +97,7 @@ std::string Model::getFullName() { @@ -61,7 +71,34 @@ return plugin->getBrand() + " " + name; } -@@ -132,18 +154,6 @@ +@@ -99,7 +122,7 @@ + void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) { + // plugin + menu->addChild(createMenuItem("Plugin: " + plugin->name, "", [=]() { +- system::openBrowser(plugin->pluginUrl); ++ patchUtils::openBrowser(plugin->pluginUrl); + }, plugin->pluginUrl == "")); + + // version +@@ -108,7 +131,7 @@ + // author + if (plugin->author != "") { + menu->addChild(createMenuItem("Author: " + plugin->author, "", [=]() { +- system::openBrowser(plugin->authorUrl); ++ patchUtils::openBrowser(plugin->authorUrl); + }, plugin->authorUrl.empty())); + } + +@@ -116,7 +139,7 @@ + std::string license = plugin->license; + if (string::startsWith(license, "https://") || string::startsWith(license, "http://")) { + menu->addChild(createMenuItem("License: Open in browser", "", [=]() { +- system::openBrowser(license); ++ patchUtils::openBrowser(license); + })); + } + else if (license != "") { +@@ -133,58 +156,32 @@ menu->addChild(new ui::MenuSeparator); @@ -80,17 +117,47 @@ // manual std::string manualUrl = getManualUrl(); if (manualUrl != "") { -@@ -173,13 +183,6 @@ + menu->addChild(createMenuItem("User manual", RACK_MOD_CTRL_NAME "+F1", [=]() { +- system::openBrowser(manualUrl); ++ patchUtils::openBrowser(manualUrl); })); } + // donate + if (plugin->donateUrl != "") { + menu->addChild(createMenuItem("Donate", "", [=]() { +- system::openBrowser(plugin->donateUrl); ++ patchUtils::openBrowser(plugin->donateUrl); + })); + } + + // source code + if (plugin->sourceUrl != "") { + menu->addChild(createMenuItem("Source code", "", [=]() { +- system::openBrowser(plugin->sourceUrl); ++ patchUtils::openBrowser(plugin->sourceUrl); + })); + } + + // changelog + if (plugin->changelogUrl != "") { + menu->addChild(createMenuItem("Changelog", "", [=]() { +- system::openBrowser(plugin->changelogUrl); +- })); +- } +- +- // author email +- if (plugin->authorEmail != "") { +- menu->addChild(createMenuItem("Author email", "Copy to clipboard", [=]() { +- glfwSetClipboardString(APP->window->win, plugin->authorEmail.c_str()); +- })); +- } +- - // plugin folder - if (plugin->path != "") { - menu->addChild(createMenuItem("Open plugin folder", "", [=]() { - system::openDirectory(plugin->path); -- })); -- } -- - // Favorite - std::string favoriteRightText = inBrowser ? (RACK_MOD_CTRL_NAME "+click") : ""; - if (isFavorite()) ++ patchUtils::openBrowser(plugin->changelogUrl); + })); + } + diff --git a/src/override/diffs/Scene.cpp.diff b/src/override/diffs/Scene.cpp.diff index cb11e92..e3591d4 100644 --- a/src/override/diffs/Scene.cpp.diff +++ b/src/override/diffs/Scene.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/app/Scene.cpp 2022-02-26 23:08:06.701192797 +0000 -+++ Scene.cpp 2022-04-02 03:13:14.856813800 +0100 +--- ../Rack/src/app/Scene.cpp 2022-06-04 19:14:19.947414815 +0100 ++++ Scene.cpp 2022-07-06 09:36:54.421492710 +0100 @@ -1,3 +1,30 @@ +/* + * DISTRHO Cardinal Plugin @@ -112,11 +112,11 @@ + } + + void onEnter(const EnterEvent& e) override { -+ glfwSetCursor(nullptr, (GLFWcursor*)0x1); ++ glfwSetCursor(APP->window->win, glfwCreateStandardCursor(GLFW_RESIZE_NWSE_CURSOR)); + } + + void onLeave(const LeaveEvent& e) override { -+ glfwSetCursor(nullptr, nullptr); ++ glfwSetCursor(APP->window->win, nullptr); } - void onDragStart(const DragStartEvent& e) override { @@ -242,7 +242,7 @@ e.consume(this); } if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { -@@ -180,19 +292,20 @@ +@@ -180,19 +292,22 @@ e.consume(this); } if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { @@ -255,19 +255,21 @@ + patchUtils::revertDialog(); e.consume(this); } ++#ifndef DISTRHO_OS_WASM if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { - APP->patch->saveDialog(); + // NOTE: will do nothing if path is empty, intentionally + patchUtils::saveDialog(APP->patch->path); e.consume(this); } ++#endif if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) { - APP->patch->saveAsDialog(); + patchUtils::saveAsDialog(); e.consume(this); } if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { -@@ -220,10 +333,14 @@ +@@ -220,22 +335,29 @@ APP->scene->rackScroll->setZoom(std::pow(2.f, zoom)); e.consume(this); } @@ -281,9 +283,11 @@ + e.consume(this); + } if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) { - system::openBrowser("https://vcvrack.com/manual/"); +- system::openBrowser("https://vcvrack.com/manual/"); ++ patchUtils::openBrowser("https://vcvrack.com/manual/"); e.consume(this); -@@ -232,10 +349,13 @@ + } + if (e.key == GLFW_KEY_F3 && (e.mods & RACK_MOD_MASK) == 0) { settings::cpuMeter ^= true; e.consume(this); } @@ -301,7 +305,7 @@ e.consume(this); } -@@ -326,13 +446,6 @@ +@@ -326,13 +448,6 @@ // Key commands that can be overridden by children if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { @@ -315,7 +319,7 @@ if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { rack->pasteClipboardAction(); e.consume(this); -@@ -351,7 +464,7 @@ +@@ -351,7 +466,7 @@ std::string extension = system::getExtension(path); if (extension == ".vcv") { @@ -324,7 +328,7 @@ e.consume(this); return; } -@@ -368,3 +481,94 @@ +@@ -368,3 +483,94 @@ } // namespace app } // namespace rack diff --git a/src/override/diffs/Window.cpp.diff b/src/override/diffs/Window.cpp.diff index 72bab0a..c6a8b19 100644 --- a/src/override/diffs/Window.cpp.diff +++ b/src/override/diffs/Window.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/window/Window.cpp 2022-02-09 15:35:19.238863170 +0000 -+++ Window.cpp 2022-05-15 12:05:26.430956655 +0100 +--- ../Rack/src/window/Window.cpp 2022-06-04 19:14:19.951414839 +0100 ++++ Window.cpp 2022-07-08 12:18:51.634824005 +0100 @@ -1,33 +1,83 @@ +/* + * DISTRHO Cardinal Plugin @@ -108,7 +108,7 @@ throw Exception("Failed to load font %s", filename.c_str()); } INFO("Loaded font %s", filename.c_str()); -@@ -79,375 +128,308 @@ +@@ -79,375 +128,317 @@ } @@ -148,7 +148,9 @@ - int frameSwapInterval = -1; - double monitorRefreshRate = 0.0; + int frameSwapInterval = 1; ++#ifndef DGL_USE_GLES + int generateScreenshotStep = kScreenshotStepNone; ++#endif + double monitorRefreshRate = 60.0; double frameTime = 0.0; double lastFrameDuration = 0.0; @@ -200,14 +202,18 @@ + return nvgCreateFontMem(vg, NANOVG_DEJAVU_SANS_TTF, + (uchar*)dejavusans_ttf, dejavusans_ttf_size, 0); } -- -- ++#endif + + -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); + -static void mouseButtonCallback(GLFWwindow* win, int button, int action, int mods) { - contextSet((Context*) glfwGetWindowUserPointer(win)); -#if defined ARCH_MAC @@ -221,28 +227,6 @@ - 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(); -- } -+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); - -- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); -- (void) cursorMode; + // Set up NanoVG + const int nvgFlags = NVG_ANTIALIAS; + vg = nvgCreateGL(nvgFlags); @@ -251,19 +235,10 @@ + fbVg = nvgCreateSharedGLES2(vg, nvgFlags); +#else + fbVg = nvgCreateSharedGL2(vg, nvgFlags); -+#endif + #endif --#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); +- APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods); +-} + // Load default Blendish font +#ifndef DGL_NO_SHARED_RESOURCES + uiFont = std::make_shared(); @@ -278,14 +253,16 @@ + internal->fontCache[uiFont2->ofilename] = uiFont2; +#else + uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); - #endif ++#endif -- APP->window->internal->lastMousePos = mousePos; + if (uiFont != nullptr) + bndSetFont(uiFont->handle); +} -- APP->event->handleHover(mousePos, mouseDelta); +-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); +void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui) +{ + if (ui != nullptr) @@ -307,12 +284,11 @@ + window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS); +#endif -- // Keyboard/mouse MIDI driver -- int width, height; -- glfwGetWindowSize(win, &width, &height); -- math::Vec scaledPos(xpos / width, ypos / height); -- keyboard::mouseMove(scaledPos); --} +- // 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(); +- } + // swap contexts + window->internal->o_vg = window->vg; + window->internal->o_fbVg = window->fbVg; @@ -337,22 +313,40 @@ + NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); + } +- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); +- (void) cursorMode; + // Init settings + WindowParametersRestore(window); --static void cursorEnterCallback(GLFWwindow* win, int entered) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- if (!entered) { -- APP->event->handleLeave(); +-#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; + widget::Widget::ContextCreateEvent e; + APP->scene->onContextCreate(e); } --} +- // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window +- glfwSetCursor(win, NULL); +-#endif +- +- APP->window->internal->lastMousePos = mousePos; +- +- APP->event->handleHover(mousePos, mouseDelta); + else + { + widget::Widget::ContextDestroyEvent e; + APP->scene->onContextDestroy(e); +- // Keyboard/mouse MIDI driver +- int width, height; +- glfwGetWindowSize(win, &width, &height); +- math::Vec scaledPos(xpos / width, ypos / height); +- keyboard::mouseMove(scaledPos); +-} + // swap contexts + window->uiFont->vg = window->internal->o_vg; + window->vg = window->internal->o_vg; @@ -376,46 +370,31 @@ + image.second->ohandle = -1; + } ++#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); -+#if defined NANOVG_GLES2 -+ nvgDeleteGLES2(window->internal->r_fbVg); - #else -- scrollDelta = scrollDelta.mult(50.0); -+ nvgDeleteGL2(window->internal->r_fbVg); - #endif - -- APP->event->handleScroll(APP->window->internal->lastMousePos, scrollDelta); -+ window->internal->ui = nullptr; -+ window->internal->callback = nullptr; -+ } - } - -- --static void charCallback(GLFWwindow* win, unsigned int codepoint) { -- contextSet((Context*) glfwGetWindowUserPointer(win)); -- if (APP->event->handleText(APP->window->internal->lastMousePos, codepoint)) -- return; -+void WindowSetMods(Window* const window, const int mods) -+{ -+ window->internal->mods = mods; - } - -- --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; -- -- // Keyboard/mouse MIDI driver -- if (action == GLFW_PRESS && (mods & RACK_MOD_MASK) == 0) { -- keyboard::press(key); -- } -- if (action == GLFW_RELEASE) { -- keyboard::release(key); +Window::~Window() { + { + DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow); @@ -429,14 +408,47 @@ +#if defined NANOVG_GLES2 + nvgDeleteGLES2(internal->o_fbVg != nullptr ? internal->o_fbVg : fbVg); + nvgDeleteGLES2(internal->o_vg != nullptr ? internal->o_vg : vg); -+#else + #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 - } --} -- + #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; + +- // Keyboard/mouse MIDI driver +- if (action == GLFW_PRESS && (mods & RACK_MOD_MASK) == 0) { +- keyboard::press(key); +- } +- if (action == GLFW_RELEASE) { +- keyboard::release(key); +- } ++ if (DISTRHO_NAMESPACE::UI* const ui = internal->ui) ++ ui->setSize(internal->size.x, internal->size.y); + } + +- -static void dropCallback(GLFWwindow* win, int count, const char** paths) { - contextSet((Context*) glfwGetWindowUserPointer(win)); - std::vector pathsVec; @@ -444,14 +456,16 @@ - pathsVec.push_back(paths[i]); - } - APP->event->handleDrop(APP->window->internal->lastMousePos, pathsVec); -+ delete internal; ++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); -+math::Vec Window::getSize() { -+ return internal->size; ++void Window::run() { ++ internal->frame = 0; } @@ -542,10 +556,7 @@ - - // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. - glGetError(); -+void Window::setSize(math::Vec size) { -+ size = size.max(WINDOW_SIZE_MIN); -+ internal->size = size; - +- - // Set up NanoVG - int nvgFlags = NVG_ANTIALIAS; -#if defined NANOVG_GL2 @@ -560,27 +571,15 @@ - 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"); - } -+ if (DISTRHO_NAMESPACE::UI* const ui = internal->ui) -+ ui->setSize(internal->size.x, internal->size.y); -+} - +- - // Load default Blendish font - uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); - bndSetFont(uiFont->handle); - +- - if (APP->scene) { - widget::Widget::ContextCreateEvent e; - APP->scene->onContextCreate(e); -- } -+void Window::run() { -+ internal->frame = 0; - } - - --Window::~Window() { -- if (APP->scene) { -- widget::Widget::ContextDestroyEvent e; -- APP->scene->onContextDestroy(e); ++#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++) { + const int flipY = height - y - 1; @@ -589,33 +588,13 @@ + std::memmove(&pixels[y * width * depth], &pixels[flipY * width * depth], width * depth); + std::memcpy(&pixels[flipY * width * depth], tmp, width * depth); } -- -- // 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); --} -- +-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; @@ -642,15 +621,42 @@ + const int xs = static_cast(x * scale); + std::memmove(pixels + (width * y + x) * 3, pixels + (width * ys + xs) * 3, 3); + } -+ } + } --void Window::setSize(math::Vec size) { -- size = size.max(WINDOW_SIZE_MIN); -- glfwSetWindowSize(win, size.x, size.y); +- // 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; + width = targetWidth; + height = targetHeight; } +- +-math::Vec Window::getSize() { +- int width, height; +- glfwGetWindowSize(win, &width, &height); +- return math::Vec(width, height); +-} +- +- +-void Window::setSize(math::Vec size) { +- size = size.max(WINDOW_SIZE_MIN); +- glfwSetWindowSize(win, size.x, size.y); +-} +- - -void Window::run() { - internal->frame = 0; @@ -663,6 +669,7 @@ + ui->setState("screenshot", String::asBase64(data, size).buffer()); } +#endif ++#endif void Window::step() { @@ -710,7 +717,7 @@ if (APP->patch->path != "") { windowTitle += " - "; if (!APP->history->isSaved()) -@@ -455,243 +437,155 @@ +@@ -455,243 +446,159 @@ windowTitle += system::getFilename(APP->patch->path); } if (windowTitle != internal->lastWindowTitle) { @@ -734,6 +741,7 @@ APP->event->handleDirty(); } ++#ifndef DGL_USE_GLES + // Hide menu and background if generating screenshot + if (internal->generateScreenshotStep == kScreenshotStepStarted) { +#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS @@ -743,6 +751,7 @@ + internal->generateScreenshotStep = kScreenshotStepSecondPass; +#endif + } ++#endif + // Get framebuffer/window ratio - int fbWidth, fbHeight; @@ -815,9 +824,10 @@ - // ); - internal->frame++; -} ++#ifndef DGL_USE_GLES + if (internal->generateScreenshotStep != kScreenshotStepNone) { + ++internal->generateScreenshotStep; - ++ + int y = 0; +#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS + constexpr const int depth = 4; @@ -826,23 +836,16 @@ + constexpr const int depth = 3; +#endif --void Window::activateContext() { -- glfwMakeContextCurrent(win); --} + // Allocate pixel color buffer + uint8_t* const pixels = new uint8_t[winHeight * winWidth * 4]; +-void Window::activateContext() { +- glfwMakeContextCurrent(win); +-} + // 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); --static void flipBitmap(uint8_t* pixels, int width, int height, int depth) { -- for (int y = 0; y < height / 2; y++) { -- int flipY = height - y - 1; -- uint8_t tmp[width * depth]; -- 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); + if (internal->generateScreenshotStep == kScreenshotStepSaving) + { + // Write pixels to PNG @@ -857,7 +860,14 @@ +#else + stbi_write_png("screenshot.png", winWidth, winHeight, depth, pixelsWithOffset, stride); +#endif -+ + +-static void flipBitmap(uint8_t* pixels, int width, int height, int depth) { +- for (int y = 0; y < height / 2; y++) { +- int flipY = height - y - 1; +- uint8_t tmp[width * depth]; +- 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); + internal->generateScreenshotStep = kScreenshotStepNone; + APP->scene->menuBar->show(); + APP->scene->rack->children.front()->show(); @@ -865,6 +875,11 @@ + + delete[] pixels; } ++#endif ++} ++ ++ ++void Window::activateContext() { } @@ -933,7 +948,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 @@ -946,10 +961,6 @@ - delete fbw; - } - } -+void Window::screenshot(const std::string&) { -+} -+ -+ +void Window::screenshotModules(const std::string&, float) { } @@ -1023,7 +1034,7 @@ bool Window::isFullScreen() { - GLFWmonitor* monitor = glfwGetWindowMonitor(win); - return monitor != NULL; -+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS ++#if defined(CARDINAL_TRANSPARENT_SCREENSHOTS) && !defined(DGL_USE_GLES) + return internal->generateScreenshotStep != kScreenshotStepNone; +#else + return false; @@ -1031,7 +1042,7 @@ } -@@ -722,14 +616,15 @@ +@@ -722,14 +629,15 @@ return pair->second; // Load font @@ -1050,7 +1061,7 @@ } internal->fontCache[filename] = font; return font; -@@ -742,14 +637,15 @@ +@@ -742,14 +650,15 @@ return pair->second; // Load image @@ -1069,21 +1080,22 @@ } internal->imageCache[filename] = image; return image; -@@ -766,28 +662,146 @@ +@@ -766,28 +675,156 @@ } -void init() { - int err; -+void generateScreenshot() { -+ APP->window->internal->generateScreenshotStep = kScreenshotStepStarted; -+} - +- - // Set up GLFW -#if defined ARCH_MAC - glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_TRUE); - glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE); --#endif ++void generateScreenshot() { ++#ifndef DGL_USE_GLES ++ APP->window->internal->generateScreenshotStep = kScreenshotStepStarted; + #endif ++} - glfwSetErrorCallback(errorCallback); - err = glfwInit(); @@ -1091,6 +1103,7 @@ - osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLFW."); - throw Exception("Could not initialize GLFW"); - } ++ +void init() { } @@ -1185,6 +1198,13 @@ + window->internal->callback->WindowParametersChanged(kWindowParameterLockModulePositions, + rack::settings::lockModules); + } ++ if (window->internal->params.squeezeModules != rack::settings::squeezeModules) ++ { ++ window->internal->params.squeezeModules = rack::settings::squeezeModules; ++ if (window->internal->callback != nullptr) ++ window->internal->callback->WindowParametersChanged(kWindowParameterSqueezeModulePositions, ++ rack::settings::squeezeModules); ++ } + if (window->internal->params.invertZoom != rack::settings::invertZoom) + { + window->internal->params.invertZoom = rack::settings::invertZoom; @@ -1214,6 +1234,7 @@ + rack::settings::tooltips = window->internal->params.tooltips; + rack::settings::knobScroll = window->internal->params.knobScroll; + rack::settings::lockModules = window->internal->params.lockModules; ++ rack::settings::squeezeModules = window->internal->params.squeezeModules; + rack::settings::invertZoom = window->internal->params.invertZoom; + rack::settings::rateLimit = window->internal->params.rateLimit; +} diff --git a/src/override/diffs/blendish.c.diff b/src/override/diffs/blendish.c.diff index 79696cd..feb7536 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 2021-10-17 13:57:24.613620711 +0100 -+++ blendish.c 2021-12-13 09:36:22.182673256 +0000 +--- ../Rack/dep/oui-blendish/blendish.c 2022-06-04 19:14:37.919525628 +0100 ++++ blendish.c 2022-06-04 19:10:13.504951454 +0100 @@ -61,7 +61,7 @@ } diff --git a/src/override/diffs/common.cpp.diff b/src/override/diffs/common.cpp.diff index 6ceca14..6f8995d 100644 --- a/src/override/diffs/common.cpp.diff +++ b/src/override/diffs/common.cpp.diff @@ -1,6 +1,6 @@ ---- ../Rack/src/common.cpp 2021-11-23 19:57:23.719015894 +0000 -+++ common.cpp 2022-05-21 22:13:36.682680714 +0100 -@@ -1,6 +1,38 @@ +--- ../Rack/src/common.cpp 2022-06-04 19:14:19.947414815 +0100 ++++ common.cpp 2022-07-07 00:16:54.680919544 +0100 +@@ -1,11 +1,45 @@ +/* + * DISTRHO Cardinal Plugin + * Copyright (C) 2021-2022 Filipe Coelho @@ -39,7 +39,14 @@ #if defined ARCH_WIN #include -@@ -14,20 +46,21 @@ + + FILE* fopen_u8(const char* filename, const char* mode) { ++ 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()); + } + +@@ -14,20 +48,21 @@ namespace rack { @@ -52,7 +59,7 @@ +const std::string APP_EDITION_NAME = "Audio Plugin"; const std::string APP_VERSION_MAJOR = "2"; -const std::string APP_VERSION = TOSTRING(_APP_VERSION); -+const std::string APP_VERSION = "2.1.1"; ++const std::string APP_VERSION = "2.1.2"; #if defined ARCH_WIN const std::string APP_OS = "win"; -#elif ARCH_MAC diff --git a/src/override/diffs/context.cpp.diff b/src/override/diffs/context.cpp.diff index 72729b9..52f3e6e 100644 --- a/src/override/diffs/context.cpp.diff +++ b/src/override/diffs/context.cpp.diff @@ -1,5 +1,5 @@ ---- ../Rack/src/context.cpp 2022-02-05 22:30:09.253393116 +0000 -+++ context.cpp 2022-01-23 17:13:11.652514338 +0000 +--- ../Rack/src/context.cpp 2022-06-04 19:14:19.947414815 +0100 ++++ context.cpp 2022-06-04 19:10:13.504951454 +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 bbf3a71..82b395a 100644 --- a/src/override/diffs/plugin.cpp.diff +++ b/src/override/diffs/plugin.cpp.diff @@ -1,6 +1,6 @@ ---- ../Rack/src/plugin.cpp 2022-05-21 22:03:14.887288742 +0100 -+++ plugin.cpp 2022-05-21 22:14:18.180931534 +0100 -@@ -1,336 +1,41 @@ +--- ../Rack/src/plugin.cpp 2022-07-07 00:16:13.701492001 +0100 ++++ plugin.cpp 2022-06-04 19:10:13.508951513 +0100 +@@ -1,342 +1,41 @@ -#include -#include -#include @@ -287,6 +287,10 @@ - // Get user plugins directory - system::createDirectory(pluginsPath); - +- // Don't load plugins if safe mode is enabled +- if (settings::safeMode) +- return; +- - // Extract packages and load plugins - extractPackages(pluginsPath); - loadPlugins(pluginsPath); @@ -342,11 +346,13 @@ - - -void destroy() { -- for (Plugin* plugin : plugins) { +- while (!plugins.empty()) { +- Plugin* plugin = plugins.back(); - INFO("Destroying plugin %s", plugin->name.c_str()); - destroyPlugin(plugin); +- plugins.pop_back(); - } -- plugins.clear(); +- assert(plugins.empty()); -} - - @@ -366,7 +372,7 @@ /** Given slug => fallback slug. -@@ -383,8 +88,19 @@ +@@ -389,8 +88,19 @@ */ using PluginModuleSlug = std::tuple; static const std::map moduleSlugFallbacks = { @@ -387,7 +393,7 @@ // {{"", ""}, {"", ""}}, }; -@@ -472,7 +188,6 @@ +@@ -478,7 +188,6 @@ }