@@ -1,5 +1,8 @@ | |||||
# DISTRHO CVCRack | # DISTRHO CVCRack | ||||
WORK IN PROGRESS | |||||
WORK IN PROGRESS - nothing to see here | |||||
Just an experiment to see how far we can go about a VCV plugin version that is opensource and uses original VCV source core directly. | |||||
Maybe it will work, maybe not, hard to say at this point. | |||||
This is a DPF'ied build of [VCVRack](https://github.com/VCVRack/Rack), allowing it to be used as an audio plugin. | This is a DPF'ied build of [VCVRack](https://github.com/VCVRack/Rack), allowing it to be used as an audio plugin. |
@@ -1 +1 @@ | |||||
Subproject commit c4e1210897e804a19b3fa35d542765b3feb0236e | |||||
Subproject commit 23f89562acbd637a23b9f0333877939ad26c0595 |
@@ -14,12 +14,102 @@ | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
*/ | */ | ||||
#include <asset.hpp> | |||||
#include <audio.hpp> | |||||
#include <context.hpp> | |||||
#include <library.hpp> | |||||
#include <keyboard.hpp> | |||||
#include <midi.hpp> | |||||
#include <plugin.hpp> | |||||
#include <random.hpp> | |||||
#include <settings.hpp> | |||||
#include <system.hpp> | |||||
#include <osdialog.h> | |||||
#include "DistrhoPlugin.hpp" | #include "DistrhoPlugin.hpp" | ||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
// ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
struct Initializer { | |||||
Initializer() | |||||
{ | |||||
using namespace rack; | |||||
settings::devMode = true; | |||||
system::init(); | |||||
asset::init(); | |||||
logger::init(); | |||||
random::init(); | |||||
// Log environment | |||||
INFO("%s %s v%s", APP_NAME.c_str(), APP_EDITION.c_str(), APP_VERSION.c_str()); | |||||
INFO("%s", system::getOperatingSystemInfo().c_str()); | |||||
INFO("System directory: %s", asset::systemDir.c_str()); | |||||
INFO("User directory: %s", asset::userDir.c_str()); | |||||
INFO("System time: %s", string::formatTimeISO(system::getUnixTime()).c_str()); | |||||
// Load settings | |||||
settings::init(); | |||||
try { | |||||
settings::load(); | |||||
} | |||||
catch (Exception& e) { | |||||
std::string message = e.what(); | |||||
message += "\n\nResetting settings to default"; | |||||
d_stdout(message.c_str()); | |||||
/* | |||||
if (!osdialog_message(OSDIALOG_WARNING, OSDIALOG_OK_CANCEL, msg.c_str())) { | |||||
exit(1); | |||||
} | |||||
*/ | |||||
} | |||||
// Check existence of the system res/ directory | |||||
std::string resDir = asset::system("res"); | |||||
if (!system::isDirectory(resDir)) { | |||||
std::string message = string::f("Rack's resource directory \"%s\" does not exist. Make sure Rack is correctly installed and launched.", resDir.c_str()); | |||||
d_stderr2(message.c_str()); | |||||
/* | |||||
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, message.c_str()); | |||||
*/ | |||||
exit(1); | |||||
} | |||||
INFO("Initializing environment"); | |||||
// network::init(); | |||||
audio::init(); | |||||
// rtaudioInit(); | |||||
midi::init(); | |||||
// rtmidiInit(); | |||||
keyboard::init(); | |||||
plugin::init(); | |||||
library::init(); | |||||
// discord::init(); | |||||
} | |||||
~Initializer() | |||||
{ | |||||
using namespace rack; | |||||
// discord::destroy(); | |||||
library::destroy(); | |||||
midi::destroy(); | |||||
audio::destroy(); | |||||
plugin::destroy(); | |||||
INFO("Destroying logger"); | |||||
logger::destroy(); | |||||
} | |||||
}; | |||||
static Initializer& getInitializerInstance() | |||||
{ | |||||
static Initializer init; | |||||
return init; | |||||
} | |||||
/** | /** | ||||
Plugin to demonstrate parameter outputs using meters. | Plugin to demonstrate parameter outputs using meters. | ||||
*/ | */ | ||||
@@ -130,6 +220,7 @@ private: | |||||
Plugin* createPlugin() | Plugin* createPlugin() | ||||
{ | { | ||||
getInitializerInstance(); | |||||
return new CVCRackPlugin(); | return new CVCRackPlugin(); | ||||
} | } | ||||
@@ -14,19 +14,92 @@ | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
*/ | */ | ||||
#include <app/common.hpp> | |||||
#include <app/Scene.hpp> | |||||
#include <context.hpp> | |||||
#include <engine/Engine.hpp> | |||||
#include <patch.hpp> | |||||
#include <ui/common.hpp> | |||||
#include <window/Window.hpp> | |||||
#include "DistrhoUI.hpp" | #include "DistrhoUI.hpp" | ||||
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window) { return nullptr; } | |||||
GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char*) {} | |||||
GLFWAPI const char* glfwGetKeyName(int key, int scancode) { return nullptr; } | |||||
GLFWAPI int glfwGetKeyScancode(int key) { return 0; } | |||||
namespace rack { | |||||
namespace window { | |||||
DISTRHO_NAMESPACE::UI* lastUI = nullptr; | |||||
} | |||||
} | |||||
START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
// ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
struct Initializer { | |||||
Initializer() | |||||
{ | |||||
using namespace rack; | |||||
ui::init(); | |||||
window::init(); | |||||
} | |||||
~Initializer() | |||||
{ | |||||
using namespace rack; | |||||
window::destroy(); | |||||
ui::destroy(); | |||||
} | |||||
}; | |||||
static Initializer& getInitializerInstance() | |||||
{ | |||||
static Initializer init; | |||||
return init; | |||||
} | |||||
class CVCRackUI : public UI | class CVCRackUI : public UI | ||||
{ | { | ||||
public: | public: | ||||
CVCRackUI() | CVCRackUI() | ||||
: UI(128, 512) | |||||
: UI(1280, 720) | |||||
{ | { | ||||
setGeometryConstraints(32, 128, false); | |||||
using namespace rack; | |||||
// Initialize context | |||||
INFO("Initializing context"); | |||||
window::lastUI = this; | |||||
contextSet(new Context); | |||||
APP->engine = new engine::Engine; | |||||
APP->history = new history::State; | |||||
APP->event = new widget::EventState; | |||||
APP->scene = new app::Scene; | |||||
APP->event->rootWidget = APP->scene; | |||||
APP->patch = new patch::Manager; | |||||
/*if (!settings::headless)*/ { | |||||
APP->window = new window::Window; | |||||
} | |||||
window::lastUI = nullptr; | |||||
APP->engine->startFallbackThread(); | |||||
} | |||||
~CVCRackUI() override | |||||
{ | |||||
using namespace rack; | |||||
delete APP; | |||||
contextSet(NULL); | |||||
} | |||||
void onNanoDisplay() override | |||||
{ | |||||
APP->window->step(); | |||||
} | } | ||||
protected: | protected: | ||||
@@ -41,16 +114,6 @@ protected: | |||||
{ | { | ||||
} | } | ||||
/* -------------------------------------------------------------------------------------------------------- | |||||
* Widget Callbacks */ | |||||
/** | |||||
The drawing function. | |||||
*/ | |||||
void onDisplay() override | |||||
{ | |||||
} | |||||
// ------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------- | ||||
private: | private: | ||||
@@ -65,6 +128,7 @@ private: | |||||
UI* createUI() | UI* createUI() | ||||
{ | { | ||||
getInitializerInstance(); | |||||
return new CVCRackUI(); | return new CVCRackUI(); | ||||
} | } | ||||
@@ -28,6 +28,9 @@ | |||||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | #define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 1 | ||||
// #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | // #define DISTRHO_PLUGIN_LV2_CATEGORY "lv2:AnalyserPlugin" | ||||
// #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Analyzer" | // #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Analyzer" | ||||
// #define DISTRHO_PLUGIN_HAS_EMBED_UI 1 | |||||
// #define DISTRHO_PLUGIN_HAS_EXTERNAL_UI 1 | |||||
#define DISTRHO_UI_USE_NANOVG 1 | |||||
#define DISTRHO_UI_USER_RESIZABLE 1 | #define DISTRHO_UI_USER_RESIZABLE 1 | ||||
enum Parameters { | enum Parameters { | ||||
@@ -16,11 +16,14 @@ FILES_DSP = \ | |||||
CVCRackPlugin.cpp | CVCRackPlugin.cpp | ||||
FILES_UI = \ | FILES_UI = \ | ||||
CVCRackUI.cpp | |||||
CVCRackUI.cpp \ | |||||
dep.cpp \ | |||||
Window.cpp | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Import base definitions | # Import base definitions | ||||
# UI_TYPE = external | |||||
include ../../dpf/Makefile.base.mk | include ../../dpf/Makefile.base.mk | ||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
@@ -30,8 +33,6 @@ FILES_DSP += Rack/dep/pffft/pffft.c | |||||
FILES_DSP += Rack/dep/pffft/fftpack.c | FILES_DSP += Rack/dep/pffft/fftpack.c | ||||
FILES_UI += Rack/dep/oui-blendish/blendish.c | FILES_UI += Rack/dep/oui-blendish/blendish.c | ||||
FILES_UI += Rack/dep/nanovg/src/nanovg.c | |||||
# FILES_UI += Rack/dep/glfw/deps/glad.c | |||||
# FIXME dont use this | # FIXME dont use this | ||||
FILES_UI += Rack/dep/osdialog/osdialog.c | FILES_UI += Rack/dep/osdialog/osdialog.c | ||||
@@ -45,13 +46,15 @@ endif | |||||
FILES_DSP += $(wildcard Rack/src/*.c) | FILES_DSP += $(wildcard Rack/src/*.c) | ||||
FILES_DSP += $(wildcard Rack/src/*/*.c) | FILES_DSP += $(wildcard Rack/src/*/*.c) | ||||
FILES_DSP += $(filter-out Rack/src/network.cpp Rack/src/rtaudio.cpp Rack/src/rtmidi.cpp, $(wildcard Rack/src/*.cpp)) | |||||
FILES_DSP += $(wildcard Rack/src/*/*.cpp) | |||||
FILES_DSP += $(filter-out Rack/src/dep.cpp Rack/src/gamepad.cpp Rack/src/rtaudio.cpp Rack/src/rtmidi.cpp, $(wildcard Rack/src/*.cpp)) | |||||
FILES_DSP += $(filter-out Rack/src/window/Window.cpp, $(wildcard Rack/src/*/*.cpp)) | |||||
# EXTRA_LIBS = Rack/dep/lib/libcurl.a | |||||
EXTRA_LIBS += Rack/dep/lib/libglfw3.a | |||||
EXTRA_LIBS = Rack/dep/lib/libcrypto.a | |||||
EXTRA_LIBS += Rack/dep/lib/libcurl.a | |||||
# EXTRA_LIBS += Rack/dep/lib/libglfw3.a | |||||
EXTRA_LIBS += Rack/dep/lib/libjansson.a | EXTRA_LIBS += Rack/dep/lib/libjansson.a | ||||
EXTRA_LIBS += Rack/dep/lib/libspeexdsp.a | EXTRA_LIBS += Rack/dep/lib/libspeexdsp.a | ||||
EXTRA_LIBS += Rack/dep/lib/libssl.a | |||||
EXTRA_LIBS += Rack/dep/lib/libzstd.a | EXTRA_LIBS += Rack/dep/lib/libzstd.a | ||||
ifeq ($(WINDOWS),true) | ifeq ($(WINDOWS),true) | ||||
@@ -76,16 +79,20 @@ endif | |||||
Rack/dep/lib/%.a: | Rack/dep/lib/%.a: | ||||
$(MAKE) CMAKE="$(CMAKE) -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_PREFIX='$(abspath Rack/dep)'" -C Rack/dep lib/$*.a | $(MAKE) CMAKE="$(CMAKE) -DCMAKE_INSTALL_LIBDIR=lib -DCMAKE_INSTALL_PREFIX='$(abspath Rack/dep)'" -C Rack/dep lib/$*.a | ||||
Rack/dep/lib/libcrypto.a: Rack/dep/lib/libssl.a | |||||
# -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
# Extra flags for VCV stuff | # Extra flags for VCV stuff | ||||
BASE_FLAGS += -D_APP_VERSION=2.git.0 | BASE_FLAGS += -D_APP_VERSION=2.git.0 | ||||
BASE_FLAGS += -I$(DPF_PATH)/dgl/src/nanovg | |||||
BASE_FLAGS += -IRack/include | BASE_FLAGS += -IRack/include | ||||
BASE_FLAGS += -IRack/dep/include | BASE_FLAGS += -IRack/dep/include | ||||
BASE_FLAGS += -IRack/dep/filesystem/include | BASE_FLAGS += -IRack/dep/filesystem/include | ||||
BASE_FLAGS += -IRack/dep/fuzzysearchdatabase/src | BASE_FLAGS += -IRack/dep/fuzzysearchdatabase/src | ||||
BASE_FLAGS += -IRack/dep/glfw/deps | BASE_FLAGS += -IRack/dep/glfw/deps | ||||
BASE_FLAGS += -IRack/dep/nanovg/src | |||||
BASE_FLAGS += -IRack/dep/glfw/include | |||||
# BASE_FLAGS += -IRack/dep/nanovg/src | |||||
BASE_FLAGS += -IRack/dep/nanosvg/src | BASE_FLAGS += -IRack/dep/nanosvg/src | ||||
BASE_FLAGS += -IRack/dep/osdialog | BASE_FLAGS += -IRack/dep/osdialog | ||||
BASE_FLAGS += -IRack/dep/oui-blendish | BASE_FLAGS += -IRack/dep/oui-blendish | ||||
@@ -115,8 +122,11 @@ endif | |||||
ifeq ($(MACOS),true) | ifeq ($(MACOS),true) | ||||
LINK_FLAGS += -framework IOKit | LINK_FLAGS += -framework IOKit | ||||
# LINK_FLAGS += -Wl,-all_load | |||||
endif | endif | ||||
# LINK_FLAGS += $(OPENGL_LIBS) | |||||
# TODO needed on windows? need to check | # TODO needed on windows? need to check | ||||
LINK_FLAGS += -lpthread | LINK_FLAGS += -lpthread | ||||
@@ -0,0 +1,381 @@ | |||||
#include <map> | |||||
#include <queue> | |||||
#include <thread> | |||||
#include <stb_image_write.h> | |||||
#include <osdialog.h> | |||||
#include <window/Window.hpp> | |||||
#include <asset.hpp> | |||||
#include <widget/Widget.hpp> | |||||
#include <app/Scene.hpp> | |||||
#include <keyboard.hpp> | |||||
#include <context.hpp> | |||||
#include <patch.hpp> | |||||
#include <settings.hpp> | |||||
#include <plugin.hpp> // used in Window::screenshot | |||||
#include <system.hpp> // used in Window::screenshot | |||||
#include "DistrhoUI.hpp" | |||||
namespace rack { | |||||
namespace window { | |||||
extern DISTRHO_NAMESPACE::UI* lastUI; | |||||
static const math::Vec minWindowSize = math::Vec(640, 480); | |||||
void Font::loadFile(const std::string& filename, NVGcontext* vg) { | |||||
this->vg = vg; | |||||
handle = nvgCreateFont(vg, filename.c_str(), filename.c_str()); | |||||
if (handle < 0) | |||||
throw Exception("Failed to load font %s", filename.c_str()); | |||||
INFO("Loaded font %s", filename.c_str()); | |||||
} | |||||
Font::~Font() { | |||||
// There is no NanoVG deleteFont() function yet, so do nothing | |||||
} | |||||
std::shared_ptr<Font> Font::load(const std::string& filename) { | |||||
return APP->window->loadFont(filename); | |||||
} | |||||
void Image::loadFile(const std::string& filename, NVGcontext* vg) { | |||||
this->vg = vg; | |||||
handle = nvgCreateImage(vg, filename.c_str(), NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); | |||||
if (handle <= 0) | |||||
throw Exception("Failed to load image %s", filename.c_str()); | |||||
INFO("Loaded image %s", filename.c_str()); | |||||
} | |||||
Image::~Image() { | |||||
// TODO What if handle is invalid? | |||||
if (handle >= 0) | |||||
nvgDeleteImage(vg, handle); | |||||
} | |||||
std::shared_ptr<Image> Image::load(const std::string& filename) { | |||||
return APP->window->loadImage(filename); | |||||
} | |||||
struct Window::Internal { | |||||
DISTRHO_NAMESPACE::UI* ui; | |||||
std::string lastWindowTitle; | |||||
int lastWindowX = 0; | |||||
int lastWindowY = 0; | |||||
int lastWindowWidth = 0; | |||||
int lastWindowHeight = 0; | |||||
int frame = 0; | |||||
bool ignoreNextMouseDelta = false; | |||||
int frameSwapInterval = -1; | |||||
double monitorRefreshRate = 0.0; | |||||
double frameTime = 0.0; | |||||
double lastFrameDuration = 0.0; | |||||
math::Vec lastMousePos; | |||||
std::map<std::string, std::shared_ptr<Font>> fontCache; | |||||
std::map<std::string, std::shared_ptr<Image>> imageCache; | |||||
bool fbDirtyOnSubpixelChange = true; | |||||
}; | |||||
Window::Window() { | |||||
internal = new Internal; | |||||
internal->ui = lastUI; | |||||
vg = lastUI->getContext(); | |||||
int err; | |||||
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); | |||||
INFO("UI pointer: %p", lastUI); | |||||
// GLEW generates GL error because it calls glGetString(GL_EXTENSIONS), we'll consume it here. | |||||
glGetError(); | |||||
// Load default Blendish font | |||||
uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf")); | |||||
bndSetFont(uiFont->handle); | |||||
if (APP->scene) { | |||||
widget::Widget::ContextCreateEvent e; | |||||
APP->scene->onContextCreate(e); | |||||
} | |||||
} | |||||
Window::~Window() { | |||||
if (APP->scene) { | |||||
widget::Widget::ContextDestroyEvent e; | |||||
APP->scene->onContextDestroy(e); | |||||
} | |||||
// Fonts and Images in the cache must be deleted before the NanoVG context is deleted | |||||
internal->fontCache.clear(); | |||||
internal->imageCache.clear(); | |||||
// nvgDeleteClone(fbVg); | |||||
delete internal; | |||||
} | |||||
math::Vec Window::getSize() { | |||||
return math::Vec(1280, 720); | |||||
} | |||||
void Window::setSize(math::Vec size) { | |||||
size = size.max(minWindowSize); | |||||
} | |||||
void Window::run() { | |||||
internal->frame = 0; | |||||
} | |||||
void Window::step() { | |||||
double frameTime = system::getTime(); | |||||
double lastFrameTime = internal->frameTime; | |||||
internal->frameTime = frameTime; | |||||
internal->lastFrameDuration = frameTime - lastFrameTime; | |||||
// DEBUG("%.2lf Hz", 1.0 / internal->lastFrameDuration); | |||||
double t1 = 0.0, t2 = 0.0, t3 = 0.0, t4 = 0.0, t5 = 0.0; | |||||
// Make event handlers and step() have a clean NanoVG context | |||||
nvgReset(vg); | |||||
bndSetFont(uiFont->handle); | |||||
nvgFillColor(vg, nvgRGBf(1, 1, 1)); | |||||
nvgStrokeColor(vg, nvgRGBf(1, 1, 1)); | |||||
// Poll events | |||||
// Save and restore context because event handler set their own context based on which window they originate from. | |||||
Context* context = contextGet(); | |||||
// glfwPollEvents(); | |||||
contextSet(context); | |||||
// Set window title | |||||
std::string windowTitle = APP_NAME + " " + APP_EDITION_NAME + " " + APP_VERSION; | |||||
if (APP->patch->path != "") { | |||||
windowTitle += " - "; | |||||
if (!APP->history->isSaved()) | |||||
windowTitle += "*"; | |||||
windowTitle += system::getFilename(APP->patch->path); | |||||
} | |||||
if (windowTitle != internal->lastWindowTitle) { | |||||
internal->ui->getWindow().setTitle(windowTitle.c_str()); | |||||
internal->lastWindowTitle = windowTitle; | |||||
} | |||||
// Get desired pixel ratio | |||||
float newPixelRatio = internal->ui->getScaleFactor(); | |||||
if (newPixelRatio != pixelRatio) { | |||||
pixelRatio = newPixelRatio; | |||||
APP->event->handleDirty(); | |||||
} | |||||
// Get framebuffer/window ratio | |||||
int winWidth = internal->ui->getWidth(); | |||||
int winHeight = internal->ui->getHeight(); | |||||
int fbWidth = winWidth;// * newPixelRatio; | |||||
int fbHeight = winHeight;// * newPixelRatio; | |||||
windowRatio = (float)fbWidth / winWidth; | |||||
t1 = system::getTime(); | |||||
if (APP->scene) { | |||||
// DEBUG("%f %f %d %d", pixelRatio, windowRatio, fbWidth, winWidth); | |||||
// Resize scene | |||||
APP->scene->box.size = math::Vec(fbWidth, fbHeight).div(pixelRatio); | |||||
// Step scene | |||||
APP->scene->step(); | |||||
t2 = system::getTime(); | |||||
// Render scene | |||||
bool visible = true; | |||||
if (visible) { | |||||
// Update and render | |||||
nvgBeginFrame(vg, fbWidth, fbHeight, pixelRatio); | |||||
nvgScale(vg, pixelRatio, pixelRatio); | |||||
// Draw scene | |||||
widget::Widget::DrawArgs args; | |||||
args.vg = vg; | |||||
args.clipBox = APP->scene->box.zeroPos(); | |||||
APP->scene->draw(args); | |||||
t3 = system::getTime(); | |||||
// glViewport(0, -winHeight, fbWidth, fbHeight); | |||||
// glClearColor(0.0, 0.0, 0.0, 1.0); | |||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |||||
nvgEndFrame(vg); | |||||
t4 = system::getTime(); | |||||
} | |||||
} | |||||
t5 = system::getTime(); | |||||
// DEBUG("pre-step %6.1f step %6.1f draw %6.1f nvgEndFrame %6.1f glfwSwapBuffers %6.1f total %6.1f", | |||||
// (t1 - frameTime) * 1e3f, | |||||
// (t2 - t1) * 1e3f, | |||||
// (t3 - t2) * 1e3f, | |||||
// (t4 - t2) * 1e3f, | |||||
// (t5 - t4) * 1e3f, | |||||
// (t5 - frameTime) * 1e3f | |||||
// ); | |||||
internal->frame++; | |||||
} | |||||
void Window::screenshot(const std::string&) { | |||||
} | |||||
void Window::screenshotModules(const std::string&, float) { | |||||
} | |||||
void Window::close() { | |||||
internal->ui->getWindow().close(); | |||||
} | |||||
void Window::cursorLock() { | |||||
if (!settings::allowCursorLock) | |||||
return; | |||||
internal->ignoreNextMouseDelta = true; | |||||
} | |||||
void Window::cursorUnlock() { | |||||
if (!settings::allowCursorLock) | |||||
return; | |||||
internal->ignoreNextMouseDelta = true; | |||||
} | |||||
bool Window::isCursorLocked() { | |||||
return false; | |||||
} | |||||
int Window::getMods() { | |||||
int mods = 0; | |||||
/* | |||||
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; | |||||
} | |||||
void Window::setFullScreen(bool) { | |||||
} | |||||
bool Window::isFullScreen() { | |||||
return false; | |||||
} | |||||
double Window::getMonitorRefreshRate() { | |||||
return internal->monitorRefreshRate; | |||||
} | |||||
double Window::getFrameTime() { | |||||
return internal->frameTime; | |||||
} | |||||
double Window::getLastFrameDuration() { | |||||
return internal->lastFrameDuration; | |||||
} | |||||
double Window::getFrameDurationRemaining() { | |||||
double frameDurationDesired = internal->frameSwapInterval / internal->monitorRefreshRate; | |||||
return frameDurationDesired - (system::getTime() - internal->frameTime); | |||||
} | |||||
std::shared_ptr<Font> Window::loadFont(const std::string& filename) { | |||||
const auto& pair = internal->fontCache.find(filename); | |||||
if (pair != internal->fontCache.end()) | |||||
return pair->second; | |||||
// Load font | |||||
std::shared_ptr<Font> font; | |||||
try { | |||||
font = std::make_shared<Font>(); | |||||
font->loadFile(filename, vg); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("%s", e.what()); | |||||
font = NULL; | |||||
} | |||||
internal->fontCache[filename] = font; | |||||
return font; | |||||
} | |||||
std::shared_ptr<Image> Window::loadImage(const std::string& filename) { | |||||
const auto& pair = internal->imageCache.find(filename); | |||||
if (pair != internal->imageCache.end()) | |||||
return pair->second; | |||||
// Load image | |||||
std::shared_ptr<Image> image; | |||||
try { | |||||
image = std::make_shared<Image>(); | |||||
image->loadFile(filename, vg); | |||||
} | |||||
catch (Exception& e) { | |||||
WARN("%s", e.what()); | |||||
image = NULL; | |||||
} | |||||
internal->imageCache[filename] = image; | |||||
return image; | |||||
} | |||||
bool& Window::fbDirtyOnSubpixelChange() { | |||||
return internal->fbDirtyOnSubpixelChange; | |||||
} | |||||
void init() { | |||||
} | |||||
void destroy() { | |||||
} | |||||
} // namespace window | |||||
} // namespace rack |
@@ -0,0 +1,19 @@ | |||||
// This source file compiles those annoying implementation-in-header libraries | |||||
#include <common.hpp> // for fopen_u8 | |||||
#define GLEW_STATIC | |||||
#define GLEW_NO_GLU | |||||
#include <GL/glew.h> | |||||
#include <nanovg.h> | |||||
#define BLENDISH_IMPLEMENTATION | |||||
#include <blendish.h> | |||||
#define NANOSVG_IMPLEMENTATION | |||||
#define NANOSVG_ALL_COLOR_KEYWORDS | |||||
#include <nanosvg.h> | |||||
#define STB_IMAGE_WRITE_IMPLEMENTATION | |||||
#include <stb_image_write.h> |