Move some code around to help remote tool later

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2022-12-24 21:59:04 +00:00
parent 76cdce063c
commit 058ad891d2
No known key found for this signature in database
GPG key ID: CDBAA37ABC74FBA0
11 changed files with 747 additions and 198 deletions

View file

@ -29,6 +29,12 @@
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
// from PluginContext.hpp // from PluginContext.hpp
#ifndef HEADLESS
START_NAMESPACE_DGL
class NanoTopLevelWidget;
END_NAMESPACE_DGL
#endif
START_NAMESPACE_DISTRHO START_NAMESPACE_DISTRHO
static constexpr const uint32_t kModuleParameters = 24; static constexpr const uint32_t kModuleParameters = 24;
@ -68,6 +74,7 @@ struct CardinalPluginContext : rack::Context {
uint32_t midiEventCount; uint32_t midiEventCount;
Plugin* const plugin; Plugin* const plugin;
#ifndef HEADLESS #ifndef HEADLESS
DGL_NAMESPACE::NanoTopLevelWidget* tlw;
UI* ui; UI* ui;
#endif #endif
CardinalPluginContext(Plugin* const p); CardinalPluginContext(Plugin* const p);

View file

@ -59,6 +59,115 @@
const std::string CARDINAL_VERSION = "22.12"; const std::string CARDINAL_VERSION = "22.12";
START_NAMESPACE_DISTRHO
// -----------------------------------------------------------------------------------------------------------
void handleHostParameterDrag(const CardinalPluginContext* pcontext, uint index, bool started)
{
DISTRHO_SAFE_ASSERT_RETURN(pcontext->ui != nullptr,);
if (started)
{
pcontext->ui->editParameter(index, true);
pcontext->ui->setParameterValue(index, pcontext->parameters[index]);
}
else
{
pcontext->ui->editParameter(index, false);
}
}
// --------------------------------------------------------------------------------------------------------------------
bool CardinalPluginContext::addIdleCallback(IdleCallback* const cb) const
{
if (ui == nullptr)
return false;
ui->addIdleCallback(cb);
return true;
}
void CardinalPluginContext::removeIdleCallback(IdleCallback* const cb) const
{
if (ui == nullptr)
return;
ui->removeIdleCallback(cb);
}
void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message, const uint8_t channel)
{
if (bypassed)
return;
const size_t size = message.bytes.size();
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
DISTRHO_SAFE_ASSERT_RETURN(message.frame >= 0,);
MidiEvent event;
event.frame = message.frame;
switch (message.bytes[0] & 0xF0)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
event.size = 3;
break;
case 0xC0:
case 0xD0:
event.size = 2;
break;
case 0xF0:
switch (message.bytes[0] & 0x0F)
{
case 0x0:
case 0x4:
case 0x5:
case 0x7:
case 0x9:
case 0xD:
// unsupported
return;
case 0x1:
case 0x2:
case 0x3:
case 0xE:
event.size = 3;
break;
case 0x6:
case 0x8:
case 0xA:
case 0xB:
case 0xC:
case 0xF:
event.size = 1;
break;
}
break;
default:
// invalid
return;
}
DISTRHO_SAFE_ASSERT_RETURN(size >= event.size,);
std::memcpy(event.data, message.bytes.data(), event.size);
if (channel != 0 && event.data[0] < 0xF0)
event.data[0] |= channel & 0x0F;
plugin->writeMidiEvent(event);
}
END_NAMESPACE_DISTRHO
// --------------------------------------------------------------------------------------------------------------------
namespace rack { namespace rack {
bool isStandalone() bool isStandalone()
@ -118,6 +227,8 @@ std::string homeDir()
} // namespace rack } // namespace rack
// --------------------------------------------------------------------------------------------------------------------
namespace patchUtils namespace patchUtils
{ {
@ -289,6 +400,8 @@ void openBrowser(const std::string& url)
} }
// --------------------------------------------------------------------------------------------------------------------
void async_dialog_filebrowser(const bool saving, void async_dialog_filebrowser(const bool saving,
const char* const defaultName, const char* const defaultName,
const char* const startDir, const char* const startDir,

View file

@ -430,75 +430,6 @@ struct Initializer
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
void CardinalPluginContext::writeMidiMessage(const rack::midi::Message& message, const uint8_t channel)
{
if (bypassed)
return;
const size_t size = message.bytes.size();
DISTRHO_SAFE_ASSERT_RETURN(size > 0,);
DISTRHO_SAFE_ASSERT_RETURN(message.frame >= 0,);
MidiEvent event;
event.frame = message.frame;
switch (message.bytes[0] & 0xF0)
{
case 0x80:
case 0x90:
case 0xA0:
case 0xB0:
case 0xE0:
event.size = 3;
break;
case 0xC0:
case 0xD0:
event.size = 2;
break;
case 0xF0:
switch (message.bytes[0] & 0x0F)
{
case 0x0:
case 0x4:
case 0x5:
case 0x7:
case 0x9:
case 0xD:
// unsupported
return;
case 0x1:
case 0x2:
case 0x3:
case 0xE:
event.size = 3;
break;
case 0x6:
case 0x8:
case 0xA:
case 0xB:
case 0xC:
case 0xF:
event.size = 1;
break;
}
break;
default:
// invalid
return;
}
DISTRHO_SAFE_ASSERT_RETURN(size >= event.size,);
std::memcpy(event.data, message.bytes.data(), event.size);
if (channel != 0 && event.data[0] < 0xF0)
event.data[0] |= channel & 0x0F;
plugin->writeMidiEvent(event);
}
// -----------------------------------------------------------------------------------------------------------
struct ScopedContext { struct ScopedContext {
ScopedContext(const CardinalBasePlugin* const plugin) ScopedContext(const CardinalBasePlugin* const plugin)
{ {
@ -1393,6 +1324,6 @@ Plugin* createPlugin()
return new CardinalPlugin(); return new CardinalPlugin();
} }
// ----------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
END_NAMESPACE_DISTRHO END_NAMESPACE_DISTRHO

View file

@ -7,8 +7,11 @@
# -------------------------------------------------------------- # --------------------------------------------------------------
# Carla stuff # Carla stuff
CWD = ../../carla/source ifneq ($(STATIC_BUILD),true)
STATIC_PLUGIN_TARGET = true STATIC_PLUGIN_TARGET = true
CWD = ../../carla/source
include $(CWD)/Makefile.deps.mk include $(CWD)/Makefile.deps.mk
CARLA_BUILD_DIR = ../../carla/build CARLA_BUILD_DIR = ../../carla/build
@ -23,7 +26,9 @@ CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/carla_engine_
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/carla_plugin.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/carla_plugin.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/native-plugins.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/native-plugins.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/audio_decoder.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/audio_decoder.a
ifneq ($(WASM),true)
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/jackbridge.min.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/jackbridge.min.a
endif
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/lilv.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/lilv.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/rtmempool.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/rtmempool.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/sfzero.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/sfzero.a
@ -31,10 +36,17 @@ CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/water.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/ysfx.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/ysfx.a
CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/zita-resampler.a CARLA_EXTRA_LIBS += $(CARLA_BUILD_DIR)/modules/$(CARLA_BUILD_TYPE)/zita-resampler.a
endif # STATIC_BUILD
# -------------------------------------------------------------- # --------------------------------------------------------------
# Import base definitions # Import base definitions
DISTRHO_NAMESPACE = CardinalDISTRHO
DGL_NAMESPACE = CardinalDGL
NVG_DISABLE_SKIPPING_WHITESPACE = true
NVG_FONT_TEXTURE_FLAGS = NVG_IMAGE_NEAREST
USE_NANOVG_FBO = true USE_NANOVG_FBO = true
WASM_EXCEPTIONS = true
include ../../dpf/Makefile.base.mk include ../../dpf/Makefile.base.mk
# -------------------------------------------------------------- # --------------------------------------------------------------
@ -57,7 +69,11 @@ endif
# -------------------------------------------------------------- # --------------------------------------------------------------
# Extra libraries to link against # Extra libraries to link against
ifeq ($(NOPLUGINS),true)
RACK_EXTRA_LIBS = ../../plugins/noplugins.a
else
RACK_EXTRA_LIBS = ../../plugins/plugins.a RACK_EXTRA_LIBS = ../../plugins/plugins.a
endif
RACK_EXTRA_LIBS += ../rack.a RACK_EXTRA_LIBS += ../rack.a
RACK_EXTRA_LIBS += $(DEP_LIB_PATH)/libquickjs.a RACK_EXTRA_LIBS += $(DEP_LIB_PATH)/libquickjs.a
@ -74,22 +90,51 @@ RACK_EXTRA_LIBS += $(DEP_LIB_PATH)/libzstd.a
endif endif
# -------------------------------------------------------------- # --------------------------------------------------------------
# surgext libraries
ifneq ($(NOPLUGINS),true)
SURGE_DEP_PATH = $(abspath ../../deps/surge-build)
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/src/common/libsurge-common.a
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/src/common/libjuce_dsp_rack_sub.a
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/airwindows/libairwindows.a
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/eurorack/libeurorack.a
ifeq ($(DEBUG),true)
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/fmt/libfmtd.a
else
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/fmt/libfmt.a
endif
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/sqlite-3.23.3/libsqlite.a
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/sst/sst-plugininfra/libsst-plugininfra.a
ifneq ($(WINDOWS),true)
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/sst/sst-plugininfra/libs/filesystem/libfilesystem.a
endif
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/sst/sst-plugininfra/libs/strnatcmp/libstrnatcmp.a
RACK_EXTRA_LIBS += $(SURGE_DEP_PATH)/libs/sst/sst-plugininfra/libs/tinyxml/libtinyxml.a
endif
# --------------------------------------------------------------
# FIXME
ifeq ($(CIBUILD)$(WASM),truetrue)
ifneq ($(STATIC_BUILD),true)
STATIC_CARLA_PLUGIN_LIBS = -lsndfile -lopus -lFLAC -lvorbisenc -lvorbis -logg -lm
endif
endif
EXTRA_DEPENDENCIES = $(RACK_EXTRA_LIBS) $(CARLA_EXTRA_LIBS) EXTRA_DEPENDENCIES = $(RACK_EXTRA_LIBS) $(CARLA_EXTRA_LIBS)
EXTRA_LIBS = $(RACK_EXTRA_LIBS) $(CARLA_EXTRA_LIBS) $(STATIC_CARLA_PLUGIN_LIBS) EXTRA_LIBS = $(RACK_EXTRA_LIBS) $(CARLA_EXTRA_LIBS) $(STATIC_CARLA_PLUGIN_LIBS)
ifeq ($(shell pkg-config --exists fftw3f && echo true),true) ifeq ($(shell $(PKG_CONFIG) --exists fftw3f && echo true),true)
EXTRA_DEPENDENCIES += ../../deps/aubio/libaubio.a EXTRA_DEPENDENCIES += ../../deps/aubio/libaubio.a
EXTRA_LIBS += ../../deps/aubio/libaubio.a EXTRA_LIBS += ../../deps/aubio/libaubio.a
EXTRA_LIBS += $(shell $(PKG_CONFIG) --libs fftw3f) EXTRA_LIBS += $(shell $(PKG_CONFIG) --libs fftw3f)
endif endif
# -------------------------------------------------------------- ifneq ($(NOPLUGINS),true)
# Extra flags for liblo ifeq ($(MACOS),true)
EXTRA_LIBS += -framework Accelerate
BASE_FLAGS += -DHAVE_LIBLO endif
BASE_FLAGS += $(LIBLO_FLAGS) endif
LINK_FLAGS += $(LIBLO_LIBS)
# -------------------------------------------------------------- # --------------------------------------------------------------
# Extra flags for VCV stuff # Extra flags for VCV stuff
@ -106,11 +151,11 @@ BASE_FLAGS += -DPRIVATE=
BASE_FLAGS += -I.. BASE_FLAGS += -I..
BASE_FLAGS += -I../../dpf/dgl/src/nanovg BASE_FLAGS += -I../../dpf/dgl/src/nanovg
BASE_FLAGS += -I../../include BASE_FLAGS += -I../../include
BASE_FLAGS += -I../../include/neon-compat BASE_FLAGS += -I../../include/simd-compat
BASE_FLAGS += -I../Rack/include BASE_FLAGS += -I../Rack/include
ifeq ($(SYSDEPS),true) ifeq ($(SYSDEPS),true)
BASE_FLAGS += -DCARDINAL_SYSDEPS BASE_FLAGS += -DCARDINAL_SYSDEPS
BASE_FLAGS += $(shell pkg-config --cflags jansson libarchive samplerate speexdsp) BASE_FLAGS += $(shell $(PKG_CONFIG) --cflags jansson libarchive samplerate speexdsp)
else else
BASE_FLAGS += -DZSTDLIB_VISIBILITY= BASE_FLAGS += -DZSTDLIB_VISIBILITY=
BASE_FLAGS += -I../Rack/dep/include BASE_FLAGS += -I../Rack/dep/include
@ -119,41 +164,98 @@ BASE_FLAGS += -I../Rack/dep/glfw/include
BASE_FLAGS += -I../Rack/dep/nanosvg/src BASE_FLAGS += -I../Rack/dep/nanosvg/src
BASE_FLAGS += -I../Rack/dep/oui-blendish BASE_FLAGS += -I../Rack/dep/oui-blendish
ifeq ($(WASM),true) ifeq ($(HEADLESS),true)
BASE_FLAGS += -DNANOVG_GLES2=1 BASE_FLAGS += -DHEADLESS
BASE_FLAGS += -msse -msse2 -msse3 -msimd128 endif
else ifneq ($(HAIKU),true)
ifeq ($(MOD_BUILD),true)
BASE_FLAGS += -DDISTRHO_PLUGIN_USES_MODGUI=1 -DDISTRHO_PLUGIN_MINIMUM_BUFFER_SIZE=0xffff
endif
ifneq ($(WASM),true)
ifneq ($(HAIKU),true)
BASE_FLAGS += -pthread BASE_FLAGS += -pthread
endif endif
endif
ifeq ($(WINDOWS),true) ifeq ($(WINDOWS),true)
BASE_FLAGS += -D_USE_MATH_DEFINES BASE_FLAGS += -D_USE_MATH_DEFINES
BASE_FLAGS += -DWIN32_LEAN_AND_MEAN BASE_FLAGS += -DWIN32_LEAN_AND_MEAN
BASE_FLAGS += -D_WIN32_WINNT=0x0600
BASE_FLAGS += -I../../include/mingw-compat BASE_FLAGS += -I../../include/mingw-compat
BASE_FLAGS += -I../../include/mingw-std-threads BASE_FLAGS += -I../../include/mingw-std-threads
endif endif
ifeq ($(USE_GLES2),true)
BASE_FLAGS += -DNANOVG_GLES2_FORCED
else ifeq ($(USE_GLES3),true)
BASE_FLAGS += -DNANOVG_GLES3_FORCED
endif
BUILD_C_FLAGS += -std=gnu11 BUILD_C_FLAGS += -std=gnu11
BUILD_C_FLAGS += -fno-finite-math-only -fno-strict-aliasing BUILD_C_FLAGS += -fno-finite-math-only -fno-strict-aliasing
BUILD_CXX_FLAGS += -fno-finite-math-only -fno-strict-aliasing BUILD_CXX_FLAGS += -fno-finite-math-only -fno-strict-aliasing
ifneq ($(MACOS),true) ifneq ($(MACOS),true)
BUILD_CXX_FLAGS += -faligned-new -Wno-abi BUILD_CXX_FLAGS += -faligned-new -Wno-abi
ifeq ($(MOD_BUILD),true)
BUILD_CXX_FLAGS += -std=gnu++17
endif
endif endif
# Rack code is not tested for this flag, unset it # Rack code is not tested for this flag, unset it
BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS BUILD_CXX_FLAGS += -U_GLIBCXX_ASSERTIONS -Wp,-U_GLIBCXX_ASSERTIONS
# Ignore bad behaviour from Rack API
BUILD_CXX_FLAGS += -Wno-format-security
# -------------------------------------------------------------- # --------------------------------------------------------------
# FIXME lots of warnings from VCV side # FIXME lots of warnings from VCV side
BASE_FLAGS += -Wno-unused-parameter BASE_FLAGS += -Wno-unused-parameter
BASE_FLAGS += -Wno-unused-variable BASE_FLAGS += -Wno-unused-variable
# -------------------------------------------------------------- ifeq ($(WASM),true)
# extra linker flags ifneq ($(STATIC_BUILD),true)
LINK_FLAGS += --use-preload-plugins
ifeq ($(HAIKU),true) LINK_FLAGS += --preload-file=./jsfx
LINK_FLAGS += --preload-file=./lv2
endif
LINK_FLAGS += --preload-file=../../bin/CardinalNative.lv2/resources@/resources
LINK_FLAGS += --use-preload-cache
ifneq ($(NOPLUGINS),true)
SYMLINKED_DIRS_RESOURCES =
# find . -type l | grep -v svg | grep -v ttf | grep -v art | grep -v json | grep -v png | grep -v otf | sort
SYMLINKED_DIRS_RESOURCES += BaconPlugs/res/midi/chopin
SYMLINKED_DIRS_RESOURCES += BaconPlugs/res/midi/debussy
SYMLINKED_DIRS_RESOURCES += BaconPlugs/res/midi/goldberg
SYMLINKED_DIRS_RESOURCES += cf/playeroscs
SYMLINKED_DIRS_RESOURCES += DrumKit/res/samples
SYMLINKED_DIRS_RESOURCES += Fundamental/presets
SYMLINKED_DIRS_RESOURCES += GrandeModular/presets
SYMLINKED_DIRS_RESOURCES += LyraeModules/presets
SYMLINKED_DIRS_RESOURCES += Meander/res
SYMLINKED_DIRS_RESOURCES += MindMeldModular/presets
SYMLINKED_DIRS_RESOURCES += MindMeldModular/res/ShapeMaster/CommunityPresets
SYMLINKED_DIRS_RESOURCES += MindMeldModular/res/ShapeMaster/CommunityShapes
SYMLINKED_DIRS_RESOURCES += MindMeldModular/res/ShapeMaster/MindMeldPresets
SYMLINKED_DIRS_RESOURCES += MindMeldModular/res/ShapeMaster/MindMeldShapes
SYMLINKED_DIRS_RESOURCES += Mog/res
SYMLINKED_DIRS_RESOURCES += nonlinearcircuits/res
SYMLINKED_DIRS_RESOURCES += Orbits/presets
SYMLINKED_DIRS_RESOURCES += stoermelder-packone/presets
SYMLINKED_DIRS_RESOURCES += surgext/build/surge-data/fx_presets
SYMLINKED_DIRS_RESOURCES += surgext/build/surge-data/wavetables
SYMLINKED_DIRS_RESOURCES += surgext/patches
SYMLINKED_DIRS_RESOURCES += surgext/presets
LINK_FLAGS += $(foreach d,$(SYMLINKED_DIRS_RESOURCES),--preload-file=../../bin/CardinalNative.lv2/resources/$(d)@/resources/$(d))
endif
LINK_FLAGS += -sALLOW_MEMORY_GROWTH
LINK_FLAGS += -sINITIAL_MEMORY=64Mb
LINK_FLAGS += -sLZ4=1
LINK_FLAGS += --shell-file=../emscripten/shell.html
LINK_FLAGS += -O3
else ifeq ($(HAIKU),true)
LINK_FLAGS += -lpthread LINK_FLAGS += -lpthread
else else
LINK_FLAGS += -pthread LINK_FLAGS += -pthread
@ -181,7 +283,7 @@ EXTRA_LIBS += -lws2_32 -lwinmm
endif endif
ifeq ($(SYSDEPS),true) ifeq ($(SYSDEPS),true)
EXTRA_LIBS += $(shell pkg-config --libs jansson libarchive samplerate speexdsp) EXTRA_LIBS += $(shell $(PKG_CONFIG) --libs jansson libarchive samplerate speexdsp)
endif endif
ifeq ($(WITH_LTO),true) ifeq ($(WITH_LTO),true)
@ -193,6 +295,13 @@ LINK_FLAGS += -Wno-stringop-overflow
endif endif
endif endif
# --------------------------------------------------------------
# Extra flags for liblo
BASE_FLAGS += -DHAVE_LIBLO
BASE_FLAGS += $(LIBLO_FLAGS)
LINK_FLAGS += $(LIBLO_LIBS)
# -------------------------------------------------------------- # --------------------------------------------------------------
# fallback path to resource files # fallback path to resource files

View file

@ -17,7 +17,7 @@
#include "RemoteUI.hpp" #include "RemoteUI.hpp"
// #include <asset.hpp> #include <asset.hpp>
// #include <random.hpp> // #include <random.hpp>
#include <patch.hpp> #include <patch.hpp>
#include <settings.hpp> #include <settings.hpp>
@ -26,66 +26,293 @@
#include <app/Scene.hpp> #include <app/Scene.hpp>
#include <engine/Engine.hpp> #include <engine/Engine.hpp>
#include "AsyncDialog.hpp"
#include "WindowParameters.hpp"
// --------------------------------------------------------------------------------------------------------------------
namespace rack {
namespace app {
widget::Widget* createMenuBar(bool isStandalone);
}
namespace window {
void WindowSetPluginRemote(Window* window, NanoTopLevelWidget* tlw);
void WindowSetMods(Window* window, int mods);
void WindowSetInternalSize(rack::window::Window* window, math::Vec size);
}
}
// --------------------------------------------------------------------------------------------------------------------
CardinalRemoteUI::CardinalRemoteUI(Window& window, const std::string& templatePath) CardinalRemoteUI::CardinalRemoteUI(Window& window, const std::string& templatePath)
: NanoTopLevelWidget(window), : NanoTopLevelWidget(window)
context(nullptr)
{ {
// create unique temporary path for this instance CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet()));
try {
char uidBuf[24];
const std::string tmp = rack::system::getTempDirectory();
for (int i=1;; ++i)
{
std::snprintf(uidBuf, sizeof(uidBuf), "CardinalRemote.%04d", i);
const std::string trypath = rack::system::join(tmp, uidBuf);
if (! rack::system::exists(trypath))
{
if (rack::system::createDirectories(trypath))
autosavePath = trypath;
break;
}
}
} DISTRHO_SAFE_EXCEPTION("create unique temporary path");
rack::contextSet(&context);
context.bufferSize = 512;
rack::settings::sampleRate = context.sampleRate = 48000;
context.engine = new rack::engine::Engine;
context.engine->setSampleRate(context.sampleRate);
context.history = new rack::history::State;
context.patch = new rack::patch::Manager;
context.patch->autosavePath = autosavePath;
context.patch->templatePath = templatePath;
context.event = new rack::widget::EventState;
context.scene = new rack::app::Scene;
context.event->rootWidget = context.scene;
context.window = new rack::window::Window;
context.patch->loadTemplate();
context.scene->rackScroll->reset();
context.nativeWindowId = getWindow().getNativeWindowHandle(); context.nativeWindowId = getWindow().getNativeWindowHandle();
context.tlw = this;
window.setIgnoringKeyRepeat(true);
context.nativeWindowId = window.getNativeWindowHandle();
const double scaleFactor = getScaleFactor();
setGeometryConstraints(648 * scaleFactor, 538 * scaleFactor);
if (scaleFactor != 1.0)
setSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor);
rack::window::WindowSetPluginRemote(context.window, this);
if (rack::widget::Widget* const menuBar = context.scene->menuBar)
{
context.scene->removeChild(menuBar);
delete menuBar;
}
context.scene->menuBar = rack::app::createMenuBar(true);
context.scene->addChildBelow(context.scene->menuBar, context.scene->rackScroll);
// hide "Browse VCV Library" button
rack::widget::Widget* const browser = context.scene->browser->children.back();
rack::widget::Widget* const headerLayout = browser->children.front();
rack::widget::Widget* const libraryButton = headerLayout->children.back();
libraryButton->hide();
// Report to user if something is wrong with the installation
std::string errorMessage;
if (rack::asset::systemDir.empty())
{
errorMessage = "Failed to locate Cardinal plugin bundle.\n"
"Install Cardinal with its plugin bundle folder intact and try again.";
}
else if (! rack::system::exists(rack::asset::systemDir))
{
errorMessage = rack::string::f("System directory \"%s\" does not exist. "
"Make sure Cardinal was downloaded and installed correctly.",
rack::asset::systemDir.c_str());
}
if (! errorMessage.empty())
{
static bool shown = false;
if (! shown)
{
shown = true;
asyncDialog::create(errorMessage.c_str());
}
}
context.window->step();
// WindowParametersSetCallback(context.window, this);
} }
CardinalRemoteUI::~CardinalRemoteUI() CardinalRemoteUI::~CardinalRemoteUI()
{ {
rack::contextSet(&context); CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet()));
context.nativeWindowId = 0; context.nativeWindowId = 0;
context.patch->clear();
if (! autosavePath.empty())
rack::system::removeRecursively(autosavePath);
} }
void CardinalRemoteUI::onNanoDisplay() void CardinalRemoteUI::onNanoDisplay()
{ {
rack::contextSet(&context); CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet()));
context.window->step(); context.window->step();
// TODO
repaint();
} }
// --------------------------------------------------------------------------------------------------------------------
static int glfwMods(const uint mod) noexcept
{
int mods = 0;
if (mod & kModifierControl)
mods |= GLFW_MOD_CONTROL;
if (mod & kModifierShift)
mods |= GLFW_MOD_SHIFT;
if (mod & kModifierAlt)
mods |= GLFW_MOD_ALT;
if (mod & kModifierSuper)
mods |= GLFW_MOD_SUPER;
/*
if (glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS)
mods |= GLFW_MOD_SHIFT;
if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS)
mods |= GLFW_MOD_CONTROL;
if (glfwGetKey(win, GLFW_KEY_LEFT_ALT) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_ALT) == GLFW_PRESS)
mods |= GLFW_MOD_ALT;
if (glfwGetKey(win, GLFW_KEY_LEFT_SUPER) == GLFW_PRESS || glfwGetKey(win, GLFW_KEY_RIGHT_SUPER) == GLFW_PRESS)
mods |= GLFW_MOD_SUPER;
*/
return mods;
}
bool CardinalRemoteUI::onMouse(const MouseEvent& ev)
{
if (ev.press)
getWindow().focus();
const int action = ev.press ? GLFW_PRESS : GLFW_RELEASE;
int mods = glfwMods(ev.mod);
int button;
switch (ev.button)
{
case 1: button = GLFW_MOUSE_BUTTON_LEFT; break;
case 2: button = GLFW_MOUSE_BUTTON_RIGHT; break;
case 3: button = GLFW_MOUSE_BUTTON_MIDDLE; break;
default:
button = ev.button;
break;
}
#ifdef DISTRHO_OS_MAC
// Remap Ctrl-left click to right click on macOS
if (button == GLFW_MOUSE_BUTTON_LEFT && (mods & RACK_MOD_MASK) == GLFW_MOD_CONTROL) {
button = GLFW_MOUSE_BUTTON_RIGHT;
mods &= ~GLFW_MOD_CONTROL;
}
// Remap Ctrl-shift-left click to middle click on macOS
if (button == GLFW_MOUSE_BUTTON_LEFT && (mods & RACK_MOD_MASK) == (GLFW_MOD_CONTROL | GLFW_MOD_SHIFT)) {
button = GLFW_MOUSE_BUTTON_MIDDLE;
mods &= ~(GLFW_MOD_CONTROL | GLFW_MOD_SHIFT);
}
#endif
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
return context->event->handleButton(lastMousePos, button, action, mods);
}
bool CardinalRemoteUI::onMotion(const MotionEvent& ev)
{
const rack::math::Vec mousePos = rack::math::Vec(ev.pos.getX(), ev.pos.getY()).div(getScaleFactor()).round();
const rack::math::Vec mouseDelta = mousePos.minus(lastMousePos);
lastMousePos = mousePos;
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
return context->event->handleHover(mousePos, mouseDelta);
}
bool CardinalRemoteUI::onScroll(const ScrollEvent& ev)
{
rack::math::Vec scrollDelta = rack::math::Vec(ev.delta.getX(), ev.delta.getY());
#ifndef DISTRHO_OS_MAC
scrollDelta = scrollDelta.mult(50.0);
#endif
const int mods = glfwMods(ev.mod);
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
return context->event->handleScroll(lastMousePos, scrollDelta);
}
bool CardinalRemoteUI::onCharacterInput(const CharacterInputEvent& ev)
{
if (ev.character < ' ' || ev.character >= kKeyDelete)
return false;
const int mods = glfwMods(ev.mod);
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
return context->event->handleText(lastMousePos, ev.character);
}
bool CardinalRemoteUI::onKeyboard(const KeyboardEvent& ev)
{
const int action = ev.press ? GLFW_PRESS : GLFW_RELEASE;
const int mods = glfwMods(ev.mod);
/* These are unsupported in pugl right now
#define GLFW_KEY_KP_0 320
#define GLFW_KEY_KP_1 321
#define GLFW_KEY_KP_2 322
#define GLFW_KEY_KP_3 323
#define GLFW_KEY_KP_4 324
#define GLFW_KEY_KP_5 325
#define GLFW_KEY_KP_6 326
#define GLFW_KEY_KP_7 327
#define GLFW_KEY_KP_8 328
#define GLFW_KEY_KP_9 329
#define GLFW_KEY_KP_DECIMAL 330
#define GLFW_KEY_KP_DIVIDE 331
#define GLFW_KEY_KP_MULTIPLY 332
#define GLFW_KEY_KP_SUBTRACT 333
#define GLFW_KEY_KP_ADD 334
#define GLFW_KEY_KP_ENTER 335
#define GLFW_KEY_KP_EQUAL 336
*/
int key;
switch (ev.key)
{
case '\r': key = GLFW_KEY_ENTER; break;
case '\t': key = GLFW_KEY_TAB; break;
case kKeyBackspace: key = GLFW_KEY_BACKSPACE; break;
case kKeyEscape: key = GLFW_KEY_ESCAPE; break;
case kKeyDelete: key = GLFW_KEY_DELETE; break;
case kKeyF1: key = GLFW_KEY_F1; break;
case kKeyF2: key = GLFW_KEY_F2; break;
case kKeyF3: key = GLFW_KEY_F3; break;
case kKeyF4: key = GLFW_KEY_F4; break;
case kKeyF5: key = GLFW_KEY_F5; break;
case kKeyF6: key = GLFW_KEY_F6; break;
case kKeyF7: key = GLFW_KEY_F7; break;
case kKeyF8: key = GLFW_KEY_F8; break;
case kKeyF9: key = GLFW_KEY_F9; break;
case kKeyF10: key = GLFW_KEY_F10; break;
case kKeyF11: key = GLFW_KEY_F11; break;
case kKeyF12: key = GLFW_KEY_F12; break;
case kKeyLeft: key = GLFW_KEY_LEFT; break;
case kKeyUp: key = GLFW_KEY_UP; break;
case kKeyRight: key = GLFW_KEY_RIGHT; break;
case kKeyDown: key = GLFW_KEY_DOWN; break;
case kKeyPageUp: key = GLFW_KEY_PAGE_UP; break;
case kKeyPageDown: key = GLFW_KEY_PAGE_DOWN; break;
case kKeyHome: key = GLFW_KEY_HOME; break;
case kKeyEnd: key = GLFW_KEY_END; break;
case kKeyInsert: key = GLFW_KEY_INSERT; break;
case kKeyShiftL: key = GLFW_KEY_LEFT_SHIFT; break;
case kKeyShiftR: key = GLFW_KEY_RIGHT_SHIFT; break;
case kKeyControlL: key = GLFW_KEY_LEFT_CONTROL; break;
case kKeyControlR: key = GLFW_KEY_RIGHT_CONTROL; break;
case kKeyAltL: key = GLFW_KEY_LEFT_ALT; break;
case kKeyAltR: key = GLFW_KEY_RIGHT_ALT; break;
case kKeySuperL: key = GLFW_KEY_LEFT_SUPER; break;
case kKeySuperR: key = GLFW_KEY_RIGHT_SUPER; break;
case kKeyMenu: key = GLFW_KEY_MENU; break;
case kKeyCapsLock: key = GLFW_KEY_CAPS_LOCK; break;
case kKeyScrollLock: key = GLFW_KEY_SCROLL_LOCK; break;
case kKeyNumLock: key = GLFW_KEY_NUM_LOCK; break;
case kKeyPrintScreen: key = GLFW_KEY_PRINT_SCREEN; break;
case kKeyPause: key = GLFW_KEY_PAUSE; break;
default:
// glfw expects uppercase
if (ev.key >= 'a' && ev.key <= 'z')
key = ev.key - ('a' - 'A');
else
key = ev.key;
break;
}
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
return context->event->handleKey(lastMousePos, key, ev.keycode, action, mods);
}
void CardinalRemoteUI::onResize(const ResizeEvent& ev)
{
NanoTopLevelWidget::onResize(ev);
CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet());
if (context->window != nullptr)
WindowSetInternalSize(context->window, rack::math::Vec(ev.size.getWidth(), ev.size.getHeight()));
}
// --------------------------------------------------------------------------------------------------------------------

