Browse Source

Cleanup

tags/22.02
falkTX 3 years ago
parent
commit
06261deb87
11 changed files with 404 additions and 1928 deletions
  1. +21
    -15
      docs/OVERVIEW.md
  2. +0
    -1693
      patches/Celebration.vcv
  3. +2
    -2
      src/override/diffs/Engine.cpp.diff
  4. +14
    -10
      src/override/diffs/MenuBar.cpp.diff
  5. +2
    -2
      src/override/diffs/Model.cpp.diff
  6. +43
    -36
      src/override/diffs/Scene.cpp.diff
  7. +314
    -162
      src/override/diffs/Window.cpp.diff
  8. +2
    -2
      src/override/diffs/blendish.c.diff
  9. +2
    -2
      src/override/diffs/common.cpp.diff
  10. +2
    -2
      src/override/diffs/context.cpp.diff
  11. +2
    -2
      src/override/diffs/plugin.cpp.diff

+ 21
- 15
docs/OVERVIEW.md View File

@@ -7,7 +7,7 @@ On the root folder the following directories can be seen;

* [carla](#carla)
* [deps](#deps)
* [doc](#doc)
* [docs](#docs)
* [dpf](#dpf)
* [include](#include)
* [lv2export](#lv2export)
@@ -26,10 +26,10 @@ Being GPLv2+ the code license is compatible with Cardinal's GPLv3+.
## deps

3rd-party libraries build setup.
No Cardinal specific code is hosted here, only external submodules and a Makefile with steps for fetching extra source code and build it.
No Cardinal specific code is hosted here, only external submodules and a Makefile with steps for fetching extra source code and build it.
The Makefile overrides Rack's `dep.mk` things for a proper static build, and supporting more platforms.

## doc
## docs

Here you find several files (like this one you are reading now) describing the Cardinal project.
It is intentionally not using something like GitHub Wiki so that rehosting does not lose any information.
@@ -57,6 +57,8 @@ Only quick&dirty hacks so far, nothing interesting to see here yet.
Public domain or CC0 licensed Rack patches, suitable for use in Cardinal.
Must be stored as plain text files (not zstd compressed) so they play nicely with git.

Note: There are no such patches at the moment, but this is where will they be once available.

## plugins

Module/Plugin related code and build setup.
@@ -76,15 +78,20 @@ Everything is a symlink except `DistrhoPluginInfo.h` (setting plugin info) and `

The source code is the same for all the variants, with compiler macros used to tweak behaviour and IO count.

### custom

Here are files that are originally from Rack but fully reimplemented in Cardinal.
Some of them are just stubs to define function symbols but without an actual implementation, for example disabling network features.

### extra

A few extra files for having access to a few utilities, code borrowed from Carla, which in turn borrowed it from JUCE.
The important one is `SharedResourcePointer`, as a way to easily manage a shared class lifecycle.

### custom
### MOD

Here are files that are originally from Rack but fully reimplemented in Cardinal.
Some of them are just stubs to define function symbols but without an actual implementation, for example disabling network features.
Here are files related to packaging for [MOD Devices](https://moddevices.com/).
These are not used for regular/common builds, only for MOD, where we add a few extra properties to make Cardinal LV2 integrate better with their system.

### override

@@ -99,6 +106,14 @@ A git submodule reference to the official Rack source code repository.

Custom Cardinal code for showing a dialog in async fashion, optionally with a callback for when the user clicks "Ok".

### CardinalCommon.{cpp,hpp}

Common Cardinal code used by a few different files.

### CardinalModuleWidget.cpp

Some more common code and a custom `ModuleWidget::onButton` implementation.

### CardinalPlugin.cpp

The DSP/plugin side of the plugin, and also where the global/shared class lifecycle is managed.
@@ -123,15 +138,6 @@ This same file is used by all variants, changing behaviour based on the plugin v
And handy but perhaps somewhat hacky `rack::Context` class extension, so internal modules can have direct access to DAW provided data.
This also extends the base `Plugin` and `UI` classes from DPF, to provide methods needed for Rack Audio/MIDI drivers.

### PluginDriver.hpp

Code that glues Rack Audio/MIDI drivers to the DPF side of things.

### ResizeHandle.hpp

A DPF-related Widget that does what you think it does.
Handles all the resizing for us.

### template.vcv

The default template patch as used by Cardinal


+ 0
- 1693
patches/Celebration.vcv
File diff suppressed because it is too large
View File


+ 2
- 2
src/override/diffs/Engine.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/engine/Engine.cpp 2022-02-05 22:30:09.253393116 +0000
+++ Engine.cpp 2022-02-08 18:03:08.304201743 +0000
--- ../Rack/src/engine/Engine.cpp 2022-01-15 11:59:46.188414546 +0000
+++ Engine.cpp 2022-02-09 02:13:37.829435608 +0000
@@ -1,3 +1,30 @@
+/*
+ * DISTRHO Cardinal Plugin


+ 14
- 10
src/override/diffs/MenuBar.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/app/MenuBar.cpp 2022-02-05 22:30:09.233392896 +0000
+++ MenuBar.cpp 2022-02-05 18:08:00.272028714 +0000
--- ../Rack/src/app/MenuBar.cpp 2022-01-15 11:59:46.188414546 +0000
+++ MenuBar.cpp 2022-02-14 03:38:00.935519007 +0000
@@ -1,8 +1,33 @@
+/*
+ * DISTRHO Cardinal Plugin
@@ -218,11 +218,14 @@
static const std::vector<std::string> knobModeLabels = {
"Linear",
@@ -467,6 +478,21 @@
@@ -467,6 +478,25 @@
menu->addChild(knobScrollSensitivitySlider);
menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules));
+
+#ifndef DISTRHO_OS_MAC
+ menu->addChild(new ui::MenuSeparator);
+
+ static const std::vector<std::string> rateLimitLabels = {
+ "None",
+ "2x",
@@ -237,10 +240,11 @@
+ ));
+ }
+ }));
+#endif
}
};
@@ -476,47 +502,6 @@
@@ -476,47 +506,6 @@
////////////////////
@@ -288,7 +292,7 @@
struct EngineButton : MenuButton {
void onAction(const ActionEvent& e) override {
ui::Menu* menu = createMenu();
@@ -529,269 +514,6 @@
@@ -529,269 +518,6 @@
menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() {
settings::cpuMeter ^= true;
}));
@@ -558,7 +562,7 @@
}
};
@@ -802,63 +524,23 @@
@@ -802,63 +528,23 @@
struct HelpButton : MenuButton {
@@ -627,7 +631,7 @@
}
};
@@ -908,7 +590,9 @@
@@ -908,7 +594,9 @@
struct MenuBar : widget::OpaqueWidget {
MeterLabel* meterLabel;
@@ -638,7 +642,7 @@
const float margin = 5;
box.size.y = BND_WIDGET_HEIGHT + 2 * margin;
@@ -917,7 +601,7 @@
@@ -917,7 +605,7 @@
layout->spacing = math::Vec(0, 0);
addChild(layout);
@@ -647,7 +651,7 @@
fileButton->text = "File";
layout->addChild(fileButton);
@@ -933,10 +617,6 @@
@@ -933,10 +621,6 @@
engineButton->text = "Engine";
layout->addChild(engineButton);
@@ -658,7 +662,7 @@
HelpButton* helpButton = new HelpButton;
helpButton->text = "Help";
layout->addChild(helpButton);
@@ -971,7 +651,11 @@
@@ -971,7 +655,11 @@
widget::Widget* createMenuBar() {


+ 2
- 2
src/override/diffs/Model.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/plugin/Model.cpp 2021-10-17 13:57:23.257633662 +0100
+++ Model.cpp 2022-01-23 17:13:22.080013846 +0000
--- ../Rack/src/plugin/Model.cpp 2021-10-20 03:28:14.516922788 +0100
+++ Model.cpp 2022-01-24 00:11:36.628498885 +0000
@@ -1,3 +1,30 @@
+/*
+ * DISTRHO Cardinal Plugin


+ 43
- 36
src/override/diffs/Scene.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/app/Scene.cpp 2021-12-14 21:35:44.414568198 +0000
+++ Scene.cpp 2022-02-06 14:11:59.259830276 +0000
--- ../Rack/src/app/Scene.cpp 2021-12-04 09:46:43.912932319 +0000
+++ Scene.cpp 2022-02-11 05:30:49.567801073 +0000
@@ -1,3 +1,30 @@
+/*
+ * DISTRHO Cardinal Plugin
@@ -39,7 +39,7 @@
#include <system.hpp>
#include <network.hpp>
#include <history.hpp>
@@ -14,6 +42,17 @@
@@ -14,6 +42,18 @@
#include <patch.hpp>
#include <asset.hpp>
@@ -52,12 +52,13 @@
+#endif
+
+#include "../CardinalCommon.hpp"
+#include "extra/Base64.hpp"
+#include "DistrhoUtils.hpp"
+
namespace rack {
namespace app {
@@ -23,16 +62,55 @@
@@ -23,16 +63,55 @@
math::Vec size;
void draw(const DrawArgs& args) override {
@@ -108,18 +109,18 @@
+
+ void onEnter(const EnterEvent& e) override {
+ glfwSetCursor(nullptr, (GLFWcursor*)0x1);
+ }
+
+ void onLeave(const LeaveEvent& e) override {
+ glfwSetCursor(nullptr, nullptr);
}
- void onDragStart(const DragStartEvent& e) override {
+ void onLeave(const LeaveEvent& e) override {
+ glfwSetCursor(nullptr, nullptr);
+ }
+
+ void onDragStart(const DragStartEvent&) override {
size = APP->window->getSize();
}
@@ -46,9 +124,32 @@
@@ -46,9 +125,32 @@
struct Scene::Internal {
ResizeHandle* resizeHandle;
@@ -154,7 +155,7 @@
};
@@ -67,13 +168,8 @@
@@ -67,13 +169,8 @@
browser->hide();
addChild(browser);
@@ -169,25 +170,8 @@
addChild(internal->resizeHandle);
}
@@ -89,32 +185,13 @@
void Scene::step() {
- if (APP->window->isFullScreen()) {
- // Expand RackScrollWidget to cover entire screen if fullscreen
- rackScroll->box.pos.y = 0;
- }
- else {
- // Always show MenuBar if not fullscreen
- menuBar->show();
- rackScroll->box.pos.y = menuBar->box.size.y;
- }
-
internal->resizeHandle->box.pos = box.size.minus(internal->resizeHandle->box.size);
// Resize owned descendants
@@ -105,16 +202,6 @@
menuBar->box.size.x = box.size.x;
+ rackScroll->box.pos.y = menuBar->box.size.y;
rackScroll->box.size = box.size.minus(rackScroll->box.pos);
- // Autosave periodically
@@ -203,7 +187,7 @@
// Scroll RackScrollWidget with arrow keys
math::Vec arrowDelta;
if (internal->heldArrowKeys[0]) {
@@ -143,6 +220,22 @@
@@ -143,6 +230,23 @@
rackScroll->offset += arrowDelta * arrowSpeed;
}
@@ -218,6 +202,7 @@
+ internal->historyActionIndex = actionIndex;
+ internal->lastSceneChangeTime = time;
+ patchUtils::deployToRemote();
+ window::generateScreenshot();
+ }
+ }
+ }
@@ -226,7 +211,7 @@
Widget::step();
}
@@ -172,7 +265,7 @@
@@ -172,7 +276,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) {
@@ -235,7 +220,7 @@
e.consume(this);
}
if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -180,19 +273,20 @@
@@ -180,19 +284,20 @@
e.consume(this);
}
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -260,7 +245,7 @@
e.consume(this);
}
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -220,10 +314,14 @@
@@ -220,10 +325,14 @@
APP->scene->rackScroll->setZoom(std::pow(2.f, zoom));
e.consume(this);
}
@@ -276,7 +261,7 @@
if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) {
system::openBrowser("https://vcvrack.com/manual/");
e.consume(this);
@@ -232,10 +330,8 @@
@@ -232,10 +341,13 @@
settings::cpuMeter ^= true;
e.consume(this);
}
@@ -286,10 +271,15 @@
- // menuBar->hide();
+ if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) {
+ patchUtils::deployToRemote();
+ window::generateScreenshot();
+ e.consume(this);
+ }
+ if (e.key == GLFW_KEY_F9 && (e.mods & RACK_MOD_MASK) == 0) {
+ window::generateScreenshot();
e.consume(this);
}
@@ -326,13 +422,6 @@
@@ -326,13 +438,6 @@
// Key commands that can be overridden by children
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
@@ -303,7 +293,7 @@
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
rack->pasteClipboardAction();
e.consume(this);
@@ -351,7 +440,7 @@
@@ -351,7 +456,7 @@
std::string extension = system::getExtension(path);
if (extension == ".vcv") {
@@ -312,7 +302,7 @@
e.consume(this);
return;
}
@@ -368,3 +457,77 @@
@@ -368,3 +473,94 @@
} // namespace app
} // namespace rack
@@ -389,4 +379,21 @@
+}
+
+
+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<uint8_t> 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

+ 314
- 162
src/override/diffs/Window.cpp.diff View File

@@ -1,6 +1,6 @@
--- ../Rack/src/window/Window.cpp 2022-01-05 19:24:25.995101080 +0000
+++ Window.cpp 2022-02-08 03:46:08.216824790 +0000
@@ -1,33 +1,73 @@
--- ../Rack/src/window/Window.cpp 2022-01-01 15:50:17.777305924 +0000
+++ Window.cpp 2022-02-13 02:07:46.554983286 +0000
@@ -1,33 +1,83 @@
+/*
+ * DISTRHO Cardinal Plugin
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
@@ -49,15 +49,27 @@
#include <context.hpp>
#include <patch.hpp>
#include <settings.hpp>
#include <plugin.hpp> // used in Window::screenshot
#include <system.hpp> // used in Window::screenshot
-#include <plugin.hpp> // used in Window::screenshot
-#include <system.hpp> // used in Window::screenshot
+#include <system.hpp>
+
+#ifdef NDEBUG
+# undef DEBUG
+#endif
+
+// 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"
+
+#include "DistrhoUI.hpp"
+#include "Application.hpp"
+#include "extra/String.hpp"
+#include "../CardinalCommon.hpp"
+#include "../WindowParameters.hpp"
+
@@ -85,7 +97,30 @@
Font::~Font() {
@@ -82,372 +122,244 @@
@@ -42,9 +92,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.
- handle = nvgCreateFontMem(vg, name.c_str(), data, size, 0);
+ handle = nvgCreateFontMem(vg, name.c_str(), data, size, 1);
if (handle < 0) {
- std::free(data);
throw Exception("Failed to load font %s", filename.c_str());
}
INFO("Loaded font %s", filename.c_str());
@@ -79,375 +128,308 @@
}
+enum ScreenshotStep {
+ kScreenshotStepNone,
+ kScreenshotStepStarted,
+ kScreenshotStepFirstPass,
+ kScreenshotStepSecondPass,
+ kScreenshotStepSaving
+};
+
+
struct Window::Internal {
std::string lastWindowTitle;
@@ -113,6 +148,7 @@
- int frameSwapInterval = -1;
- double monitorRefreshRate = 0.0;
+ int frameSwapInterval = 1;
+ int generateScreenshotStep = kScreenshotStepNone;
+ double monitorRefreshRate = 60.0;
double frameTime = 0.0;
double lastFrameDuration = 0.0;
@@ -189,24 +225,33 @@
- APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods);
-}
-
-
+Window::Window() {
+ internal = new Internal;
-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);
-
- // 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();
- }
+Window::Window() {
+ internal = new Internal;
+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow);
- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR);
- (void) cursorMode;
+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow);
+ // Set up NanoVG
+ const int nvgFlags = NVG_ANTIALIAS;
+ vg = nvgCreateGL(nvgFlags);
+ DISTRHO_SAFE_ASSERT_RETURN(vg != nullptr,);
+#ifdef NANOVG_GLES2
+ fbVg = nvgCreateSharedGLES2(vg, nvgFlags);
+#else
+ fbVg = nvgCreateSharedGL2(vg, nvgFlags);
+#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.
@@ -219,41 +264,6 @@
- }
- // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window
- glfwSetCursor(win, NULL);
+ // Set up NanoVG
+ const int nvgFlags = NVG_ANTIALIAS;
+ vg = nvgCreateGL(nvgFlags);
+ DISTRHO_SAFE_ASSERT_RETURN(vg != nullptr,);
+#ifdef NANOVG_GLES2
+ fbVg = nvgCreateSharedGLES2(vg, nvgFlags);
+#else
+ fbVg = nvgCreateSharedGL2(vg, nvgFlags);
#endif
- APP->window->internal->lastMousePos = mousePos;
-
- APP->event->handleHover(mousePos, mouseDelta);
-
- // Keyboard/mouse MIDI driver
- int width, height;
- glfwGetWindowSize(win, &width, &height);
- math::Vec scaledPos(xpos / width, ypos / height);
- keyboard::mouseMove(scaledPos);
-}
-
-
-static void cursorEnterCallback(GLFWwindow* win, int entered) {
- contextSet((Context*) glfwGetWindowUserPointer(win));
- if (!entered) {
- APP->event->handleLeave();
- }
-}
-
-
-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);
+ // Load default Blendish font
+#ifndef DGL_NO_SHARED_RESOURCES
+ uiFont = std::make_shared<Font>();
@@ -266,23 +276,16 @@
+ uiFont2->handle = loadFallbackFont(vg);
+ uiFont2->ofilename = asset::system("res/fonts/DejaVuSans.ttf");
+ internal->fontCache[uiFont2->ofilename] = uiFont2;
#else
- scrollDelta = scrollDelta.mult(50.0);
+#else
+ uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf"));
#endif
- APP->event->handleScroll(APP->window->internal->lastMousePos, scrollDelta);
-}
-
-
-static void charCallback(GLFWwindow* win, unsigned int codepoint) {
- contextSet((Context*) glfwGetWindowUserPointer(win));
- if (APP->event->handleText(APP->window->internal->lastMousePos, codepoint))
- return;
- APP->window->internal->lastMousePos = mousePos;
+ if (uiFont != nullptr)
+ bndSetFont(uiFont->handle);
}
+}
- APP->event->handleHover(mousePos, mouseDelta);
+void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui)
+{
+ if (ui != nullptr)
@@ -304,18 +307,11 @@
+ window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS);
+#endif
-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);
- }
- int width, height;
- glfwGetWindowSize(win, &width, &height);
- math::Vec scaledPos(xpos / width, ypos / height);
- keyboard::mouseMove(scaledPos);
-}
+ // swap contexts
+ window->internal->o_vg = window->vg;
@@ -344,43 +340,19 @@
+ // Init settings
+ WindowParametersRestore(window);
-static void dropCallback(GLFWwindow* win, int count, const char** paths) {
-static void cursorEnterCallback(GLFWwindow* win, int entered) {
- contextSet((Context*) glfwGetWindowUserPointer(win));
- std::vector<std::string> pathsVec;
- for (int i = 0; i < count; i++) {
- pathsVec.push_back(paths[i]);
- if (!entered) {
- APP->event->handleLeave();
+ widget::Widget::ContextCreateEvent e;
+ APP->scene->onContextCreate(e);
}
- APP->event->handleDrop(APP->window->internal->lastMousePos, pathsVec);
-}
-
-
-static void errorCallback(int error, const char* description) {
- WARN("GLFW error %d: %s", error, description);
-}
-
-
-Window::Window() {
- internal = new Internal;
- int err;
+ else
+ {
+ widget::Widget::ContextDestroyEvent e;
+ APP->scene->onContextDestroy(e);
- // Set window hints
-#if defined NANOVG_GL2
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-#elif defined NANOVG_GL3
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#endif
- glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
- glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
+ // swap contexts
+ window->uiFont->vg = window->internal->o_vg;
+ window->vg = window->internal->o_vg;
@@ -404,14 +376,106 @@
+ image.second->ohandle = -1;
+ }
-static void scrollCallback(GLFWwindow* win, double x, double y) {
- contextSet((Context*) glfwGetWindowUserPointer(win));
- math::Vec scrollDelta = math::Vec(x, y);
-#if defined ARCH_MAC
- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
- scrollDelta = scrollDelta.mult(10.0);
+#if defined NANOVG_GLES2
+ nvgDeleteGLES2(window->internal->r_fbVg);
+#else
#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);
+ 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 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
}
-}
-
-static void dropCallback(GLFWwindow* win, int count, const char** paths) {
- contextSet((Context*) glfwGetWindowUserPointer(win));
- std::vector<std::string> pathsVec;
- for (int i = 0; i < count; i++) {
- pathsVec.push_back(paths[i]);
- }
- APP->event->handleDrop(APP->window->internal->lastMousePos, pathsVec);
+ delete internal;
}
-static void errorCallback(int error, const char* description) {
- WARN("GLFW error %d: %s", error, description);
+math::Vec Window::getSize() {
+ return internal->size;
}
-Window::Window() {
- internal = new Internal;
- int err;
-
- // Set window hints
-#if defined NANOVG_GL2
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-#elif defined NANOVG_GL3
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-#endif
- glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE);
- glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
-
-#if defined ARCH_MAC
- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
-#endif
-
- // Create window
- win = glfwCreateWindow(1024, 720, "", NULL, NULL);
- if (!win) {
@@ -478,7 +542,10 @@
-
- // 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
@@ -493,29 +560,35 @@
- 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);
+ window->internal->ui = nullptr;
+ window->internal->callback = nullptr;
}
- }
+void Window::run() {
+ internal->frame = 0;
}
+void WindowSetMods(Window* const window, const int mods)
+{
+ window->internal->mods = mods;
+}
Window::~Window() {
-Window::~Window() {
- if (APP->scene) {
- widget::Widget::ContextDestroyEvent e;
- APP->scene->onContextDestroy(e);
- }
+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;
+ uint8_t tmp[width * depth];
+ std::memcpy(tmp, &pixels[y * width * depth], width * depth);
+ 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();
@@ -530,53 +603,66 @@
- nvgDeleteGL3(vg);
-#elif defined NANOVG_GLES2
- nvgDeleteGLES2(vg);
+ {
+ 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 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
+ }
-#endif
-
- glfwDestroyWindow(win);
delete internal;
- delete internal;
}
math::Vec Window::getSize() {
-math::Vec Window::getSize() {
- int width, height;
- glfwGetWindowSize(win, &width, &height);
- return math::Vec(width, height);
+ return internal->size;
}
-}
-
+#ifdef STBI_WRITE_NO_STDIO
+static void Window__downscaleBitmap(uint8_t* pixels, int& width, int& height) {
+ int targetWidth = width;
+ int targetHeight = height;
+ double scale = 1.0;
+
+ if (targetWidth > 340) {
+ scale = width / 340.0;
+ targetWidth = 340;
+ targetHeight = height / scale;
+ }
+ if (targetHeight > 210) {
+ scale = height / 210.0;
+ targetHeight = 210;
+ targetWidth = width / scale;
+ }
+ DISTRHO_SAFE_ASSERT_INT_RETURN(targetWidth <= 340, targetWidth,);
+ DISTRHO_SAFE_ASSERT_INT_RETURN(targetHeight <= 210, targetHeight,);
+
+ // FIXME worst possible quality :/
+ for (int y = 0; y < targetHeight; ++y) {
+ const int ys = static_cast<int>(y * scale);
+ for (int x = 0; x < targetWidth; ++x) {
+ const int xs = static_cast<int>(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);
-void Window::setSize(math::Vec size) {
- size = size.max(WINDOW_SIZE_MIN);
- glfwSetWindowSize(win, size.x, size.y);
+ internal->size = size;
+
+ if (DISTRHO_NAMESPACE::UI* const ui = internal->ui)
+ ui->setSize(internal->size.x, internal->size.y);
+ width = targetWidth;
+ height = targetHeight;
}
void Window::run() {
internal->frame = 0;
-
-void Window::run() {
- internal->frame = 0;
- while (!glfwWindowShouldClose(win)) {
- step();
- }
+static void Window__writeImagePNG(void* context, void* data, int size) {
+ USE_NAMESPACE_DISTRHO
+ UI* const ui = static_cast<UI*>(context);
+ ui->setState("screenshot", String::asBase64(data, size).buffer());
}
+#endif
void Window::step() {
@@ -624,7 +710,7 @@
if (APP->patch->path != "") {
windowTitle += " - ";
if (!APP->history->isSaved())
@@ -455,31 +367,23 @@
@@ -455,243 +437,155 @@
windowTitle += system::getFilename(APP->patch->path);
}
if (windowTitle != internal->lastWindowTitle) {
@@ -648,6 +734,16 @@
APP->event->handleDirty();
}
+ // Hide menu and background if generating screenshot
+ if (internal->generateScreenshotStep == kScreenshotStepStarted) {
+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS
+ APP->scene->menuBar->hide();
+ APP->scene->rack->children.front()->hide();
+#else
+ internal->generateScreenshotStep = kScreenshotStepSecondPass;
+#endif
+ }
+
// Get framebuffer/window ratio
- int fbWidth, fbHeight;
- glfwGetFramebufferSize(win, &fbWidth, &fbHeight);
@@ -662,7 +758,9 @@
if (APP->scene) {
// DEBUG("%f %f %d %d", pixelRatio, windowRatio, fbWidth, winWidth);
@@ -488,13 +392,10 @@
// Resize scene
- APP->scene->box.size = math::Vec(fbWidth, fbHeight).div(pixelRatio);
+ APP->scene->box.size = math::Vec(fbWidth, fbHeight).div(newPixelRatio);
// Step scene
APP->scene->step();
@@ -674,17 +772,22 @@
+ {
// Update and render
- nvgBeginFrame(vg, fbWidth, fbHeight, pixelRatio);
nvgScale(vg, pixelRatio, pixelRatio);
- nvgScale(vg, pixelRatio, pixelRatio);
+ nvgScale(vg, newPixelRatio, newPixelRatio);
// Draw scene
@@ -502,196 +403,60 @@
widget::Widget::DrawArgs args;
args.vg = vg;
args.clipBox = APP->scene->box.zeroPos();
APP->scene->draw(args);
- // t3 = system::getTime();
glViewport(0, 0, fbWidth, fbHeight);
+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+#else
glClearColor(0.0, 0.0, 0.0, 1.0);
+#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- nvgEndFrame(vg);
- // t4 = system::getTime();
@@ -692,7 +795,8 @@
}
- glfwSwapBuffers(win);
-
+ ++internal->frame;
- // On some platforms, glfwSwapBuffers() doesn't wait on monitor refresh, so we have to sleep as a fallback.
- double frameDurationRemaining = getFrameDurationRemaining();
- if (frameDurationRemaining > 0.0) {
@@ -710,14 +814,27 @@
- // (t5 - frameTime) * 1e3f
- // );
- internal->frame++;
+ ++internal->frame;
}
-}
+ if (internal->generateScreenshotStep != kScreenshotStepNone) {
+ ++internal->generateScreenshotStep;
+ int y = 0;
+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS
+ constexpr const int depth = 4;
+#else
+ y = APP->scene->menuBar->box.size.y * newPixelRatio;
+ constexpr const int depth = 3;
+#endif
void Window::activateContext() {
-void Window::activateContext() {
- glfwMakeContextCurrent(win);
}
-}
+ // Allocate pixel color buffer
+ uint8_t* const pixels = new uint8_t[winHeight * winWidth * 4];
+ // 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++) {
@@ -726,8 +843,28 @@
- 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);
- }
+void Window::screenshot(const std::string&) {
+ if (internal->generateScreenshotStep == kScreenshotStepSaving)
+ {
+ // Write pixels to PNG
+ const int stride = winWidth * depth;
+ uint8_t* const pixelsWithOffset = pixels + (stride * y);
+ Window__flipBitmap(pixels, winWidth, winHeight, depth);
+ winHeight -= y;
+#ifdef STBI_WRITE_NO_STDIO
+ Window__downscaleBitmap(pixelsWithOffset, winWidth, winHeight);
+ stbi_write_png_to_func(Window__writeImagePNG, internal->ui,
+ winWidth, winHeight, depth, pixelsWithOffset, stride);
+#else
+ stbi_write_png("screenshot.png", winWidth, winHeight, depth, pixelsWithOffset, stride);
+#endif
+
+ internal->generateScreenshotStep = kScreenshotStepNone;
+ APP->scene->menuBar->show();
+ APP->scene->rack->children.front()->show();
+ }
+
+ delete[] pixels;
}
}
@@ -796,17 +933,23 @@
- 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() {
+}
- // Write pixels to PNG
- flipBitmap(pixels, width, height, 4);
- stbi_write_png(filename.c_str(), width, height, 4, pixels, width * 4);
-
- // Cleanup
- delete[] pixels;
- nvgluBindFramebuffer(NULL);
- delete fbw;
- }
- }
+void Window::screenshot(const std::string&) {
+}
+
+
+void Window::screenshotModules(const std::string&, float) {
}
@@ -880,11 +1023,15 @@
bool Window::isFullScreen() {
- GLFWmonitor* monitor = glfwGetWindowMonitor(win);
- return monitor != NULL;
+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS
+ return internal->generateScreenshotStep != kScreenshotStepNone;
+#else
+ return false;
+#endif
}
@@ -722,14 +487,15 @@
@@ -722,14 +616,15 @@
return pair->second;
// Load font
@@ -903,7 +1050,7 @@
}
internal->fontCache[filename] = font;
return font;
@@ -742,14 +508,15 @@
@@ -742,14 +637,15 @@
return pair->second;
// Load image
@@ -922,24 +1069,29 @@
}
internal->imageCache[filename] = image;
return image;
@@ -767,27 +534,116 @@
@@ -766,28 +662,122 @@
}
void init() {
-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
-
- glfwSetErrorCallback(errorCallback);
- err = glfwInit();
- if (err != GLFW_TRUE) {
- osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLFW.");
- throw Exception("Could not initialize GLFW");
- }
+void init() {
}


+ 2
- 2
src/override/diffs/blendish.c.diff View File

@@ -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 2021-12-12 16:59:23.714275191 +0000
+++ blendish.c 2021-12-12 16:51:37.956349106 +0000
@@ -61,7 +61,7 @@
}


+ 2
- 2
src/override/diffs/common.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/common.cpp 2021-11-23 19:57:23.719015894 +0000
+++ common.cpp 2022-01-31 13:24:14.558807713 +0000
--- ../Rack/src/common.cpp 2021-12-04 09:46:43.912932319 +0000
+++ common.cpp 2022-01-24 00:11:36.628498885 +0000
@@ -1,6 +1,38 @@
+/*
+ * DISTRHO Cardinal Plugin


+ 2
- 2
src/override/diffs/context.cpp.diff View File

@@ -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-01-15 11:59:46.188414546 +0000
+++ context.cpp 2022-01-24 00:11:36.628498885 +0000
@@ -1,3 +1,30 @@
+/*
+ * DISTRHO Cardinal Plugin


+ 2
- 2
src/override/diffs/plugin.cpp.diff View File

@@ -1,5 +1,5 @@
--- ../Rack/src/plugin.cpp 2022-02-05 22:30:09.265393248 +0000
+++ plugin.cpp 2022-01-30 00:24:49.375329910 +0000
--- ../Rack/src/plugin.cpp 2022-01-15 11:59:46.188414546 +0000
+++ plugin.cpp 2022-01-30 02:49:08.228488442 +0000
@@ -1,308 +1,40 @@
-#include <thread>
-#include <map>


Loading…
Cancel
Save