From beb0965051fd7481267ecc7867de0aee79c47cbd Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 9 Oct 2021 12:46:18 +0100 Subject: [PATCH] Multi-context, basic keyboard input --- plugins/Cardinal/CardinalPlugin.cpp | 61 +++++++++--- plugins/Cardinal/CardinalUI.cpp | 144 +++++++++++++-------------- plugins/Cardinal/DistrhoPluginInfo.h | 5 +- plugins/Cardinal/Makefile | 18 +--- plugins/Cardinal/Window.cpp | 47 ++++++--- plugins/Cardinal/dep.cpp | 10 ++ 6 files changed, 162 insertions(+), 123 deletions(-) diff --git a/plugins/Cardinal/CardinalPlugin.cpp b/plugins/Cardinal/CardinalPlugin.cpp index 757f220..a028b43 100644 --- a/plugins/Cardinal/CardinalPlugin.cpp +++ b/plugins/Cardinal/CardinalPlugin.cpp @@ -22,11 +22,14 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include @@ -99,38 +102,23 @@ struct Initializer { } INFO("Initializing environment"); - // network::init(); audio::init(); - // rtaudioInit(); midi::init(); - // rtmidiInit(); keyboard::init(); -#ifndef DPF_AS_GLFW - gamepad::init(); -#endif plugin::init(); library::init(); - // discord::init(); - ui::init(); - window::init(); } ~Initializer() { using namespace rack; - window::destroy(); ui::destroy(); - - // discord::destroy(); library::destroy(); midi::destroy(); audio::destroy(); plugin::destroy(); -#ifndef DPF_AS_GLFW - gamepad::destroy(); -#endif INFO("Destroying logger"); logger::destroy(); } @@ -146,10 +134,46 @@ static const Initializer& getInitializerInstance() class CardinalPlugin : public Plugin { + rack::Context* const fContext; + + struct ScopedContext { + ScopedContext(CardinalPlugin* const plugin) + { + rack::contextSet(plugin->fContext); + } + + ~ScopedContext() + { + rack::contextSet(nullptr); + } + }; + public: CardinalPlugin() - : Plugin(0, 0, 0) + : Plugin(0, 0, 0), + fContext(new rack::Context) { + const ScopedContext sc(this); + + fContext->engine = new rack::engine::Engine; + fContext->history = new rack::history::State; + fContext->event = new rack::widget::EventState; + fContext->scene = new rack::app::Scene; + fContext->event->rootWidget = fContext->scene; + fContext->patch = new rack::patch::Manager; + fContext->engine->startFallbackThread(); + } + + ~CardinalPlugin() override + { + const ScopedContext sc(this); + + delete fContext; + } + + rack::Context* getRackContext() const noexcept + { + return fContext; } protected: @@ -246,6 +270,11 @@ private: DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CardinalPlugin) }; +rack::Context* getRackContextFromPlugin(void* const ptr) +{ + return static_cast(ptr)->getRackContext(); +} + /* ------------------------------------------------------------------------------------------------------------ * Plugin entry point, called by DPF to create a new plugin instance. */ diff --git a/plugins/Cardinal/CardinalUI.cpp b/plugins/Cardinal/CardinalUI.cpp index c94342f..595f7be 100644 --- a/plugins/Cardinal/CardinalUI.cpp +++ b/plugins/Cardinal/CardinalUI.cpp @@ -18,9 +18,6 @@ #include #include #include -#include -#include -#include #include #include @@ -30,15 +27,6 @@ #include "DistrhoUI.hpp" #include "ResizeHandle.hpp" -namespace rack { -namespace network { - std::string encodeUrl(const std::string&) { return {}; } - json_t* requestJson(Method, const std::string&, json_t*, const CookieMap&) { return nullptr; } - bool requestDownload(const std::string&, const std::string&, float*, const CookieMap&) { return false; } -} -} - -#ifdef DPF_AS_GLFW GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window) { return nullptr; } GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char*) {} GLFWAPI const char* glfwGetKeyName(int key, int scancode) { return nullptr; } @@ -48,89 +36,66 @@ namespace rack { namespace window { DISTRHO_NAMESPACE::UI* lastUI = nullptr; - void mouseButtonCallback(Window* win, int button, int action, int mods); - void cursorPosCallback(Window* win, double xpos, double ypos); - void scrollCallback(Window* win, double x, double y); + void mouseButtonCallback(Context* ctx, int button, int action, int mods); + void cursorPosCallback(Context* ctx, double xpos, double ypos); + void cursorEnterCallback(Context* ctx, int entered); + void scrollCallback(Context* ctx, double x, double y); + void charCallback(Context* ctx, unsigned int codepoint); + void keyCallback(Context* ctx, int key, int scancode, int action, int mods); } } -#endif START_NAMESPACE_DISTRHO // ----------------------------------------------------------------------------------------------------------- -struct Initializer2 { - Initializer2() - { - using namespace rack; - - } - - ~Initializer2() - { - using namespace rack; - - } -}; - -static const Initializer2& getInitializer2Instance() -{ - static const Initializer2 init; - return init; -} +rack::Context* getRackContextFromPlugin(void* ptr); class CardinalUI : public UI { + rack::Context* const fContext; ResizeHandle fResizeHandle; + + struct ScopedContext { + ScopedContext(CardinalUI* const ui) + { + rack::contextSet(ui->fContext); + } + + ~ScopedContext() + { + rack::contextSet(nullptr); + } + }; + public: CardinalUI() : UI(1280, 720), + fContext(getRackContextFromPlugin(getPluginInstancePointer())), fResizeHandle(this) { - using namespace rack; + const ScopedContext sc(this); - /* - The following code was based from VCVRack adapters/standalone.cpp - - Copyright (C) 2016-2021 VCV - - This program is free software: you can redistribute it and/or modify it under the terms of the - GNU General Public License as published by the Free Software Foundation, either version 3 of the - License, or (at your option) any later version. - */ // Initialize context d_stdout("UI context ptr %p", NanoVG::getContext()); -#ifdef DPF_AS_GLFW - window::lastUI = this; -#endif - contextSet(new Context); - APP->engine = new engine::Engine; - APP->history = new history::State; - APP->event = new widget::EventState; - APP->scene = new app::Scene; - APP->event->rootWidget = APP->scene; - APP->patch = new patch::Manager; - /*if (!settings::headless)*/ { - APP->window = new window::Window; - } -#ifdef DPF_AS_GLFW - window::lastUI = nullptr; -#endif - - APP->engine->startFallbackThread(); + rack::window::lastUI = this; + fContext->window = new rack::window::Window; + rack::window::lastUI = nullptr; } ~CardinalUI() override { - using namespace rack; + const ScopedContext sc(this); - delete APP; - contextSet(NULL); + delete fContext->window; + fContext->window = nullptr; } void onNanoDisplay() override { - APP->window->step(); + const ScopedContext sc(this); + + fContext->window->step(); } void uiIdle() override @@ -152,9 +117,10 @@ protected: // ------------------------------------------------------------------------------------------------------- -#ifdef DPF_AS_GLFW bool onMouse(const MouseEvent& ev) override { + const ScopedContext sc(this); + int button; int mods = 0; int action = ev.press; @@ -206,22 +172,25 @@ protected: } #endif - mouseButtonCallback(APP->window, button, action, mods); + rack::window::mouseButtonCallback(fContext, button, action, mods); return true; } bool onMotion(const MotionEvent& ev) override { - cursorPosCallback(APP->window, ev.pos.getX(), ev.pos.getY()); + const ScopedContext sc(this); + + rack::window::cursorPosCallback(fContext, ev.pos.getX(), ev.pos.getY()); return true; } bool onScroll(const ScrollEvent& ev) override { - scrollCallback(APP->window, ev.delta.getX(), ev.delta.getY()); + const ScopedContext sc(this); + + rack::window::scrollCallback(fContext, ev.delta.getX(), ev.delta.getY()); return true; } -#endif #if 0 void onResize(const ResizeEvent& ev) override @@ -233,6 +202,36 @@ protected: // TODO uiFocus + bool onCharacterInput(const CharacterInputEvent& ev) override + { + if (ev.character == 0) + return false; + + const ScopedContext sc(this); + + rack::window::charCallback(fContext, ev.character); + return true; + } + + bool onKeyboard(const KeyboardEvent& ev) override + { + const ScopedContext sc(this); + + int mods = 0; + int action = ev.press; + + if (ev.mod & kModifierControl) + mods |= GLFW_MOD_CONTROL; + if (ev.mod & kModifierShift) + mods |= GLFW_MOD_SHIFT; + if (ev.mod & kModifierAlt) + mods |= GLFW_MOD_ALT; + + // TODO special key conversion + rack::window::keyCallback(fContext, ev.key, ev.keycode, action, mods); + return true; + } + private: /** Set our UI class as non-copyable and add a leak detector just in case. @@ -245,7 +244,6 @@ private: UI* createUI() { - getInitializer2Instance(); return new CardinalUI(); } diff --git a/plugins/Cardinal/DistrhoPluginInfo.h b/plugins/Cardinal/DistrhoPluginInfo.h index 0ff5612..1fe8ce0 100644 --- a/plugins/Cardinal/DistrhoPluginInfo.h +++ b/plugins/Cardinal/DistrhoPluginInfo.h @@ -28,12 +28,9 @@ #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 // #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" // #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Analyzer" -// #define DISTRHO_PLUGIN_HAS_EMBED_UI 1 -// #define DISTRHO_PLUGIN_HAS_EXTERNAL_UI 1 #define DISTRHO_UI_USE_NANOVG 1 #define DISTRHO_UI_USER_RESIZABLE 0 - -#define DPF_AS_GLFW 1 +#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 enum Parameters { kParameterCount diff --git a/plugins/Cardinal/Makefile b/plugins/Cardinal/Makefile index 7910393..918672f 100644 --- a/plugins/Cardinal/Makefile +++ b/plugins/Cardinal/Makefile @@ -16,15 +16,13 @@ FILES_DSP = \ CardinalPlugin.cpp FILES_UI = \ - CardinalUI.cpp - -FILES_UI += dep.cpp -FILES_UI += Window.cpp + CardinalUI.cpp \ + dep.cpp \ + Window.cpp # -------------------------------------------------------------- # Import base definitions -# UI_TYPE = external USE_NANOVG_FBO = true include ../../dpf/Makefile.base.mk @@ -35,7 +33,6 @@ FILES_DSP += Rack/dep/pffft/pffft.c FILES_DSP += Rack/dep/pffft/fftpack.c FILES_UI += Rack/dep/oui-blendish/blendish.c -# FILES_UI += Rack/dep/nanovg/src/nanovg.c # FIXME dont use this FILES_UI += Rack/dep/osdialog/osdialog.c @@ -63,10 +60,6 @@ endif EXTRA_LIBS += Rack/dep/lib/libzstd.a -# for raw GLFW window -# EXTRA_LIBS += Rack/dep/lib/libglfw3.a -# FILES_DSP += Rack/src/gamepad.cpp Rack/src/window/Window.cpp - # -------------------------------------------------------------- # Do some magic @@ -87,8 +80,6 @@ Rack/dep/lib/libarchive.a: Rack/dep/lib/libzstd.a Rack/dep/lib/libarchive_static.a: Rack/dep/lib/libzstd.a -Rack/dep/lib/libcrypto.a: Rack/dep/lib/libssl.a - # -------------------------------------------------------------- # Extra flags for VCV stuff @@ -98,10 +89,7 @@ BASE_FLAGS += -IRack/include BASE_FLAGS += -IRack/dep/include BASE_FLAGS += -IRack/dep/filesystem/include BASE_FLAGS += -IRack/dep/fuzzysearchdatabase/src -# BASE_FLAGS += -IRack/dep/glew-2.1.0/include -# BASE_FLAGS += -IRack/dep/glfw/deps BASE_FLAGS += -IRack/dep/glfw/include -# BASE_FLAGS += -IRack/dep/nanovg/src BASE_FLAGS += -IRack/dep/nanosvg/src BASE_FLAGS += -IRack/dep/osdialog BASE_FLAGS += -IRack/dep/oui-blendish diff --git a/plugins/Cardinal/Window.cpp b/plugins/Cardinal/Window.cpp index fe955da..4f18637 100644 --- a/plugins/Cardinal/Window.cpp +++ b/plugins/Cardinal/Window.cpp @@ -363,7 +363,7 @@ bool& Window::fbDirtyOnSubpixelChange() { } -void mouseButtonCallback(Window* win, int button, int action, int mods) { +void mouseButtonCallback(Context* ctx, int button, int action, int mods) { /* #if defined ARCH_MAC // Remap Ctrl-left click to right click on Mac @@ -379,29 +379,35 @@ void mouseButtonCallback(Window* win, int button, int action, int mods) { #endif */ - APP->event->handleButton(win->internal->lastMousePos, button, action, mods); + ctx->event->handleButton(ctx->window->internal->lastMousePos, button, action, mods); } -void cursorPosCallback(Window* win, double xpos, double ypos) { - math::Vec mousePos = math::Vec(xpos, ypos).div(win->pixelRatio / win->windowRatio).round(); - math::Vec mouseDelta = mousePos.minus(win->internal->lastMousePos); +void cursorPosCallback(Context* ctx, double xpos, double ypos) { + math::Vec mousePos = math::Vec(xpos, ypos).div(ctx->window->pixelRatio / ctx->window->windowRatio).round(); + math::Vec mouseDelta = mousePos.minus(ctx->window->internal->lastMousePos); // Workaround for GLFW warping mouse to a different position when the cursor is locked or unlocked. - if (win->internal->ignoreNextMouseDelta) { - win->internal->ignoreNextMouseDelta = false; + if (ctx->window->internal->ignoreNextMouseDelta) { + ctx->window->internal->ignoreNextMouseDelta = false; mouseDelta = math::Vec(); } - win->internal->lastMousePos = mousePos; + ctx->window->internal->lastMousePos = mousePos; - APP->event->handleHover(mousePos, mouseDelta); + ctx->event->handleHover(mousePos, mouseDelta); // Keyboard/mouse MIDI driver - math::Vec scaledPos(xpos / win->internal->ui->getWidth(), ypos / win->internal->ui->getHeight()); + math::Vec scaledPos(xpos / ctx->window->internal->ui->getWidth(), ypos / ctx->window->internal->ui->getHeight()); keyboard::mouseMove(scaledPos); } -void scrollCallback(Window* win, double x, double y) { +void cursorEnterCallback(Context* ctx, int entered) { + if (!entered) { + ctx->event->handleLeave(); + } +} + +void scrollCallback(Context* ctx, double x, double y) { math::Vec scrollDelta = math::Vec(x, y); #if defined ARCH_MAC scrollDelta = scrollDelta.mult(10.0); @@ -409,14 +415,25 @@ void scrollCallback(Window* win, double x, double y) { scrollDelta = scrollDelta.mult(50.0); #endif - APP->event->handleScroll(win->internal->lastMousePos, scrollDelta); + ctx->event->handleScroll(ctx->window->internal->lastMousePos, scrollDelta); } - -void init() { +void charCallback(Context* ctx, unsigned int codepoint) { + if (ctx->event->handleText(ctx->window->internal->lastMousePos, codepoint)) + return; } -void destroy() { +void keyCallback(Context* ctx, int key, int scancode, int action, int mods) { + if (ctx->event->handleKey(ctx->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); + } } diff --git a/plugins/Cardinal/dep.cpp b/plugins/Cardinal/dep.cpp index c020754..34eea80 100644 --- a/plugins/Cardinal/dep.cpp +++ b/plugins/Cardinal/dep.cpp @@ -13,3 +13,13 @@ #define NANOSVG_IMPLEMENTATION #define NANOSVG_ALL_COLOR_KEYWORDS #include + +#include + +namespace rack { +namespace network { + std::string encodeUrl(const std::string&) { return {}; } + json_t* requestJson(Method, const std::string&, json_t*, const CookieMap&) { return nullptr; } + bool requestDownload(const std::string&, const std::string&, float*, const CookieMap&) { return false; } +} +}