View file

@ -20,10 +20,11 @@
#include "NanoVG.hpp" #include "NanoVG.hpp"
#include "PluginContext.hpp" #include "PluginContext.hpp"
#include <app/common.hpp>
class CardinalRemoteUI : public NanoTopLevelWidget class CardinalRemoteUI : public NanoTopLevelWidget
{ {
CardinalPluginContext context; rack::math::Vec lastMousePos;
std::string autosavePath;
public: public:
explicit CardinalRemoteUI(Window& window, const std::string& templatePath); explicit CardinalRemoteUI(Window& window, const std::string& templatePath);
@ -31,6 +32,12 @@ public:
protected: protected:
void onNanoDisplay() override; void onNanoDisplay() override;
bool onMouse(const MouseEvent& ev) override;
bool onMotion(const MotionEvent& ev) override;
bool onScroll(const ScrollEvent& ev) override;
bool onCharacterInput(const CharacterInputEvent& ev) override;
bool onKeyboard(const KeyboardEvent& ev) override;
void onResize(const ResizeEvent& ev) override;
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CardinalRemoteUI) DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CardinalRemoteUI)
}; };

View file

@ -20,13 +20,19 @@
#include "RemoteUI.hpp" #include "RemoteUI.hpp"
#include <asset.hpp> #include <asset.hpp>
#include <patch.hpp>
#include <random.hpp> #include <random.hpp>
#include <settings.hpp> #include <settings.hpp>
#include <system.hpp> #include <system.hpp>
#include <app/Browser.hpp> #include <app/Browser.hpp>
#include <app/Scene.hpp>
#include <engine/Engine.hpp>
#include <ui/common.hpp> #include <ui/common.hpp>
#include "PluginContext.hpp"
namespace rack { namespace rack {
namespace plugin { namespace plugin {
void initStaticPlugins(); void initStaticPlugins();
@ -34,6 +40,26 @@ namespace plugin {
} }
} }
START_NAMESPACE_DISTRHO
bool isUsingNativeAudio() noexcept { return false; }
bool supportsAudioInput() { return false; }
bool supportsBufferSizeChanges() { return false; }
bool supportsMIDI() { return false; }
bool isAudioInputEnabled() { return false; }
bool isMIDIEnabled() { return false; }
uint getBufferSize() { return 0; }
bool requestAudioInput() { return false; }
bool requestBufferSizeChange(uint) { return false; }
bool requestMIDI() { return false; }
const char* getPluginFormatName() noexcept { return "Remote"; }
uint32_t Plugin::getBufferSize() const noexcept { return 128; }
double Plugin::getSampleRate() const noexcept { return 48000; }
bool Plugin::writeMidiEvent(const MidiEvent&) noexcept { return false; }
END_NAMESPACE_DISTRHO
int main(const int argc, const char* argv[]) int main(const int argc, const char* argv[])
{ {
using namespace rack; using namespace rack;
@ -42,7 +68,6 @@ int main(const int argc, const char* argv[])
settings::autoCheckUpdates = false; settings::autoCheckUpdates = false;
settings::autosaveInterval = 0; settings::autosaveInterval = 0;
settings::devMode = true; settings::devMode = true;
settings::discordUpdateActivity = false;
settings::isPlugin = true; settings::isPlugin = true;
settings::skipLoadOnLaunch = true; settings::skipLoadOnLaunch = true;
settings::showTipsOnLaunch = false; settings::showTipsOnLaunch = false;
@ -131,17 +156,68 @@ int main(const int argc, const char* argv[])
INFO("Initializing plugin browser DB"); INFO("Initializing plugin browser DB");
app::browserInit(); app::browserInit();
// create unique temporary path for this instance
std::string autosavePath;
try {
char uidBuf[24];
const std::string tmp = rack::system::getTempDirectory();
for (int i=1;; ++i)
{
std::snprintf(uidBuf, sizeof(uidBuf), "CardinalRemote.%04d", i);
const std::string trypath = rack::system::join(tmp, uidBuf);
if (! rack::system::exists(trypath))
{
if (rack::system::createDirectories(trypath))
autosavePath = trypath;
break;
}
}
} DISTRHO_SAFE_EXCEPTION("create unique temporary path");
CardinalPluginContext context(nullptr);
rack::contextSet(&context);
context.bufferSize = 512;
rack::settings::sampleRate = context.sampleRate = 48000;
context.engine = new rack::engine::Engine;
context.engine->setSampleRate(context.sampleRate);
context.history = new rack::history::State;
context.patch = new rack::patch::Manager;
context.patch->autosavePath = autosavePath;
context.patch->templatePath = templatePath;
context.event = new rack::widget::EventState;
context.scene = new rack::app::Scene;
context.event->rootWidget = context.scene;
context.window = new rack::window::Window;
context.patch->loadTemplate();
context.scene->rackScroll->reset();
Application app; Application app;
Window win(app); Window win(app);
win.setResizable(true);
win.setTitle("CardinalRemote"); win.setTitle("CardinalRemote");
ScopedPointer<CardinalRemoteUI> remoteUI; ScopedPointer<CardinalRemoteUI> remoteUI;
{ {
const Window::ScopedGraphicsContext sgc(win);
remoteUI = new CardinalRemoteUI(win, templatePath); remoteUI = new CardinalRemoteUI(win, templatePath);
} }
win.show();
app.exec(); app.exec();
context.patch->clear();
if (! autosavePath.empty())
rack::system::removeRecursively(autosavePath);
INFO("Clearing asset paths"); INFO("Clearing asset paths");
asset::bundlePath.clear(); asset::bundlePath.clear();
asset::systemDir.clear(); asset::systemDir.clear();

View file

@ -67,40 +67,6 @@ START_NAMESPACE_DISTRHO
// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------
bool CardinalPluginContext::addIdleCallback(IdleCallback* const cb) const
{
if (ui == nullptr)
return false;
ui->addIdleCallback(cb);
return true;
}
void CardinalPluginContext::removeIdleCallback(IdleCallback* const cb) const
{
if (ui == nullptr)
return;
ui->removeIdleCallback(cb);
}
void handleHostParameterDrag(const CardinalPluginContext* pcontext, uint index, bool started)
{
DISTRHO_SAFE_ASSERT_RETURN(pcontext->ui != nullptr,);
if (started)
{
pcontext->ui->editParameter(index, true);
pcontext->ui->setParameterValue(index, pcontext->parameters[index]);
}
else
{
pcontext->ui->editParameter(index, false);
}
}
// -----------------------------------------------------------------------------------------------------------
#ifdef DISTRHO_OS_WASM #ifdef DISTRHO_OS_WASM
struct WasmWelcomeDialog : rack::widget::OpaqueWidget struct WasmWelcomeDialog : rack::widget::OpaqueWidget
{ {

View file

@ -64,13 +64,14 @@ struct CardinalPluginContext : rack::Context {
uint32_t midiEventCount; uint32_t midiEventCount;
Plugin* const plugin; Plugin* const plugin;
#ifndef HEADLESS #ifndef HEADLESS
NanoTopLevelWidget* tlw;
UI* ui; UI* ui;
#endif #endif
CardinalPluginContext(Plugin* const p) CardinalPluginContext(Plugin* const p)
: bufferSize(p->getBufferSize()), : bufferSize(p != nullptr ? p->getBufferSize() : 0),
processCounter(0), processCounter(0),
sampleRate(p->getSampleRate()), sampleRate(p != nullptr ? p->getSampleRate() : 0.0),
#if CARDINAL_VARIANT_MAIN #if CARDINAL_VARIANT_MAIN
variant(kCardinalVariantMain), variant(kCardinalVariantMain),
#elif CARDINAL_VARIANT_FX #elif CARDINAL_VARIANT_FX
@ -105,6 +106,7 @@ struct CardinalPluginContext : rack::Context {
midiEventCount(0), midiEventCount(0),
plugin(p) plugin(p)
#ifndef HEADLESS #ifndef HEADLESS
, tlw(nullptr)
, ui(nullptr) , ui(nullptr)
#endif #endif
{ {
@ -169,6 +171,7 @@ public:
filebrowseraction(), filebrowseraction(),
filebrowserhandle(nullptr) filebrowserhandle(nullptr)
{ {
context->tlw = this;
context->ui = this; context->ui = this;
} }
@ -177,6 +180,7 @@ public:
if (filebrowserhandle != nullptr) if (filebrowserhandle != nullptr)
fileBrowserClose(filebrowserhandle); fileBrowserClose(filebrowserhandle);
context->tlw = nullptr;
context->ui = nullptr; context->ui = nullptr;
} }
}; };

View file

@ -30,10 +30,10 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow*)
{ {
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, nullptr); DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, nullptr);
DISTRHO_SAFE_ASSERT_RETURN(context->ui != nullptr, nullptr); DISTRHO_SAFE_ASSERT_RETURN(context->tlw != nullptr, nullptr);
size_t dataSize; size_t dataSize;
return static_cast<const char*>(context->ui->getClipboard(dataSize)); return static_cast<const char*>(context->tlw->getClipboard(dataSize));
} }
GLFWAPI void glfwSetClipboardString(GLFWwindow*, const char* const text) GLFWAPI void glfwSetClipboardString(GLFWwindow*, const char* const text)
@ -42,9 +42,9 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow*, const char* const text)
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(context->ui != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(context->tlw != nullptr,);
context->ui->setClipboard(nullptr, text, std::strlen(text)+1); context->tlw->setClipboard(nullptr, text, std::strlen(text)+1);
} }
GLFWAPI GLFWcursor* glfwCreateStandardCursor(const int shape) GLFWAPI GLFWcursor* glfwCreateStandardCursor(const int shape)
@ -91,18 +91,18 @@ GLFWAPI void glfwSetCursor(GLFWwindow*, GLFWcursor* const cursor)
{ {
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,);
DISTRHO_SAFE_ASSERT_RETURN(context->ui != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(context->tlw != nullptr,);
context->ui->setCursor(cursor != nullptr ? cursor->cursorId : kMouseCursorArrow); context->tlw->setCursor(cursor != nullptr ? cursor->cursorId : kMouseCursorArrow);
} }
GLFWAPI double glfwGetTime(void) GLFWAPI double glfwGetTime(void)
{ {
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, 0.0); DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, 0.0);
DISTRHO_SAFE_ASSERT_RETURN(context->ui != nullptr, 0.0); DISTRHO_SAFE_ASSERT_RETURN(context->tlw != nullptr, 0.0);
return context->ui->getApp().getTime(); return context->tlw->getApp().getTime();
} }
GLFWAPI const char* glfwGetKeyName(const int key, int) GLFWAPI const char* glfwGetKeyName(const int key, int)

