Browse Source

Move some code around to help remote tool later

Signed-off-by: falkTX <falktx@falktx.com>
tags/23.02
falkTX 2 years ago
parent
commit
058ad891d2
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
11 changed files with 740 additions and 191 deletions
  1. +7
    -0
      plugins/Cardinal/src/plugincontext.hpp
  2. +113
    -0
      src/CardinalCommon.cpp
  3. +1
    -70
      src/CardinalPlugin.cpp
  4. +128
    -19
      src/CardinalRemote/Makefile
  5. +270
    -43
      src/CardinalRemote/RemoteUI.cpp
  6. +9
    -2
      src/CardinalRemote/RemoteUI.hpp
  7. +78
    -2
      src/CardinalRemote/main.cpp
  8. +0
    -34
      src/CardinalUI.cpp
  9. +6
    -2
      src/PluginContext.hpp
  10. +8
    -8
      src/custom/glfw.cpp
  11. +120
    -11
      src/override/Window.cpp

+ 7
- 0
plugins/Cardinal/src/plugincontext.hpp 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);


+ 113
- 0
src/CardinalCommon.cpp 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,


+ 1
- 70
src/CardinalPlugin.cpp 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

+ 128
- 19
src/CardinalRemote/Makefile 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


# --------------------------------------------------------------
# Extra flags for liblo

BASE_FLAGS += -DHAVE_LIBLO
BASE_FLAGS += $(LIBLO_FLAGS)
LINK_FLAGS += $(LIBLO_LIBS)
ifneq ($(NOPLUGINS),true)
ifeq ($(MACOS),true)
EXTRA_LIBS += -framework Accelerate
endif
endif


# -------------------------------------------------------------- # --------------------------------------------------------------
# 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)
BASE_FLAGS += -DNANOVG_GLES2=1
BASE_FLAGS += -msse -msse2 -msse3 -msimd128
else ifneq ($(HAIKU),true)
ifeq ($(HEADLESS),true)
BASE_FLAGS += -DHEADLESS
endif

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


# --------------------------------------------------------------
# extra linker flags

ifeq ($(HAIKU),true)
ifeq ($(WASM),true)
ifneq ($(STATIC_BUILD),true)
LINK_FLAGS += --use-preload-plugins
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




+ 270
- 43
src/CardinalRemote/RemoteUI.cpp 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),
context(nullptr)
: NanoTopLevelWidget(window)
{ {
// create unique temporary path for this instance
try {
char uidBuf[24];
const std::string tmp = rack::system::getTempDirectory();
CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet()));
context.nativeWindowId = getWindow().getNativeWindowHandle();
context.tlw = this;


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");
window.setIgnoringKeyRepeat(true);
context.nativeWindowId = window.getNativeWindowHandle();


rack::contextSet(&context);
const double scaleFactor = getScaleFactor();


context.bufferSize = 512;
rack::settings::sampleRate = context.sampleRate = 48000;
setGeometryConstraints(648 * scaleFactor, 538 * scaleFactor);


context.engine = new rack::engine::Engine;
context.engine->setSampleRate(context.sampleRate);
if (scaleFactor != 1.0)
setSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor);


context.history = new rack::history::State;
context.patch = new rack::patch::Manager;
context.patch->autosavePath = autosavePath;
context.patch->templatePath = templatePath;
rack::window::WindowSetPluginRemote(context.window, this);


context.event = new rack::widget::EventState;
context.scene = new rack::app::Scene;
context.event->rootWidget = context.scene;
context.window = new rack::window::Window;
if (rack::widget::Widget* const menuBar = context.scene->menuBar)
{
context.scene->removeChild(menuBar);
delete menuBar;
}


context.patch->loadTemplate();
context.scene->rackScroll->reset();
context.scene->menuBar = rack::app::createMenuBar(true);
context.scene->addChildBelow(context.scene->menuBar, context.scene->rackScroll);


context.nativeWindowId = getWindow().getNativeWindowHandle();
// 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()));
}

// --------------------------------------------------------------------------------------------------------------------

+ 9
- 2
src/CardinalRemote/RemoteUI.hpp 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;
std::string autosavePath;
rack::math::Vec lastMousePos;


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)
}; };

+ 78
- 2
src/CardinalRemote/main.cpp 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();


+ 0
- 34
src/CardinalUI.cpp 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
{ {


+ 6
- 2
src/PluginContext.hpp 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;
} }
}; };


+ 8
- 8
src/custom/glfw.cpp 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)


+ 120
- 11
src/override/Window.cpp 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)
ui->setSize(internal->size.x, internal->size.y);
if (DGL_NAMESPACE::NanoTopLevelWidget* const tlw = internal->ui)
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 winHeight = internal->ui->getHeight();
int winWidth = internal->tlw->getWidth();
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


Loading…
Cancel
Save