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


3rd-party libraries build setup. 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. 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. 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. 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. 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. 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 ## plugins


Module/Plugin related code and build setup. 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. 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 ### extra


A few extra files for having access to a few utilities, code borrowed from Carla, which in turn borrowed it from JUCE. 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. 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 ### 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". 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 ### CardinalPlugin.cpp


The DSP/plugin side of the plugin, and also where the global/shared class lifecycle is managed. 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. 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. 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 ### template.vcv


The default template patch as used by Cardinal 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 @@ @@ -1,3 +1,30 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * 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 @@ @@ -1,8 +1,33 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * DISTRHO Cardinal Plugin
@@ -218,11 +218,14 @@
static const std::vector<std::string> knobModeLabels = { static const std::vector<std::string> knobModeLabels = {
"Linear", "Linear",
@@ -467,6 +478,21 @@
@@ -467,6 +478,25 @@
menu->addChild(knobScrollSensitivitySlider); menu->addChild(knobScrollSensitivitySlider);
menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules));
+ +
+#ifndef DISTRHO_OS_MAC
+ menu->addChild(new ui::MenuSeparator);
+
+ static const std::vector<std::string> rateLimitLabels = { + static const std::vector<std::string> rateLimitLabels = {
+ "None", + "None",
+ "2x", + "2x",
@@ -237,10 +240,11 @@
+ )); + ));
+ } + }
+ })); + }));
+#endif
} }
}; };
@@ -476,47 +502,6 @@
@@ -476,47 +506,6 @@
//////////////////// ////////////////////
@@ -288,7 +292,7 @@
struct EngineButton : MenuButton { struct EngineButton : MenuButton {
void onAction(const ActionEvent& e) override { void onAction(const ActionEvent& e) override {
ui::Menu* menu = createMenu(); ui::Menu* menu = createMenu();
@@ -529,269 +514,6 @@
@@ -529,269 +518,6 @@
menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() { menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() {
settings::cpuMeter ^= true; settings::cpuMeter ^= true;
})); }));
@@ -558,7 +562,7 @@
} }
}; };
@@ -802,63 +524,23 @@
@@ -802,63 +528,23 @@
struct HelpButton : MenuButton { struct HelpButton : MenuButton {
@@ -627,7 +631,7 @@
} }
}; };
@@ -908,7 +590,9 @@
@@ -908,7 +594,9 @@
struct MenuBar : widget::OpaqueWidget { struct MenuBar : widget::OpaqueWidget {
MeterLabel* meterLabel; MeterLabel* meterLabel;
@@ -638,7 +642,7 @@
const float margin = 5; const float margin = 5;
box.size.y = BND_WIDGET_HEIGHT + 2 * margin; box.size.y = BND_WIDGET_HEIGHT + 2 * margin;
@@ -917,7 +601,7 @@
@@ -917,7 +605,7 @@
layout->spacing = math::Vec(0, 0); layout->spacing = math::Vec(0, 0);
addChild(layout); addChild(layout);
@@ -647,7 +651,7 @@
fileButton->text = "File"; fileButton->text = "File";
layout->addChild(fileButton); layout->addChild(fileButton);
@@ -933,10 +617,6 @@
@@ -933,10 +621,6 @@
engineButton->text = "Engine"; engineButton->text = "Engine";
layout->addChild(engineButton); layout->addChild(engineButton);
@@ -658,7 +662,7 @@
HelpButton* helpButton = new HelpButton; HelpButton* helpButton = new HelpButton;
helpButton->text = "Help"; helpButton->text = "Help";
layout->addChild(helpButton); layout->addChild(helpButton);
@@ -971,7 +651,11 @@
@@ -971,7 +655,11 @@
widget::Widget* createMenuBar() { 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 @@ @@ -1,3 +1,30 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * 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 @@ @@ -1,3 +1,30 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * DISTRHO Cardinal Plugin
@@ -39,7 +39,7 @@
#include <system.hpp> #include <system.hpp>
#include <network.hpp> #include <network.hpp>
#include <history.hpp> #include <history.hpp>
@@ -14,6 +42,17 @@
@@ -14,6 +42,18 @@
#include <patch.hpp> #include <patch.hpp>
#include <asset.hpp> #include <asset.hpp>
@@ -52,12 +52,13 @@
+#endif +#endif
+ +
+#include "../CardinalCommon.hpp" +#include "../CardinalCommon.hpp"
+#include "extra/Base64.hpp"
+#include "DistrhoUtils.hpp" +#include "DistrhoUtils.hpp"
+ +
namespace rack { namespace rack {
namespace app { namespace app {
@@ -23,16 +62,55 @@
@@ -23,16 +63,55 @@
math::Vec size; math::Vec size;
void draw(const DrawArgs& args) override { void draw(const DrawArgs& args) override {
@@ -108,18 +109,18 @@
+ +
+ void onEnter(const EnterEvent& e) override { + void onEnter(const EnterEvent& e) override {
+ glfwSetCursor(nullptr, (GLFWcursor*)0x1); + glfwSetCursor(nullptr, (GLFWcursor*)0x1);
+ }
+
+ void onLeave(const LeaveEvent& e) override {
+ glfwSetCursor(nullptr, nullptr);
} }
- void onDragStart(const DragStartEvent& e) override { - void onDragStart(const DragStartEvent& e) override {
+ void onLeave(const LeaveEvent& e) override {
+ glfwSetCursor(nullptr, nullptr);
+ }
+
+ void onDragStart(const DragStartEvent&) override { + void onDragStart(const DragStartEvent&) override {
size = APP->window->getSize(); size = APP->window->getSize();
} }
@@ -46,9 +124,32 @@
@@ -46,9 +125,32 @@
struct Scene::Internal { struct Scene::Internal {
ResizeHandle* resizeHandle; ResizeHandle* resizeHandle;
@@ -154,7 +155,7 @@
}; };
@@ -67,13 +168,8 @@
@@ -67,13 +169,8 @@
browser->hide(); browser->hide();
addChild(browser); addChild(browser);
@@ -169,25 +170,8 @@
addChild(internal->resizeHandle); 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; menuBar->box.size.x = box.size.x;
+ rackScroll->box.pos.y = menuBar->box.size.y;
rackScroll->box.size = box.size.minus(rackScroll->box.pos); rackScroll->box.size = box.size.minus(rackScroll->box.pos);
- // Autosave periodically - // Autosave periodically
@@ -203,7 +187,7 @@
// Scroll RackScrollWidget with arrow keys // Scroll RackScrollWidget with arrow keys
math::Vec arrowDelta; math::Vec arrowDelta;
if (internal->heldArrowKeys[0]) { if (internal->heldArrowKeys[0]) {
@@ -143,6 +220,22 @@
@@ -143,6 +230,23 @@
rackScroll->offset += arrowDelta * arrowSpeed; rackScroll->offset += arrowDelta * arrowSpeed;
} }
@@ -218,6 +202,7 @@
+ internal->historyActionIndex = actionIndex; + internal->historyActionIndex = actionIndex;
+ internal->lastSceneChangeTime = time; + internal->lastSceneChangeTime = time;
+ patchUtils::deployToRemote(); + patchUtils::deployToRemote();
+ window::generateScreenshot();
+ } + }
+ } + }
+ } + }
@@ -226,7 +211,7 @@
Widget::step(); Widget::step();
} }
@@ -172,7 +265,7 @@
@@ -172,7 +276,7 @@
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { 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()); // 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) { if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -235,7 +220,7 @@
e.consume(this); e.consume(this);
} }
if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -180,19 +273,20 @@
@@ -180,19 +284,20 @@
e.consume(this); e.consume(this);
} }
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
@@ -260,7 +245,7 @@
e.consume(this); e.consume(this);
} }
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { 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)); APP->scene->rackScroll->setZoom(std::pow(2.f, zoom));
e.consume(this); e.consume(this);
} }
@@ -276,7 +261,7 @@
if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) { if (e.key == GLFW_KEY_F1 && (e.mods & RACK_MOD_MASK) == 0) {
system::openBrowser("https://vcvrack.com/manual/"); system::openBrowser("https://vcvrack.com/manual/");
e.consume(this); e.consume(this);
@@ -232,10 +330,8 @@
@@ -232,10 +341,13 @@
settings::cpuMeter ^= true; settings::cpuMeter ^= true;
e.consume(this); e.consume(this);
} }
@@ -286,10 +271,15 @@
- // menuBar->hide(); - // menuBar->hide();
+ if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { + if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) {
+ patchUtils::deployToRemote(); + patchUtils::deployToRemote();
+ window::generateScreenshot();
+ e.consume(this);
+ }
+ if (e.key == GLFW_KEY_F9 && (e.mods & RACK_MOD_MASK) == 0) {
+ window::generateScreenshot();
e.consume(this); e.consume(this);
} }
@@ -326,13 +422,6 @@
@@ -326,13 +438,6 @@
// Key commands that can be overridden by children // Key commands that can be overridden by children
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { 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) { if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
rack->pasteClipboardAction(); rack->pasteClipboardAction();
e.consume(this); e.consume(this);
@@ -351,7 +440,7 @@
@@ -351,7 +456,7 @@
std::string extension = system::getExtension(path); std::string extension = system::getExtension(path);
if (extension == ".vcv") { if (extension == ".vcv") {
@@ -312,7 +302,7 @@
e.consume(this); e.consume(this);
return; return;
} }
@@ -368,3 +457,77 @@
@@ -368,3 +473,94 @@
} // namespace app } // namespace app
} // namespace rack } // 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 +} // 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 + * DISTRHO Cardinal Plugin
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com> + * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
@@ -49,15 +49,27 @@
#include <context.hpp> #include <context.hpp>
#include <patch.hpp> #include <patch.hpp>
#include <settings.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 +#ifdef NDEBUG
+# undef DEBUG +# undef DEBUG
+#endif +#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 "DistrhoUI.hpp"
+#include "Application.hpp" +#include "Application.hpp"
+#include "extra/String.hpp"
+#include "../CardinalCommon.hpp" +#include "../CardinalCommon.hpp"
+#include "../WindowParameters.hpp" +#include "../WindowParameters.hpp"
+ +
@@ -85,7 +97,30 @@
Font::~Font() { 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 { struct Window::Internal {
std::string lastWindowTitle; std::string lastWindowTitle;
@@ -113,6 +148,7 @@
- int frameSwapInterval = -1; - int frameSwapInterval = -1;
- double monitorRefreshRate = 0.0; - double monitorRefreshRate = 0.0;
+ int frameSwapInterval = 1; + int frameSwapInterval = 1;
+ int generateScreenshotStep = kScreenshotStepNone;
+ double monitorRefreshRate = 60.0; + double monitorRefreshRate = 60.0;
double frameTime = 0.0; double frameTime = 0.0;
double lastFrameDuration = 0.0; double lastFrameDuration = 0.0;
@@ -189,24 +225,33 @@
- APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods); - APP->event->handleButton(APP->window->internal->lastMousePos, button, action, mods);
-} -}
-
-
+Window::Window() {
+ internal = new Internal;
-static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) { -static void cursorPosCallback(GLFWwindow* win, double xpos, double ypos) {
- contextSet((Context*) glfwGetWindowUserPointer(win)); - contextSet((Context*) glfwGetWindowUserPointer(win));
- math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round(); - math::Vec mousePos = math::Vec(xpos, ypos).div(APP->window->pixelRatio / APP->window->windowRatio).round();
- math::Vec mouseDelta = mousePos.minus(APP->window->internal->lastMousePos); - 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. - // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked.
- if (APP->window->internal->ignoreNextMouseDelta) { - if (APP->window->internal->ignoreNextMouseDelta) {
- APP->window->internal->ignoreNextMouseDelta = false; - APP->window->internal->ignoreNextMouseDelta = false;
- mouseDelta = math::Vec(); - mouseDelta = math::Vec();
- } - }
+Window::Window() {
+ internal = new Internal;
+ DGL_NAMESPACE::Window::ScopedGraphicsContext sgc(internal->hiddenWindow);
- int cursorMode = glfwGetInputMode(win, GLFW_CURSOR); - int cursorMode = glfwGetInputMode(win, GLFW_CURSOR);
- (void) cursorMode; - (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 -#if defined ARCH_MAC
- // Workaround for Mac. We can't use GLFW_CURSOR_DISABLED because it's buggy, so implement it on our own. - // 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 - // Because sometimes the cursor turns into an arrow when its position is on the boundary of the window
- glfwSetCursor(win, NULL); - 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 + // Load default Blendish font
+#ifndef DGL_NO_SHARED_RESOURCES +#ifndef DGL_NO_SHARED_RESOURCES
+ uiFont = std::make_shared<Font>(); + uiFont = std::make_shared<Font>();
@@ -266,23 +276,16 @@
+ uiFont2->handle = loadFallbackFont(vg); + uiFont2->handle = loadFallbackFont(vg);
+ uiFont2->ofilename = asset::system("res/fonts/DejaVuSans.ttf"); + uiFont2->ofilename = asset::system("res/fonts/DejaVuSans.ttf");
+ internal->fontCache[uiFont2->ofilename] = uiFont2; + internal->fontCache[uiFont2->ofilename] = uiFont2;
#else
- scrollDelta = scrollDelta.mult(50.0);
+#else
+ uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); + uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf"));
#endif #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) + if (uiFont != nullptr)
+ bndSetFont(uiFont->handle); + bndSetFont(uiFont->handle);
}
+}
- APP->event->handleHover(mousePos, mouseDelta);
+void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui) +void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui)
+{ +{
+ if (ui != nullptr) + if (ui != nullptr)
@@ -304,18 +307,11 @@
+ window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS); + window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS);
+#endif +#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 - // 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 + // swap contexts
+ window->internal->o_vg = window->vg; + window->internal->o_vg = window->vg;
@@ -344,43 +340,19 @@
+ // Init settings + // Init settings
+ WindowParametersRestore(window); + WindowParametersRestore(window);
-static void dropCallback(GLFWwindow* win, int count, const char** paths) {
-static void cursorEnterCallback(GLFWwindow* win, int entered) {
- contextSet((Context*) glfwGetWindowUserPointer(win)); - 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; + widget::Widget::ContextCreateEvent e;
+ APP->scene->onContextCreate(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 + else
+ { + {
+ widget::Widget::ContextDestroyEvent e; + widget::Widget::ContextDestroyEvent e;
+ APP->scene->onContextDestroy(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 + // swap contexts
+ window->uiFont->vg = window->internal->o_vg; + window->uiFont->vg = window->internal->o_vg;
+ window->vg = window->internal->o_vg; + window->vg = window->internal->o_vg;
@@ -404,14 +376,106 @@
+ image.second->ohandle = -1; + 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 -#if defined ARCH_MAC
- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE);
- scrollDelta = scrollDelta.mult(10.0);
+#if defined NANOVG_GLES2 +#if defined NANOVG_GLES2
+ nvgDeleteGLES2(window->internal->r_fbVg); + nvgDeleteGLES2(window->internal->r_fbVg);
+#else
#else
- scrollDelta = scrollDelta.mult(50.0);
+ nvgDeleteGL2(window->internal->r_fbVg); + nvgDeleteGL2(window->internal->r_fbVg);
#endif #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 - // Create window
- win = glfwCreateWindow(1024, 720, "", NULL, NULL); - win = glfwCreateWindow(1024, 720, "", NULL, NULL);
- if (!win) { - if (!win) {
@@ -478,7 +542,10 @@
- -
- // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. - // GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here.
- glGetError(); - glGetError();
-
+void Window::setSize(math::Vec size) {
+ size = size.max(WINDOW_SIZE_MIN);
+ internal->size = size;
- // Set up NanoVG - // Set up NanoVG
- int nvgFlags = NVG_ANTIALIAS; - int nvgFlags = NVG_ANTIALIAS;
-#if defined NANOVG_GL2 -#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."); - 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"); - 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 - // Load default Blendish font
- uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); - uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf"));
- bndSetFont(uiFont->handle); - bndSetFont(uiFont->handle);
-
- if (APP->scene) { - if (APP->scene) {
- widget::Widget::ContextCreateEvent e; - widget::Widget::ContextCreateEvent e;
- APP->scene->onContextCreate(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) { - if (APP->scene) {
- widget::Widget::ContextDestroyEvent e; - widget::Widget::ContextDestroyEvent e;
- APP->scene->onContextDestroy(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 - // Fonts and Images in the cache must be deleted before the NanoVG context is deleted
- internal->fontCache.clear(); - internal->fontCache.clear();
@@ -530,53 +603,66 @@
- nvgDeleteGL3(vg); - nvgDeleteGL3(vg);
-#elif defined NANOVG_GLES2 -#elif defined NANOVG_GLES2
- nvgDeleteGLES2(vg); - 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); - glfwDestroyWindow(win);
delete internal;
- delete internal;
} }
math::Vec Window::getSize() {
-math::Vec Window::getSize() {
- int width, height; - int width, height;
- glfwGetWindowSize(win, &width, &height); - glfwGetWindowSize(win, &width, &height);
- return math::Vec(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); - 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)) { - while (!glfwWindowShouldClose(win)) {
- step(); - 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() { void Window::step() {
@@ -624,7 +710,7 @@
if (APP->patch->path != "") { if (APP->patch->path != "") {
windowTitle += " - "; windowTitle += " - ";
if (!APP->history->isSaved()) if (!APP->history->isSaved())
@@ -455,31 +367,23 @@
@@ -455,243 +437,155 @@
windowTitle += system::getFilename(APP->patch->path); windowTitle += system::getFilename(APP->patch->path);
} }
if (windowTitle != internal->lastWindowTitle) { if (windowTitle != internal->lastWindowTitle) {
@@ -648,6 +734,16 @@
APP->event->handleDirty(); 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 // Get framebuffer/window ratio
- int fbWidth, fbHeight; - int fbWidth, fbHeight;
- glfwGetFramebufferSize(win, &fbWidth, &fbHeight); - glfwGetFramebufferSize(win, &fbWidth, &fbHeight);
@@ -662,7 +758,9 @@
if (APP->scene) { if (APP->scene) {
// DEBUG("%f %f %d %d", pixelRatio, windowRatio, fbWidth, winWidth); // 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 // Step scene
APP->scene->step(); APP->scene->step();
@@ -674,17 +772,22 @@
+ { + {
// Update and render // Update and render
- nvgBeginFrame(vg, fbWidth, fbHeight, pixelRatio); - nvgBeginFrame(vg, fbWidth, fbHeight, pixelRatio);
nvgScale(vg, pixelRatio, pixelRatio);
- nvgScale(vg, pixelRatio, pixelRatio);
+ nvgScale(vg, newPixelRatio, newPixelRatio);
// Draw scene // Draw scene
@@ -502,196 +403,60 @@
widget::Widget::DrawArgs args;
args.vg = vg; args.vg = vg;
args.clipBox = APP->scene->box.zeroPos(); args.clipBox = APP->scene->box.zeroPos();
APP->scene->draw(args); APP->scene->draw(args);
- // t3 = system::getTime(); - // t3 = system::getTime();
glViewport(0, 0, fbWidth, fbHeight); 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); glClearColor(0.0, 0.0, 0.0, 1.0);
+#endif
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- nvgEndFrame(vg); - nvgEndFrame(vg);
- // t4 = system::getTime(); - // t4 = system::getTime();
@@ -692,7 +795,8 @@
} }
- glfwSwapBuffers(win); - glfwSwapBuffers(win);
-
+ ++internal->frame;
- // On some platforms, glfwSwapBuffers() doesn't wait on monitor refresh, so we have to sleep as a fallback. - // On some platforms, glfwSwapBuffers() doesn't wait on monitor refresh, so we have to sleep as a fallback.
- double frameDurationRemaining = getFrameDurationRemaining(); - double frameDurationRemaining = getFrameDurationRemaining();
- if (frameDurationRemaining > 0.0) { - if (frameDurationRemaining > 0.0) {
@@ -710,14 +814,27 @@
- // (t5 - frameTime) * 1e3f - // (t5 - frameTime) * 1e3f
- // ); - // );
- internal->frame++; - 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); - 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) { -static void flipBitmap(uint8_t* pixels, int width, int height, int depth) {
- for (int y = 0; y < height / 2; y++) { - for (int y = 0; y < height / 2; y++) {
@@ -726,8 +843,28 @@
- std::memcpy(tmp, &pixels[y * width * depth], 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[y * width * depth], &pixels[flipY * width * depth], width * depth);
- std::memcpy(&pixels[flipY * width * depth], tmp, 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); - nvgImageSize(vg, fbw->getImageHandle(), &width, &height);
- uint8_t* pixels = new uint8_t[height * width * 4]; - uint8_t* pixels = new uint8_t[height * width * 4];
- glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
-
+void Window::activateContext() {
+}
- // Write pixels to PNG - // Write pixels to PNG
- flipBitmap(pixels, width, height, 4); - flipBitmap(pixels, width, height, 4);
- stbi_write_png(filename.c_str(), width, height, 4, pixels, width * 4); - stbi_write_png(filename.c_str(), width, height, 4, pixels, width * 4);
-
- // Cleanup - // Cleanup
- delete[] pixels; - delete[] pixels;
- nvgluBindFramebuffer(NULL); - nvgluBindFramebuffer(NULL);
- delete fbw; - delete fbw;
- } - }
- } - }
+void Window::screenshot(const std::string&) {
+}
+
+
+void Window::screenshotModules(const std::string&, float) { +void Window::screenshotModules(const std::string&, float) {
} }
@@ -880,11 +1023,15 @@
bool Window::isFullScreen() { bool Window::isFullScreen() {
- GLFWmonitor* monitor = glfwGetWindowMonitor(win); - GLFWmonitor* monitor = glfwGetWindowMonitor(win);
- return monitor != NULL; - return monitor != NULL;
+#ifdef CARDINAL_TRANSPARENT_SCREENSHOTS
+ return internal->generateScreenshotStep != kScreenshotStepNone;
+#else
+ return false; + return false;
+#endif
} }
@@ -722,14 +487,15 @@
@@ -722,14 +616,15 @@
return pair->second; return pair->second;
// Load font // Load font
@@ -903,7 +1050,7 @@
} }
internal->fontCache[filename] = font; internal->fontCache[filename] = font;
return font; return font;
@@ -742,14 +508,15 @@
@@ -742,14 +637,15 @@
return pair->second; return pair->second;
// Load image // Load image
@@ -922,24 +1069,29 @@
} }
internal->imageCache[filename] = image; internal->imageCache[filename] = image;
return image; return image;
@@ -767,27 +534,116 @@
@@ -766,28 +662,122 @@
}
void init() {
-void init() {
- int err; - int err;
-
+void generateScreenshot() {
+ APP->window->internal->generateScreenshotStep = kScreenshotStepStarted;
+}
- // Set up GLFW - // Set up GLFW
-#if defined ARCH_MAC -#if defined ARCH_MAC
- glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_TRUE); - glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, GLFW_TRUE);
- glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE); - glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
-#endif -#endif
-
- glfwSetErrorCallback(errorCallback); - glfwSetErrorCallback(errorCallback);
- err = glfwInit(); - err = glfwInit();
- if (err != GLFW_TRUE) { - if (err != GLFW_TRUE) {
- osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLFW."); - osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize GLFW.");
- throw Exception("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 @@ @@ -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 @@ @@ -1,6 +1,38 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * 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 @@ @@ -1,3 +1,30 @@
+/* +/*
+ * DISTRHO Cardinal Plugin + * 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 @@ @@ -1,308 +1,40 @@
-#include <thread> -#include <thread>
-#include <map> -#include <map>


Loading…
Cancel
Save