View file

@ -145,6 +145,7 @@ struct Window::Internal {
std::string lastWindowTitle; std::string lastWindowTitle;
DISTRHO_NAMESPACE::UI* ui = nullptr; DISTRHO_NAMESPACE::UI* ui = nullptr;
DGL_NAMESPACE::NanoTopLevelWidget* tlw = nullptr;
DISTRHO_NAMESPACE::WindowParameters params; DISTRHO_NAMESPACE::WindowParameters params;
DISTRHO_NAMESPACE::WindowParametersCallback* callback = nullptr; DISTRHO_NAMESPACE::WindowParametersCallback* callback = nullptr;
DGL_NAMESPACE::Application hiddenApp; DGL_NAMESPACE::Application hiddenApp;
@ -238,6 +239,112 @@ Window::Window() {
#endif #endif
} }
void WindowSetPluginRemote(Window* const window, NanoTopLevelWidget* const tlw)
{
// if nanovg context failed, init only bare minimum
if (window->vg == nullptr)
{
if (tlw != nullptr)
{
window->internal->tlw = tlw;
window->internal->size = rack::math::Vec(tlw->getWidth(), tlw->getHeight());
}
else
{
window->internal->tlw = nullptr;
window->internal->callback = nullptr;
}
return;
}
if (tlw != nullptr)
{
const GLubyte* vendor = glGetString(GL_VENDOR);
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
INFO("Renderer: %s %s", vendor, renderer);
INFO("OpenGL: %s", version);
window->internal->tlw = tlw;
window->internal->size = rack::math::Vec(tlw->getWidth(), tlw->getHeight());
// Set up NanoVG
window->internal->r_vg = tlw->getContext();
#ifdef NANOVG_GLES2
window->internal->r_fbVg = nvgCreateSharedGLES2(window->internal->r_vg, NVG_ANTIALIAS);
#else
window->internal->r_fbVg = nvgCreateSharedGL2(window->internal->r_vg, NVG_ANTIALIAS);
#endif
// swap contexts
window->internal->o_vg = window->vg;
window->internal->o_fbVg = window->fbVg;
window->vg = window->internal->r_vg;
window->fbVg = window->internal->r_fbVg;
// also for fonts and images
window->uiFont->vg = window->vg;
window->uiFont->handle = loadFallbackFont(window->vg);
for (auto& font : window->internal->fontCache)
{
font.second->vg = window->vg;
font.second->ohandle = font.second->handle;
font.second->handle = nvgCreateFont(window->vg,
font.second->ofilename.c_str(), font.second->ofilename.c_str());
}
for (auto& image : window->internal->imageCache)
{
image.second->vg = window->vg;
image.second->ohandle = image.second->handle;
image.second->handle = nvgCreateImage(window->vg, image.second->ofilename.c_str(),
NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY);
}
// Init settings
WindowParametersRestore(window);
widget::Widget::ContextCreateEvent e;
APP->scene->onContextCreate(e);
}
else
{
widget::Widget::ContextDestroyEvent e;
APP->scene->onContextDestroy(e);
// swap contexts
window->uiFont->vg = window->internal->o_vg;
window->vg = window->internal->o_vg;
window->fbVg = window->internal->o_fbVg;
window->internal->o_vg = nullptr;
window->internal->o_fbVg = nullptr;
// also for fonts and images
window->uiFont->vg = window->vg;
window->uiFont->handle = loadFallbackFont(window->vg);
for (auto& font : window->internal->fontCache)
{
font.second->vg = window->vg;
font.second->handle = font.second->ohandle;
font.second->ohandle = -1;
}
for (auto& image : window->internal->imageCache)
{
image.second->vg = window->vg;
image.second->handle = image.second->ohandle;
image.second->ohandle = -1;
}
#if defined NANOVG_GLES2
nvgDeleteGLES2(window->internal->r_fbVg);
#else
nvgDeleteGL2(window->internal->r_fbVg);
#endif
window->internal->tlw = nullptr;
window->internal->callback = nullptr;
}
}
void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui) void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui)
{ {
// if nanovg context failed, init only bare minimum // if nanovg context failed, init only bare minimum
@ -264,6 +371,7 @@ void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui)
INFO("Renderer: %s %s", vendor, renderer); INFO("Renderer: %s %s", vendor, renderer);
INFO("OpenGL: %s", version); INFO("OpenGL: %s", version);
window->internal->tlw = ui;
window->internal->ui = ui; window->internal->ui = ui;
window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight()); window->internal->size = rack::math::Vec(ui->getWidth(), ui->getHeight());
@ -339,6 +447,7 @@ void WindowSetPluginUI(Window* const window, DISTRHO_NAMESPACE::UI* const ui)
nvgDeleteGL2(window->internal->r_fbVg); nvgDeleteGL2(window->internal->r_fbVg);
#endif #endif
window->internal->tlw = nullptr;
window->internal->ui = nullptr; window->internal->ui = nullptr;
window->internal->callback = nullptr; window->internal->callback = nullptr;
} }
@ -384,8 +493,8 @@ void Window::setSize(math::Vec size) {
size = size.max(WINDOW_SIZE_MIN); size = size.max(WINDOW_SIZE_MIN);
internal->size = size; internal->size = size;
if (DISTRHO_NAMESPACE::UI* const ui = internal->ui) if (DGL_NAMESPACE::NanoTopLevelWidget* const tlw = internal->ui)
ui->setSize(internal->size.x, internal->size.y); tlw->setSize(internal->size.x, internal->size.y);
} }
void WindowSetInternalSize(rack::window::Window* const window, math::Vec size) { void WindowSetInternalSize(rack::window::Window* const window, math::Vec size) {
@ -453,7 +562,7 @@ static void Window__writeImagePNG(void* context, void* data, int size) {
void Window::step() { void Window::step() {
DISTRHO_SAFE_ASSERT_RETURN(internal->ui != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(internal->tlw != nullptr,);
if (vg == nullptr) if (vg == nullptr)
return; return;
@ -480,12 +589,12 @@ void Window::step() {
windowTitle += system::getFilename(APP->patch->path); windowTitle += system::getFilename(APP->patch->path);
} }
if (windowTitle != internal->lastWindowTitle) { if (windowTitle != internal->lastWindowTitle) {
internal->ui->getWindow().setTitle(windowTitle.c_str()); internal->tlw->getWindow().setTitle(windowTitle.c_str());
internal->lastWindowTitle = windowTitle; internal->lastWindowTitle = windowTitle;
} }
// Get desired pixel ratio // Get desired pixel ratio
float newPixelRatio = internal->ui->getScaleFactor(); float newPixelRatio = internal->tlw->getScaleFactor();
if (newPixelRatio != pixelRatio) { if (newPixelRatio != pixelRatio) {
pixelRatio = newPixelRatio; pixelRatio = newPixelRatio;
APP->event->handleDirty(); APP->event->handleDirty();
@ -504,8 +613,8 @@ void Window::step() {
#endif #endif
// Get framebuffer/window ratio // Get framebuffer/window ratio
int winWidth = internal->ui->getWidth(); int winWidth = internal->tlw->getWidth();
int winHeight = internal->ui->getHeight(); int winHeight = internal->tlw->getHeight();
int fbWidth = winWidth;// * newPixelRatio; int fbWidth = winWidth;// * newPixelRatio;
int fbHeight = winHeight;// * newPixelRatio; int fbHeight = winHeight;// * newPixelRatio;
windowRatio = (float)fbWidth / winWidth; windowRatio = (float)fbWidth / winWidth;
@ -599,9 +708,9 @@ void Window::screenshotModules(const std::string&, float) {
void Window::close() { void Window::close() {
DISTRHO_SAFE_ASSERT_RETURN(internal->ui != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(internal->tlw != nullptr,);
internal->ui->getWindow().close(); internal->tlw->getWindow().close();
} }
@ -610,7 +719,7 @@ void Window::cursorLock() {
if (!settings::allowCursorLock) if (!settings::allowCursorLock)
return; return;
emscripten_request_pointerlock(internal->ui->getWindow().getApp().getClassName(), false); emscripten_request_pointerlock(internal->tlw->getWindow().getApp().getClassName(), false);
#endif #endif
} }
@ -643,7 +752,7 @@ int Window::getMods() {
void Window::setFullScreen(const bool fullscreen) { void Window::setFullScreen(const bool fullscreen) {
#ifdef DISTRHO_OS_WASM #ifdef DISTRHO_OS_WASM
if (fullscreen) if (fullscreen)
emscripten_request_fullscreen(internal->ui->getWindow().getApp().getClassName(), false); emscripten_request_fullscreen(internal->tlw->getWindow().getApp().getClassName(), false);
else else
emscripten_exit_fullscreen(); emscripten_exit_fullscreen();
#endif #endif