Add diffs for the overriden files
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
2c3867ca6a
commit
810928190c
9 changed files with 3047 additions and 0 deletions
12
src/override/.generate-diffs.sh
Executable file
12
src/override/.generate-diffs.sh
Executable file
|
@ -0,0 +1,12 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
diff -U3 ../Rack/dep/oui-blendish/blendish.c blendish.c > diffs/blendish.c.diff
|
||||
diff -U3 ../Rack/src/common.cpp common.cpp > diffs/common.cpp.diff
|
||||
diff -U3 ../Rack/src/context.cpp context.cpp > diffs/context.cpp.diff
|
||||
diff -U3 ../Rack/src/app/MenuBar.cpp MenuBar.cpp > diffs/MenuBar.cpp.diff
|
||||
diff -U3 ../Rack/src/app/Scene.cpp Scene.cpp > diffs/Scene.cpp.diff
|
||||
diff -U3 ../Rack/src/engine/Engine.cpp Engine.cpp > diffs/Engine.cpp.diff
|
||||
diff -U3 ../Rack/src/plugin/Model.cpp Model.cpp > diffs/Model.cpp.diff
|
||||
diff -U3 ../Rack/src/window/Window.cpp Window.cpp > diffs/Window.cpp.diff
|
761
src/override/diffs/Engine.cpp.diff
Normal file
761
src/override/diffs/Engine.cpp.diff
Normal file
|
@ -0,0 +1,761 @@
|
|||
--- ../Rack/src/engine/Engine.cpp 2022-01-15 14:44:46.395281005 +0000
|
||||
+++ Engine.cpp 2022-01-23 17:13:03.200930905 +0000
|
||||
@@ -1,3 +1,30 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's engine/Engine.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <thread>
|
||||
@@ -11,178 +38,25 @@
|
||||
#include <settings.hpp>
|
||||
#include <system.hpp>
|
||||
#include <random.hpp>
|
||||
-#include <context.hpp>
|
||||
#include <patch.hpp>
|
||||
#include <plugin.hpp>
|
||||
#include <mutex.hpp>
|
||||
+#include <helpers.hpp>
|
||||
+
|
||||
+#ifdef NDEBUG
|
||||
+# undef DEBUG
|
||||
+#endif
|
||||
|
||||
+#include "DistrhoUtils.hpp"
|
||||
|
||||
namespace rack {
|
||||
namespace engine {
|
||||
|
||||
|
||||
-static void initMXCSR() {
|
||||
- // Set CPU to flush-to-zero (FTZ) and denormals-are-zero (DAZ) mode
|
||||
- // https://software.intel.com/en-us/node/682949
|
||||
- _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||
- _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||
- // Reset other flags
|
||||
- _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/** Barrier based on mutexes.
|
||||
-Not finished or tested, do not use.
|
||||
-*/
|
||||
-struct Barrier {
|
||||
- int count = 0;
|
||||
- uint8_t step = 0;
|
||||
- int threads = 0;
|
||||
-
|
||||
- std::mutex mutex;
|
||||
- std::condition_variable cv;
|
||||
-
|
||||
- void setThreads(int threads) {
|
||||
- this->threads = threads;
|
||||
- }
|
||||
-
|
||||
- void wait() {
|
||||
- std::unique_lock<std::mutex> lock(mutex);
|
||||
- uint8_t s = step;
|
||||
- if (++count >= threads) {
|
||||
- // We're the last thread. Reset next phase.
|
||||
- count = 0;
|
||||
- // Allow other threads to exit wait()
|
||||
- step++;
|
||||
- cv.notify_all();
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- cv.wait(lock, [&] {
|
||||
- return step != s;
|
||||
- });
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/** 2-phase barrier based on spin-locking.
|
||||
-*/
|
||||
-struct SpinBarrier {
|
||||
- std::atomic<int> count{0};
|
||||
- std::atomic<uint8_t> step{0};
|
||||
- int threads = 0;
|
||||
-
|
||||
- /** Must be called when no threads are calling wait().
|
||||
- */
|
||||
- void setThreads(int threads) {
|
||||
- this->threads = threads;
|
||||
- }
|
||||
-
|
||||
- void wait() {
|
||||
- uint8_t s = step;
|
||||
- if (count.fetch_add(1, std::memory_order_acquire) + 1 >= threads) {
|
||||
- // We're the last thread. Reset next phase.
|
||||
- count = 0;
|
||||
- // Allow other threads to exit wait()
|
||||
- step++;
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Spin until the last thread begins waiting
|
||||
- while (true) {
|
||||
- if (step.load(std::memory_order_relaxed) != s)
|
||||
- return;
|
||||
- __builtin_ia32_pause();
|
||||
- }
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-/** Barrier that spin-locks until yield() is called, and then all threads switch to a mutex.
|
||||
-yield() should be called if it is likely that all threads will block for a while and continuing to spin-lock is unnecessary.
|
||||
-Saves CPU power after yield is called.
|
||||
-*/
|
||||
-struct HybridBarrier {
|
||||
- std::atomic<int> count{0};
|
||||
- std::atomic<uint8_t> step{0};
|
||||
- int threads = 0;
|
||||
-
|
||||
- std::atomic<bool> yielded{false};
|
||||
- std::mutex mutex;
|
||||
- std::condition_variable cv;
|
||||
-
|
||||
- void setThreads(int threads) {
|
||||
- this->threads = threads;
|
||||
- }
|
||||
-
|
||||
- void yield() {
|
||||
- yielded = true;
|
||||
- }
|
||||
-
|
||||
- void wait() {
|
||||
- uint8_t s = step;
|
||||
- if (count.fetch_add(1, std::memory_order_acquire) + 1 >= threads) {
|
||||
- // We're the last thread. Reset next phase.
|
||||
- count = 0;
|
||||
- bool wasYielded = yielded;
|
||||
- yielded = false;
|
||||
- // Allow other threads to exit wait()
|
||||
- step++;
|
||||
- if (wasYielded) {
|
||||
- std::unique_lock<std::mutex> lock(mutex);
|
||||
- cv.notify_all();
|
||||
- }
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // Spin until the last thread begins waiting
|
||||
- while (!yielded.load(std::memory_order_relaxed)) {
|
||||
- if (step.load(std::memory_order_relaxed) != s)
|
||||
- return;
|
||||
- __builtin_ia32_pause();
|
||||
- }
|
||||
-
|
||||
- // Wait on mutex CV
|
||||
- std::unique_lock<std::mutex> lock(mutex);
|
||||
- cv.wait(lock, [&] {
|
||||
- return step != s;
|
||||
- });
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct EngineWorker {
|
||||
- Engine* engine;
|
||||
- int id;
|
||||
- std::thread thread;
|
||||
- bool running = false;
|
||||
-
|
||||
- void start() {
|
||||
- assert(!running);
|
||||
- running = true;
|
||||
- thread = std::thread([&] {
|
||||
- run();
|
||||
- });
|
||||
- }
|
||||
-
|
||||
- void requestStop() {
|
||||
- running = false;
|
||||
- }
|
||||
-
|
||||
- void join() {
|
||||
- assert(thread.joinable());
|
||||
- thread.join();
|
||||
- }
|
||||
-
|
||||
- void run();
|
||||
-};
|
||||
-
|
||||
-
|
||||
struct Engine::Internal {
|
||||
std::vector<Module*> modules;
|
||||
std::vector<Cable*> cables;
|
||||
std::set<ParamHandle*> paramHandles;
|
||||
- Module* masterModule = NULL;
|
||||
|
||||
// moduleId
|
||||
std::map<int64_t, Module*> modulesCache;
|
||||
@@ -217,22 +91,6 @@
|
||||
Readers lock when using the engine's state.
|
||||
*/
|
||||
SharedMutex mutex;
|
||||
- /** Mutex that guards stepBlock() so it's not called simultaneously.
|
||||
- */
|
||||
- std::mutex blockMutex;
|
||||
-
|
||||
- int threadCount = 0;
|
||||
- std::vector<EngineWorker> workers;
|
||||
- HybridBarrier engineBarrier;
|
||||
- HybridBarrier workerBarrier;
|
||||
- std::atomic<int> workerModuleIndex;
|
||||
- // For worker threads
|
||||
- Context* context;
|
||||
-
|
||||
- bool fallbackRunning = false;
|
||||
- std::thread fallbackThread;
|
||||
- std::mutex fallbackMutex;
|
||||
- std::condition_variable fallbackCv;
|
||||
};
|
||||
|
||||
|
||||
@@ -260,71 +118,6 @@
|
||||
}
|
||||
|
||||
|
||||
-static void Engine_relaunchWorkers(Engine* that, int threadCount) {
|
||||
- Engine::Internal* internal = that->internal;
|
||||
- if (threadCount == internal->threadCount)
|
||||
- return;
|
||||
-
|
||||
- if (internal->threadCount > 0) {
|
||||
- // Stop engine workers
|
||||
- for (EngineWorker& worker : internal->workers) {
|
||||
- worker.requestStop();
|
||||
- }
|
||||
- internal->engineBarrier.wait();
|
||||
-
|
||||
- // Join and destroy engine workers
|
||||
- for (EngineWorker& worker : internal->workers) {
|
||||
- worker.join();
|
||||
- }
|
||||
- internal->workers.resize(0);
|
||||
- }
|
||||
-
|
||||
- // Configure engine
|
||||
- internal->threadCount = threadCount;
|
||||
-
|
||||
- // Set barrier counts
|
||||
- internal->engineBarrier.setThreads(threadCount);
|
||||
- internal->workerBarrier.setThreads(threadCount);
|
||||
-
|
||||
- if (threadCount > 0) {
|
||||
- // Create and start engine workers
|
||||
- internal->workers.resize(threadCount - 1);
|
||||
- for (int id = 1; id < threadCount; id++) {
|
||||
- EngineWorker& worker = internal->workers[id - 1];
|
||||
- worker.id = id;
|
||||
- worker.engine = that;
|
||||
- worker.start();
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void Engine_stepWorker(Engine* that, int threadId) {
|
||||
- Engine::Internal* internal = that->internal;
|
||||
-
|
||||
- // int threadCount = internal->threadCount;
|
||||
- int modulesLen = internal->modules.size();
|
||||
-
|
||||
- // Build ProcessArgs
|
||||
- Module::ProcessArgs processArgs;
|
||||
- processArgs.sampleRate = internal->sampleRate;
|
||||
- processArgs.sampleTime = internal->sampleTime;
|
||||
- processArgs.frame = internal->frame;
|
||||
-
|
||||
- // Step each module
|
||||
- while (true) {
|
||||
- // Choose next module
|
||||
- // First-come-first serve module-to-thread allocation algorithm
|
||||
- int i = internal->workerModuleIndex++;
|
||||
- if (i >= modulesLen)
|
||||
- break;
|
||||
-
|
||||
- Module* module = internal->modules[i];
|
||||
- module->doProcess(processArgs);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
static void Cable_step(Cable* that) {
|
||||
Output* output = &that->outputModule->outputs[that->outputId];
|
||||
Input* input = &that->inputModule->inputs[that->inputId];
|
||||
@@ -373,12 +166,12 @@
|
||||
}
|
||||
|
||||
// Step cables
|
||||
- for (Cable* cable : that->internal->cables) {
|
||||
+ for (Cable* cable : internal->cables) {
|
||||
Cable_step(cable);
|
||||
}
|
||||
|
||||
// Flip messages for each module
|
||||
- for (Module* module : that->internal->modules) {
|
||||
+ for (Module* module : internal->modules) {
|
||||
if (module->leftExpander.messageFlipRequested) {
|
||||
std::swap(module->leftExpander.producerMessage, module->leftExpander.consumerMessage);
|
||||
module->leftExpander.messageFlipRequested = false;
|
||||
@@ -389,13 +182,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
- // Step modules along with workers
|
||||
- internal->workerModuleIndex = 0;
|
||||
- internal->engineBarrier.wait();
|
||||
- Engine_stepWorker(that, 0);
|
||||
- internal->workerBarrier.wait();
|
||||
+ // Build ProcessArgs
|
||||
+ Module::ProcessArgs processArgs;
|
||||
+ processArgs.sampleRate = internal->sampleRate;
|
||||
+ processArgs.sampleTime = internal->sampleTime;
|
||||
+ processArgs.frame = internal->frame;
|
||||
+
|
||||
+ // Step each module
|
||||
+ for (Module* module : internal->modules) {
|
||||
+ module->doProcess(processArgs);
|
||||
+ }
|
||||
|
||||
- internal->frame++;
|
||||
+ ++internal->frame;
|
||||
}
|
||||
|
||||
|
||||
@@ -460,37 +258,22 @@
|
||||
|
||||
Engine::Engine() {
|
||||
internal = new Internal;
|
||||
-
|
||||
- internal->context = contextGet();
|
||||
- setSuggestedSampleRate(0.f);
|
||||
}
|
||||
|
||||
|
||||
Engine::~Engine() {
|
||||
- // Stop fallback thread if running
|
||||
- {
|
||||
- std::lock_guard<std::mutex> lock(internal->fallbackMutex);
|
||||
- internal->fallbackRunning = false;
|
||||
- internal->fallbackCv.notify_all();
|
||||
- }
|
||||
- if (internal->fallbackThread.joinable())
|
||||
- internal->fallbackThread.join();
|
||||
-
|
||||
- // Shut down workers
|
||||
- Engine_relaunchWorkers(this, 0);
|
||||
-
|
||||
// Clear modules, cables, etc
|
||||
clear();
|
||||
|
||||
// Make sure there are no cables or modules in the rack on destruction.
|
||||
// If this happens, a module must have failed to remove itself before the RackWidget was destroyed.
|
||||
- assert(internal->cables.empty());
|
||||
- assert(internal->modules.empty());
|
||||
- assert(internal->paramHandles.empty());
|
||||
-
|
||||
- assert(internal->modulesCache.empty());
|
||||
- assert(internal->cablesCache.empty());
|
||||
- assert(internal->paramHandlesCache.empty());
|
||||
+ DISTRHO_SAFE_ASSERT(internal->cables.empty());
|
||||
+ DISTRHO_SAFE_ASSERT(internal->modules.empty());
|
||||
+ DISTRHO_SAFE_ASSERT(internal->paramHandles.empty());
|
||||
+
|
||||
+ DISTRHO_SAFE_ASSERT(internal->modulesCache.empty());
|
||||
+ DISTRHO_SAFE_ASSERT(internal->cablesCache.empty());
|
||||
+ DISTRHO_SAFE_ASSERT(internal->paramHandlesCache.empty());
|
||||
|
||||
delete internal;
|
||||
}
|
||||
@@ -526,11 +309,8 @@
|
||||
// Start timer before locking
|
||||
double startTime = system::getTime();
|
||||
|
||||
- std::lock_guard<std::mutex> stepLock(internal->blockMutex);
|
||||
SharedLock<SharedMutex> lock(internal->mutex);
|
||||
// Configure thread
|
||||
- uint32_t csr = _mm_getcsr();
|
||||
- initMXCSR();
|
||||
random::init();
|
||||
|
||||
internal->blockFrame = internal->frame;
|
||||
@@ -543,16 +323,11 @@
|
||||
Engine_updateExpander_NoLock(this, module, true);
|
||||
}
|
||||
|
||||
- // Launch workers
|
||||
- Engine_relaunchWorkers(this, settings::threadCount);
|
||||
-
|
||||
// Step individual frames
|
||||
for (int i = 0; i < frames; i++) {
|
||||
Engine_stepFrame(this);
|
||||
}
|
||||
|
||||
- yieldWorkers();
|
||||
-
|
||||
internal->block++;
|
||||
|
||||
// Stop timer
|
||||
@@ -572,47 +347,19 @@
|
||||
internal->meterTotal = 0.0;
|
||||
internal->meterMax = 0.0;
|
||||
}
|
||||
-
|
||||
- // Reset MXCSR back to original value
|
||||
- _mm_setcsr(csr);
|
||||
}
|
||||
|
||||
|
||||
void Engine::setMasterModule(Module* module) {
|
||||
- if (module == internal->masterModule)
|
||||
- return;
|
||||
- std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
- setMasterModule_NoLock(module);
|
||||
}
|
||||
|
||||
|
||||
void Engine::setMasterModule_NoLock(Module* module) {
|
||||
- if (module == internal->masterModule)
|
||||
- return;
|
||||
-
|
||||
- if (internal->masterModule) {
|
||||
- // Dispatch UnsetMasterEvent
|
||||
- Module::UnsetMasterEvent e;
|
||||
- internal->masterModule->onUnsetMaster(e);
|
||||
- }
|
||||
-
|
||||
- internal->masterModule = module;
|
||||
-
|
||||
- if (internal->masterModule) {
|
||||
- // Dispatch SetMasterEvent
|
||||
- Module::SetMasterEvent e;
|
||||
- internal->masterModule->onSetMaster(e);
|
||||
- }
|
||||
-
|
||||
- // Wake up fallback thread if master module was unset
|
||||
- if (!internal->masterModule) {
|
||||
- internal->fallbackCv.notify_all();
|
||||
- }
|
||||
}
|
||||
|
||||
|
||||
Module* Engine::getMasterModule() {
|
||||
- return internal->masterModule;
|
||||
+ return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -639,16 +386,6 @@
|
||||
|
||||
|
||||
void Engine::setSuggestedSampleRate(float suggestedSampleRate) {
|
||||
- if (settings::sampleRate > 0) {
|
||||
- setSampleRate(settings::sampleRate);
|
||||
- }
|
||||
- else if (suggestedSampleRate > 0) {
|
||||
- setSampleRate(suggestedSampleRate);
|
||||
- }
|
||||
- else {
|
||||
- // Fallback sample rate
|
||||
- setSampleRate(44100.f);
|
||||
- }
|
||||
}
|
||||
|
||||
|
||||
@@ -658,7 +395,6 @@
|
||||
|
||||
|
||||
void Engine::yieldWorkers() {
|
||||
- internal->workerBarrier.yield();
|
||||
}
|
||||
|
||||
|
||||
@@ -738,10 +474,10 @@
|
||||
|
||||
void Engine::addModule(Module* module) {
|
||||
std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
- assert(module);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(module,);
|
||||
// Check that the module is not already added
|
||||
auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
|
||||
- assert(it == internal->modules.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it == internal->modules.end(),);
|
||||
// Set ID if unset or collides with an existing ID
|
||||
while (module->id < 0 || internal->modulesCache.find(module->id) != internal->modulesCache.end()) {
|
||||
// Randomly generate ID
|
||||
@@ -773,10 +509,14 @@
|
||||
|
||||
|
||||
void Engine::removeModule_NoLock(Module* module) {
|
||||
- assert(module);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(module,);
|
||||
// Check that the module actually exists
|
||||
auto it = std::find(internal->modules.begin(), internal->modules.end(), module);
|
||||
- assert(it != internal->modules.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it != internal->modules.end(),);
|
||||
+ // Remove from widgets cache
|
||||
+ CardinalPluginModelHelper* const helper = dynamic_cast<CardinalPluginModelHelper*>(module->model);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(helper != nullptr,);
|
||||
+ helper->removeCachedModuleWidget(module);
|
||||
// Dispatch RemoveEvent
|
||||
Module::RemoveEvent eRemove;
|
||||
module->onRemove(eRemove);
|
||||
@@ -785,18 +525,14 @@
|
||||
if (paramHandle->moduleId == module->id)
|
||||
paramHandle->module = NULL;
|
||||
}
|
||||
- // Unset master module
|
||||
- if (getMasterModule() == module) {
|
||||
- setMasterModule_NoLock(NULL);
|
||||
- }
|
||||
// If a param is being smoothed on this module, stop smoothing it immediately
|
||||
if (module == internal->smoothModule) {
|
||||
internal->smoothModule = NULL;
|
||||
}
|
||||
// Check that all cables are disconnected
|
||||
for (Cable* cable : internal->cables) {
|
||||
- assert(cable->inputModule != module);
|
||||
- assert(cable->outputModule != module);
|
||||
+ DISTRHO_SAFE_ASSERT(cable->inputModule != module);
|
||||
+ DISTRHO_SAFE_ASSERT(cable->outputModule != module);
|
||||
}
|
||||
// Update expanders of other modules
|
||||
for (Module* m : internal->modules) {
|
||||
@@ -844,7 +580,7 @@
|
||||
|
||||
void Engine::resetModule(Module* module) {
|
||||
std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
- assert(module);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(module,);
|
||||
|
||||
Module::ResetEvent eReset;
|
||||
module->onReset(eReset);
|
||||
@@ -853,7 +589,7 @@
|
||||
|
||||
void Engine::randomizeModule(Module* module) {
|
||||
std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
- assert(module);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(module,);
|
||||
|
||||
Module::RandomizeEvent eRandomize;
|
||||
module->onRandomize(eRandomize);
|
||||
@@ -861,7 +597,7 @@
|
||||
|
||||
|
||||
void Engine::bypassModule(Module* module, bool bypassed) {
|
||||
- assert(module);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(module,);
|
||||
if (module->isBypassed() == bypassed)
|
||||
return;
|
||||
|
||||
@@ -946,16 +682,16 @@
|
||||
|
||||
void Engine::addCable(Cable* cable) {
|
||||
std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
- assert(cable);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(cable,);
|
||||
// Check cable properties
|
||||
- assert(cable->inputModule);
|
||||
- assert(cable->outputModule);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(cable->inputModule,);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(cable->outputModule,);
|
||||
bool outputWasConnected = false;
|
||||
for (Cable* cable2 : internal->cables) {
|
||||
// Check that the cable is not already added
|
||||
- assert(cable2 != cable);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(cable2 != cable,);
|
||||
// Check that the input is not already used by another cable
|
||||
- assert(!(cable2->inputModule == cable->inputModule && cable2->inputId == cable->inputId));
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(!(cable2->inputModule == cable->inputModule && cable2->inputId == cable->inputId),);
|
||||
// Get connected status of output, to decide whether we need to call a PortChangeEvent.
|
||||
// It's best to not trust `cable->outputModule->outputs[cable->outputId]->isConnected()`
|
||||
if (cable2->outputModule == cable->outputModule && cable2->outputId == cable->outputId)
|
||||
@@ -996,10 +732,10 @@
|
||||
|
||||
|
||||
void Engine::removeCable_NoLock(Cable* cable) {
|
||||
- assert(cable);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(cable,);
|
||||
// Check that the cable is already added
|
||||
auto it = std::find(internal->cables.begin(), internal->cables.end(), cable);
|
||||
- assert(it != internal->cables.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it != internal->cables.end(),);
|
||||
// Remove the cable
|
||||
internal->cablesCache.erase(cable->id);
|
||||
internal->cables.erase(it);
|
||||
@@ -1085,11 +821,11 @@
|
||||
std::lock_guard<SharedMutex> lock(internal->mutex);
|
||||
// New ParamHandles must be blank.
|
||||
// This means we don't have to refresh the cache.
|
||||
- assert(paramHandle->moduleId < 0);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(paramHandle->moduleId < 0,);
|
||||
|
||||
// Check that the ParamHandle is not already added
|
||||
auto it = internal->paramHandles.find(paramHandle);
|
||||
- assert(it == internal->paramHandles.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it == internal->paramHandles.end(),);
|
||||
|
||||
// Add it
|
||||
internal->paramHandles.insert(paramHandle);
|
||||
@@ -1106,7 +842,7 @@
|
||||
void Engine::removeParamHandle_NoLock(ParamHandle* paramHandle) {
|
||||
// Check that the ParamHandle is already added
|
||||
auto it = internal->paramHandles.find(paramHandle);
|
||||
- assert(it != internal->paramHandles.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it != internal->paramHandles.end(),);
|
||||
|
||||
// Remove it
|
||||
paramHandle->module = NULL;
|
||||
@@ -1143,7 +879,7 @@
|
||||
void Engine::updateParamHandle_NoLock(ParamHandle* paramHandle, int64_t moduleId, int paramId, bool overwrite) {
|
||||
// Check that it exists
|
||||
auto it = internal->paramHandles.find(paramHandle);
|
||||
- assert(it != internal->paramHandles.end());
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(it != internal->paramHandles.end(),);
|
||||
|
||||
// Set IDs
|
||||
paramHandle->moduleId = moduleId;
|
||||
@@ -1197,11 +933,6 @@
|
||||
}
|
||||
json_object_set_new(rootJ, "cables", cablesJ);
|
||||
|
||||
- // masterModule
|
||||
- if (internal->masterModule) {
|
||||
- json_object_set_new(rootJ, "masterModuleId", json_integer(internal->masterModule->id));
|
||||
- }
|
||||
-
|
||||
return rootJ;
|
||||
}
|
||||
|
||||
@@ -1225,14 +956,20 @@
|
||||
}
|
||||
catch (Exception& e) {
|
||||
WARN("Cannot load model: %s", e.what());
|
||||
- APP->patch->log(e.what());
|
||||
+ // APP->patch->log(e.what());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create module
|
||||
- INFO("Creating module %s", model->getFullName().c_str());
|
||||
- Module* module = model->createModule();
|
||||
- assert(module);
|
||||
+ Module* const module = model->createModule();
|
||||
+ DISTRHO_SAFE_ASSERT_CONTINUE(module != nullptr);
|
||||
+
|
||||
+ // Create the widget too, needed by a few modules
|
||||
+ CardinalPluginModelHelper* const helper = dynamic_cast<CardinalPluginModelHelper*>(model);
|
||||
+ DISTRHO_SAFE_ASSERT_CONTINUE(helper != nullptr);
|
||||
+
|
||||
+ app::ModuleWidget* const moduleWidget = helper->createModuleWidgetFromEngineLoad(module);
|
||||
+ DISTRHO_SAFE_ASSERT_CONTINUE(moduleWidget != nullptr);
|
||||
|
||||
try {
|
||||
// This doesn't need a lock because the Module is not added to the Engine yet.
|
||||
@@ -1248,7 +985,8 @@
|
||||
}
|
||||
catch (Exception& e) {
|
||||
WARN("Cannot load module: %s", e.what());
|
||||
- APP->patch->log(e.what());
|
||||
+ // APP->patch->log(e.what());
|
||||
+ helper->removeCachedModuleWidget(module);
|
||||
delete module;
|
||||
continue;
|
||||
}
|
||||
@@ -1285,67 +1023,10 @@
|
||||
continue;
|
||||
}
|
||||
}
|
||||
-
|
||||
- // masterModule
|
||||
- json_t* masterModuleIdJ = json_object_get(rootJ, "masterModuleId");
|
||||
- if (masterModuleIdJ) {
|
||||
- Module* masterModule = getModule(json_integer_value(masterModuleIdJ));
|
||||
- setMasterModule(masterModule);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-void EngineWorker::run() {
|
||||
- // Configure thread
|
||||
- contextSet(engine->internal->context);
|
||||
- system::setThreadName(string::f("Worker %d", id));
|
||||
- initMXCSR();
|
||||
- random::init();
|
||||
-
|
||||
- while (true) {
|
||||
- engine->internal->engineBarrier.wait();
|
||||
- if (!running)
|
||||
- return;
|
||||
- Engine_stepWorker(engine, id);
|
||||
- engine->internal->workerBarrier.wait();
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-
|
||||
-static void Engine_fallbackRun(Engine* that) {
|
||||
- system::setThreadName("Engine fallback");
|
||||
- contextSet(that->internal->context);
|
||||
-
|
||||
- while (that->internal->fallbackRunning) {
|
||||
- if (!that->getMasterModule()) {
|
||||
- // Step blocks and wait
|
||||
- double start = system::getTime();
|
||||
- int frames = std::floor(that->getSampleRate() / 60);
|
||||
- that->stepBlock(frames);
|
||||
- double end = system::getTime();
|
||||
-
|
||||
- double duration = frames * that->getSampleTime() - (end - start);
|
||||
- if (duration > 0.0) {
|
||||
- std::this_thread::sleep_for(std::chrono::duration<double>(duration));
|
||||
- }
|
||||
- }
|
||||
- else {
|
||||
- // Wait for master module to be unset, or for the request to stop running
|
||||
- std::unique_lock<std::mutex> lock(that->internal->fallbackMutex);
|
||||
- that->internal->fallbackCv.wait(lock, [&]() {
|
||||
- return !that->internal->fallbackRunning || !that->getMasterModule();
|
||||
- });
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
|
||||
void Engine::startFallbackThread() {
|
||||
- if (internal->fallbackThread.joinable())
|
||||
- return;
|
||||
-
|
||||
- internal->fallbackRunning = true;
|
||||
- internal->fallbackThread = std::thread(Engine_fallbackRun, this);
|
||||
}
|
||||
|
||||
|
704
src/override/diffs/MenuBar.cpp.diff
Normal file
704
src/override/diffs/MenuBar.cpp.diff
Normal file
|
@ -0,0 +1,704 @@
|
|||
--- ../Rack/src/app/MenuBar.cpp 2022-01-15 14:44:46.391280963 +0000
|
||||
+++ MenuBar.cpp 2022-01-23 17:13:16.500279828 +0000
|
||||
@@ -1,8 +1,33 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's app/MenuBar.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
-#include <osdialog.h>
|
||||
-
|
||||
#include <app/MenuBar.hpp>
|
||||
#include <app/TipWindow.hpp>
|
||||
#include <widget/OpaqueWidget.hpp>
|
||||
@@ -25,6 +50,11 @@
|
||||
#include <patch.hpp>
|
||||
#include <library.hpp>
|
||||
|
||||
+#ifdef HAVE_LIBLO
|
||||
+# include <lo/lo.h>
|
||||
+#endif
|
||||
+
|
||||
+#include "../CardinalCommon.hpp"
|
||||
|
||||
namespace rack {
|
||||
namespace app {
|
||||
@@ -48,80 +78,108 @@
|
||||
};
|
||||
|
||||
|
||||
-struct NotificationIcon : widget::Widget {
|
||||
- void draw(const DrawArgs& args) override {
|
||||
- nvgBeginPath(args.vg);
|
||||
- float radius = 4;
|
||||
- nvgCircle(args.vg, radius, radius, radius);
|
||||
- nvgFillColor(args.vg, nvgRGBf(1.0, 0.0, 0.0));
|
||||
- nvgFill(args.vg);
|
||||
- nvgStrokeColor(args.vg, nvgRGBf(0.5, 0.0, 0.0));
|
||||
- nvgStroke(args.vg);
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
////////////////////
|
||||
// File
|
||||
////////////////////
|
||||
|
||||
|
||||
struct FileButton : MenuButton {
|
||||
+ const bool isStandalone;
|
||||
+
|
||||
+#ifdef HAVE_LIBLO
|
||||
+ bool oscConnected = false;
|
||||
+ lo_server oscServer = nullptr;
|
||||
+
|
||||
+ static int osc_handler(const char* const path, const char* const types, lo_arg** argv, const int argc, lo_message, void* const self)
|
||||
+ {
|
||||
+ d_stdout("osc_handler(\"%s\", \"%s\", %p, %i)", path, types, argv, argc);
|
||||
+
|
||||
+ if (std::strcmp(path, "/resp") == 0 && argc == 2 && types[0] == 's' && types[1] == 's') {
|
||||
+ d_stdout("osc_handler(\"%s\", ...) - got resp | '%s' '%s'", path, &argv[0]->s, &argv[1]->s);
|
||||
+ if (std::strcmp(&argv[0]->s, "hello") == 0 && std::strcmp(&argv[1]->s, "ok") == 0)
|
||||
+ static_cast<FileButton*>(self)->oscConnected = true;
|
||||
+ }
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ~FileButton() {
|
||||
+ lo_server_free(oscServer);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ FileButton(const bool standalone)
|
||||
+ : MenuButton(), isStandalone(standalone) {}
|
||||
+
|
||||
void onAction(const ActionEvent& e) override {
|
||||
ui::Menu* menu = createMenu();
|
||||
menu->cornerFlags = BND_CORNER_TOP;
|
||||
menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y));
|
||||
|
||||
menu->addChild(createMenuItem("New", RACK_MOD_CTRL_NAME "+N", []() {
|
||||
- APP->patch->loadTemplateDialog();
|
||||
+ patchUtils::loadTemplateDialog();
|
||||
}));
|
||||
|
||||
- menu->addChild(createMenuItem("Open", RACK_MOD_CTRL_NAME "+O", []() {
|
||||
- APP->patch->loadDialog();
|
||||
+ menu->addChild(createMenuItem("Open / Import...", RACK_MOD_CTRL_NAME "+O", []() {
|
||||
+ patchUtils::loadDialog();
|
||||
}));
|
||||
|
||||
- menu->addChild(createSubmenuItem("Open recent", "", [](ui::Menu* menu) {
|
||||
- for (const std::string& path : settings::recentPatchPaths) {
|
||||
- std::string name = system::getStem(path);
|
||||
- menu->addChild(createMenuItem(name, "", [=]() {
|
||||
- APP->patch->loadPathDialog(path);
|
||||
- }));
|
||||
- }
|
||||
- }, settings::recentPatchPaths.empty()));
|
||||
-
|
||||
menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() {
|
||||
- APP->patch->saveDialog();
|
||||
- }));
|
||||
-
|
||||
- menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() {
|
||||
- APP->patch->saveAsDialog();
|
||||
+ // NOTE: will do nothing if path is empty, intentionally
|
||||
+ patchUtils::saveDialog(APP->patch->path);
|
||||
+ }, APP->patch->path.empty()));
|
||||
+
|
||||
+ menu->addChild(createMenuItem("Save as / Export...", RACK_MOD_CTRL_NAME "+Shift+S", []() {
|
||||
+ patchUtils::saveAsDialog();
|
||||
}));
|
||||
|
||||
- menu->addChild(createMenuItem("Save a copy", "", []() {
|
||||
- APP->patch->saveAsDialog(false);
|
||||
- }));
|
||||
+#ifdef HAVE_LIBLO
|
||||
+ if (oscServer == nullptr || !oscConnected) {
|
||||
+ menu->addChild(createMenuItem("Connect to MOD", "", [this]() {
|
||||
+ if (oscServer == nullptr) {
|
||||
+ oscServer = lo_server_new_with_proto(nullptr, LO_UDP, nullptr);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr,);
|
||||
+ lo_server_add_method(oscServer, "/resp", nullptr, osc_handler, this);
|
||||
+ }
|
||||
+ const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);
|
||||
+ lo_send(addr, "/hello", "");
|
||||
+ lo_address_free(addr);
|
||||
+ }));
|
||||
+ } else {
|
||||
+ menu->addChild(createMenuItem("Deploy to MOD", "F7", []() {
|
||||
+ patchUtils::deployToMOD();
|
||||
+ }));
|
||||
+ }
|
||||
+#endif
|
||||
|
||||
menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() {
|
||||
- APP->patch->revertDialog();
|
||||
- }, APP->patch->path == ""));
|
||||
-
|
||||
- menu->addChild(createMenuItem("Overwrite template", "", []() {
|
||||
- APP->patch->saveTemplateDialog();
|
||||
- }));
|
||||
+ patchUtils::revertDialog();
|
||||
+ }, APP->patch->path.empty()));
|
||||
|
||||
menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
// Load selection
|
||||
menu->addChild(createMenuItem("Import selection", "", [=]() {
|
||||
- APP->scene->rack->loadSelectionDialog();
|
||||
+ patchUtils::loadSelectionDialog();
|
||||
}, false, true));
|
||||
|
||||
- menu->addChild(new ui::MenuSeparator);
|
||||
+ if (isStandalone) {
|
||||
+ menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
- menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() {
|
||||
- APP->window->close();
|
||||
- }));
|
||||
+ menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() {
|
||||
+ APP->window->close();
|
||||
+ }));
|
||||
+ };
|
||||
}
|
||||
+
|
||||
+#ifdef HAVE_LIBLO
|
||||
+ void step() override {
|
||||
+ MenuButton::step();
|
||||
+ if (oscServer != nullptr) {
|
||||
+ while (lo_server_recv_noblock(oscServer, 0) != 0) {}
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -166,7 +224,7 @@
|
||||
|
||||
menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
- APP->scene->rack->appendSelectionContextMenu(menu);
|
||||
+ patchUtils::appendSelectionContextMenu(menu);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -256,7 +314,7 @@
|
||||
return settings::cableTension;
|
||||
}
|
||||
float getDefaultValue() override {
|
||||
- return 0.5;
|
||||
+ return 0.75;
|
||||
}
|
||||
float getDisplayValue() override {
|
||||
return getValue() * 100;
|
||||
@@ -421,28 +479,9 @@
|
||||
haloBrightnessSlider->box.size.x = 250.0;
|
||||
menu->addChild(haloBrightnessSlider);
|
||||
|
||||
- double frameRate = APP->window->getMonitorRefreshRate() / settings::frameSwapInterval;
|
||||
- menu->addChild(createSubmenuItem("Frame rate", string::f("%.0f Hz", frameRate), [=](ui::Menu* menu) {
|
||||
- for (int i = 1; i <= 6; i++) {
|
||||
- double frameRate = APP->window->getMonitorRefreshRate() / i;
|
||||
- menu->addChild(createCheckMenuItem(string::f("%.0f Hz", frameRate), "",
|
||||
- [=]() {return settings::frameSwapInterval == i;},
|
||||
- [=]() {settings::frameSwapInterval = i;}
|
||||
- ));
|
||||
- }
|
||||
- }));
|
||||
-
|
||||
- bool fullscreen = APP->window->isFullScreen();
|
||||
- std::string fullscreenText = "F11";
|
||||
- if (fullscreen)
|
||||
- fullscreenText += " " CHECKMARK_STRING;
|
||||
- menu->addChild(createMenuItem("Fullscreen", fullscreenText, [=]() {
|
||||
- APP->window->setFullScreen(!fullscreen);
|
||||
- }));
|
||||
-
|
||||
menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
- menu->addChild(createBoolPtrMenuItem("Lock cursor while dragging params", "", &settings::allowCursorLock));
|
||||
+ // menu->addChild(createBoolPtrMenuItem("Hide cursor while dragging", "", &settings::allowCursorLock));
|
||||
|
||||
static const std::vector<std::string> knobModeLabels = {
|
||||
"Linear",
|
||||
@@ -467,6 +506,21 @@
|
||||
menu->addChild(knobScrollSensitivitySlider);
|
||||
|
||||
menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules));
|
||||
+
|
||||
+ static const std::vector<std::string> rateLimitLabels = {
|
||||
+ "None",
|
||||
+ "2x",
|
||||
+ "4x",
|
||||
+ };
|
||||
+ static const std::vector<int> rateLimits = {0, 1, 2};
|
||||
+ menu->addChild(createSubmenuItem("Update rate limit", rateLimitLabels[settings::rateLimit], [=](ui::Menu* menu) {
|
||||
+ for (int rateLimit : rateLimits) {
|
||||
+ menu->addChild(createCheckMenuItem(rateLimitLabels[rateLimit], "",
|
||||
+ [=]() {return settings::rateLimit == rateLimit;},
|
||||
+ [=]() {settings::rateLimit = rateLimit;}
|
||||
+ ));
|
||||
+ }
|
||||
+ }));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -476,47 +530,6 @@
|
||||
////////////////////
|
||||
|
||||
|
||||
-struct SampleRateItem : ui::MenuItem {
|
||||
- ui::Menu* createChildMenu() override {
|
||||
- ui::Menu* menu = new ui::Menu;
|
||||
-
|
||||
- // Auto sample rate
|
||||
- std::string rightText;
|
||||
- if (settings::sampleRate == 0) {
|
||||
- float sampleRate = APP->engine->getSampleRate();
|
||||
- rightText += string::f("(%g kHz) ", sampleRate / 1000.f);
|
||||
- }
|
||||
- menu->addChild(createCheckMenuItem("Auto", rightText,
|
||||
- [=]() {return settings::sampleRate == 0;},
|
||||
- [=]() {settings::sampleRate = 0;}
|
||||
- ));
|
||||
-
|
||||
- // Power-of-2 oversample times 44.1kHz or 48kHz
|
||||
- for (int i = -2; i <= 4; i++) {
|
||||
- for (int j = 0; j < 2; j++) {
|
||||
- float oversample = std::pow(2.f, i);
|
||||
- float sampleRate = (j == 0) ? 44100.f : 48000.f;
|
||||
- sampleRate *= oversample;
|
||||
-
|
||||
- std::string text = string::f("%g kHz", sampleRate / 1000.f);
|
||||
- std::string rightText;
|
||||
- if (oversample > 1.f) {
|
||||
- rightText += string::f("(%.0fx)", oversample);
|
||||
- }
|
||||
- else if (oversample < 1.f) {
|
||||
- rightText += string::f("(1/%.0fx)", 1.f / oversample);
|
||||
- }
|
||||
- menu->addChild(createCheckMenuItem(text, rightText,
|
||||
- [=]() {return settings::sampleRate == sampleRate;},
|
||||
- [=]() {settings::sampleRate = sampleRate;}
|
||||
- ));
|
||||
- }
|
||||
- }
|
||||
- return menu;
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
struct EngineButton : MenuButton {
|
||||
void onAction(const ActionEvent& e) override {
|
||||
ui::Menu* menu = createMenu();
|
||||
@@ -529,269 +542,6 @@
|
||||
menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() {
|
||||
settings::cpuMeter ^= true;
|
||||
}));
|
||||
-
|
||||
- menu->addChild(createMenuItem<SampleRateItem>("Sample rate", RIGHT_ARROW));
|
||||
-
|
||||
- menu->addChild(createSubmenuItem("Threads", string::f("%d", settings::threadCount), [=](ui::Menu* menu) {
|
||||
- // BUG This assumes SMT is enabled.
|
||||
- int cores = system::getLogicalCoreCount() / 2;
|
||||
-
|
||||
- for (int i = 1; i <= 2 * cores; i++) {
|
||||
- std::string rightText;
|
||||
- if (i == cores)
|
||||
- rightText += "(most modules)";
|
||||
- else if (i == 1)
|
||||
- rightText += "(lowest CPU usage)";
|
||||
- menu->addChild(createCheckMenuItem(string::f("%d", i), rightText,
|
||||
- [=]() {return settings::threadCount == i;},
|
||||
- [=]() {settings::threadCount = i;}
|
||||
- ));
|
||||
- }
|
||||
- }));
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-////////////////////
|
||||
-// Plugins
|
||||
-////////////////////
|
||||
-
|
||||
-
|
||||
-struct AccountPasswordField : ui::PasswordField {
|
||||
- ui::MenuItem* logInItem;
|
||||
- void onAction(const ActionEvent& e) override {
|
||||
- logInItem->doAction();
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct LogInItem : ui::MenuItem {
|
||||
- ui::TextField* emailField;
|
||||
- ui::TextField* passwordField;
|
||||
-
|
||||
- void onAction(const ActionEvent& e) override {
|
||||
- std::string email = emailField->text;
|
||||
- std::string password = passwordField->text;
|
||||
- std::thread t([=] {
|
||||
- library::logIn(email, password);
|
||||
- library::checkUpdates();
|
||||
- });
|
||||
- t.detach();
|
||||
- e.unconsume();
|
||||
- }
|
||||
-
|
||||
- void step() override {
|
||||
- text = "Log in";
|
||||
- rightText = library::loginStatus;
|
||||
- MenuItem::step();
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct SyncUpdatesItem : ui::MenuItem {
|
||||
- void step() override {
|
||||
- if (library::updateStatus != "") {
|
||||
- text = library::updateStatus;
|
||||
- }
|
||||
- else if (library::isSyncing) {
|
||||
- text = "Updating...";
|
||||
- }
|
||||
- else if (!library::hasUpdates()) {
|
||||
- text = "Up-to-date";
|
||||
- }
|
||||
- else {
|
||||
- text = "Update all";
|
||||
- }
|
||||
-
|
||||
- disabled = library::isSyncing || !library::hasUpdates();
|
||||
- MenuItem::step();
|
||||
- }
|
||||
-
|
||||
- void onAction(const ActionEvent& e) override {
|
||||
- std::thread t([=] {
|
||||
- library::syncUpdates();
|
||||
- });
|
||||
- t.detach();
|
||||
- e.unconsume();
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct SyncUpdateItem : ui::MenuItem {
|
||||
- std::string slug;
|
||||
-
|
||||
- void setUpdate(const std::string& slug) {
|
||||
- this->slug = slug;
|
||||
-
|
||||
- auto it = library::updateInfos.find(slug);
|
||||
- if (it == library::updateInfos.end())
|
||||
- return;
|
||||
- library::UpdateInfo update = it->second;
|
||||
-
|
||||
- text = update.name;
|
||||
- }
|
||||
-
|
||||
- ui::Menu* createChildMenu() override {
|
||||
- auto it = library::updateInfos.find(slug);
|
||||
- if (it == library::updateInfos.end())
|
||||
- return NULL;
|
||||
- library::UpdateInfo update = it->second;
|
||||
-
|
||||
- if (update.changelogUrl == "")
|
||||
- return NULL;
|
||||
-
|
||||
- ui::Menu* menu = new ui::Menu;
|
||||
-
|
||||
- std::string changelogUrl = update.changelogUrl;
|
||||
- menu->addChild(createMenuItem("Changelog", "", [=]() {
|
||||
- system::openBrowser(changelogUrl);
|
||||
- }));
|
||||
-
|
||||
- return menu;
|
||||
- }
|
||||
-
|
||||
- void step() override {
|
||||
- disabled = library::isSyncing;
|
||||
-
|
||||
- auto it = library::updateInfos.find(slug);
|
||||
- if (it != library::updateInfos.end()) {
|
||||
- library::UpdateInfo update = it->second;
|
||||
-
|
||||
- if (update.downloaded) {
|
||||
- rightText = CHECKMARK_STRING;
|
||||
- disabled = true;
|
||||
- }
|
||||
- else if (slug == library::updateSlug) {
|
||||
- rightText = string::f("%.0f%%", library::updateProgress * 100.f);
|
||||
- }
|
||||
- else {
|
||||
- rightText = "";
|
||||
- plugin::Plugin* p = plugin::getPlugin(slug);
|
||||
- if (p) {
|
||||
- rightText += p->version + " → ";
|
||||
- }
|
||||
- rightText += update.version;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- MenuItem::step();
|
||||
- }
|
||||
-
|
||||
- void onAction(const ActionEvent& e) override {
|
||||
- std::thread t([=] {
|
||||
- library::syncUpdate(slug);
|
||||
- });
|
||||
- t.detach();
|
||||
- e.unconsume();
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct LibraryMenu : ui::Menu {
|
||||
- LibraryMenu() {
|
||||
- refresh();
|
||||
- }
|
||||
-
|
||||
- void step() override {
|
||||
- // Refresh menu when appropriate
|
||||
- if (library::refreshRequested) {
|
||||
- library::refreshRequested = false;
|
||||
- refresh();
|
||||
- }
|
||||
- Menu::step();
|
||||
- }
|
||||
-
|
||||
- void refresh() {
|
||||
- setChildMenu(NULL);
|
||||
- clearChildren();
|
||||
-
|
||||
- if (settings::devMode) {
|
||||
- addChild(createMenuLabel("Disabled in development mode"));
|
||||
- }
|
||||
- else if (!library::isLoggedIn()) {
|
||||
- addChild(createMenuItem("Register VCV account", "", [=]() {
|
||||
- system::openBrowser("https://vcvrack.com/login");
|
||||
- }));
|
||||
-
|
||||
- ui::TextField* emailField = new ui::TextField;
|
||||
- emailField->placeholder = "Email";
|
||||
- emailField->box.size.x = 240.0;
|
||||
- addChild(emailField);
|
||||
-
|
||||
- AccountPasswordField* passwordField = new AccountPasswordField;
|
||||
- passwordField->placeholder = "Password";
|
||||
- passwordField->box.size.x = 240.0;
|
||||
- passwordField->nextField = emailField;
|
||||
- emailField->nextField = passwordField;
|
||||
- addChild(passwordField);
|
||||
-
|
||||
- LogInItem* logInItem = new LogInItem;
|
||||
- logInItem->emailField = emailField;
|
||||
- logInItem->passwordField = passwordField;
|
||||
- passwordField->logInItem = logInItem;
|
||||
- addChild(logInItem);
|
||||
- }
|
||||
- else {
|
||||
- addChild(createMenuItem("Log out", "", [=]() {
|
||||
- library::logOut();
|
||||
- }));
|
||||
-
|
||||
- addChild(createMenuItem("Browse VCV Library", "", [=]() {
|
||||
- system::openBrowser("https://library.vcvrack.com/");
|
||||
- }));
|
||||
-
|
||||
- SyncUpdatesItem* syncItem = new SyncUpdatesItem;
|
||||
- syncItem->text = "Update all";
|
||||
- addChild(syncItem);
|
||||
-
|
||||
- if (!library::updateInfos.empty()) {
|
||||
- addChild(new ui::MenuSeparator);
|
||||
- addChild(createMenuLabel("Updates"));
|
||||
-
|
||||
- for (auto& pair : library::updateInfos) {
|
||||
- SyncUpdateItem* updateItem = new SyncUpdateItem;
|
||||
- updateItem->setUpdate(pair.first);
|
||||
- addChild(updateItem);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-
|
||||
-struct LibraryButton : MenuButton {
|
||||
- NotificationIcon* notification;
|
||||
-
|
||||
- LibraryButton() {
|
||||
- notification = new NotificationIcon;
|
||||
- addChild(notification);
|
||||
- }
|
||||
-
|
||||
- void onAction(const ActionEvent& e) override {
|
||||
- ui::Menu* menu = createMenu<LibraryMenu>();
|
||||
- menu->cornerFlags = BND_CORNER_TOP;
|
||||
- menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y));
|
||||
- // Check for updates when menu is opened
|
||||
- std::thread t([&]() {
|
||||
- system::setThreadName("Library");
|
||||
- library::checkUpdates();
|
||||
- });
|
||||
- t.detach();
|
||||
- }
|
||||
-
|
||||
- void step() override {
|
||||
- notification->box.pos = math::Vec(0, 0);
|
||||
- notification->visible = library::hasUpdates();
|
||||
-
|
||||
- // Popup when updates finish downloading
|
||||
- if (library::restartRequested) {
|
||||
- library::restartRequested = false;
|
||||
- if (osdialog_message(OSDIALOG_INFO, OSDIALOG_OK_CANCEL, "All plugins have been downloaded. Close and re-launch Rack to load new updates.")) {
|
||||
- APP->window->close();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- MenuButton::step();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -802,63 +552,24 @@
|
||||
|
||||
|
||||
struct HelpButton : MenuButton {
|
||||
- NotificationIcon* notification;
|
||||
-
|
||||
- HelpButton() {
|
||||
- notification = new NotificationIcon;
|
||||
- addChild(notification);
|
||||
- }
|
||||
-
|
||||
void onAction(const ActionEvent& e) override {
|
||||
ui::Menu* menu = createMenu();
|
||||
menu->cornerFlags = BND_CORNER_TOP;
|
||||
menu->box.pos = getAbsoluteOffset(math::Vec(0, box.size.y));
|
||||
|
||||
- menu->addChild(createMenuItem("Tips", "", [=]() {
|
||||
- APP->scene->addChild(tipWindowCreate());
|
||||
- }));
|
||||
-
|
||||
- menu->addChild(createMenuItem("User manual", "F1", [=]() {
|
||||
+ menu->addChild(createMenuItem("Rack User manual", "F1", [=]() {
|
||||
system::openBrowser("https://vcvrack.com/manual/");
|
||||
}));
|
||||
|
||||
- menu->addChild(createMenuItem("VCVRack.com", "", [=]() {
|
||||
- system::openBrowser("https://vcvrack.com/");
|
||||
- }));
|
||||
-
|
||||
- menu->addChild(createMenuItem("Open user folder", "", [=]() {
|
||||
- system::openDirectory(asset::user(""));
|
||||
+ menu->addChild(createMenuItem("Cardinal Project page", "", [=]() {
|
||||
+ system::openBrowser("https://github.com/DISTRHO/Cardinal/");
|
||||
}));
|
||||
|
||||
- if (library::isAppUpdateAvailable()) {
|
||||
- menu->addChild(new ui::MenuSeparator);
|
||||
-
|
||||
- menu->addChild(createMenuItem("Update " + APP_NAME, APP_VERSION + " → " + library::appVersion, [=]() {
|
||||
- system::openBrowser(library::appDownloadUrl);
|
||||
- }));
|
||||
-
|
||||
- menu->addChild(createMenuItem("Review changelog", "", [=]() {
|
||||
- system::openBrowser(library::appChangelogUrl);
|
||||
- }));
|
||||
- }
|
||||
- else if (!settings::autoCheckUpdates && !settings::devMode) {
|
||||
- menu->addChild(createMenuItem("Check for " + APP_NAME + " update", "", [=]() {
|
||||
- std::thread t([&]() {
|
||||
- library::checkAppUpdate();
|
||||
- });
|
||||
- t.detach();
|
||||
- }, false, true));
|
||||
- }
|
||||
-
|
||||
menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
- menu->addChild(createMenuLabel(APP_NAME + " " + APP_EDITION_NAME + " " + APP_VERSION));
|
||||
- }
|
||||
+ menu->addChild(createMenuLabel(APP_EDITION + " " + APP_EDITION_NAME));
|
||||
|
||||
- void step() override {
|
||||
- notification->box.pos = math::Vec(0, 0);
|
||||
- notification->visible = library::isAppUpdateAvailable();
|
||||
- MenuButton::step();
|
||||
+ menu->addChild(createMenuLabel("Rack " + APP_VERSION + " Compatible"));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -908,7 +619,9 @@
|
||||
struct MenuBar : widget::OpaqueWidget {
|
||||
MeterLabel* meterLabel;
|
||||
|
||||
- MenuBar() {
|
||||
+ MenuBar(const bool isStandalone)
|
||||
+ : widget::OpaqueWidget()
|
||||
+ {
|
||||
const float margin = 5;
|
||||
box.size.y = BND_WIDGET_HEIGHT + 2 * margin;
|
||||
|
||||
@@ -917,7 +630,7 @@
|
||||
layout->spacing = math::Vec(0, 0);
|
||||
addChild(layout);
|
||||
|
||||
- FileButton* fileButton = new FileButton;
|
||||
+ FileButton* fileButton = new FileButton(isStandalone);
|
||||
fileButton->text = "File";
|
||||
layout->addChild(fileButton);
|
||||
|
||||
@@ -933,10 +646,6 @@
|
||||
engineButton->text = "Engine";
|
||||
layout->addChild(engineButton);
|
||||
|
||||
- LibraryButton* libraryButton = new LibraryButton;
|
||||
- libraryButton->text = "Library";
|
||||
- layout->addChild(libraryButton);
|
||||
-
|
||||
HelpButton* helpButton = new HelpButton;
|
||||
helpButton->text = "Help";
|
||||
layout->addChild(helpButton);
|
||||
@@ -971,7 +680,11 @@
|
||||
|
||||
|
||||
widget::Widget* createMenuBar() {
|
||||
- menuBar::MenuBar* menuBar = new menuBar::MenuBar;
|
||||
+ return new widget::Widget;
|
||||
+}
|
||||
+
|
||||
+widget::Widget* createMenuBar(const bool isStandalone) {
|
||||
+ menuBar::MenuBar* menuBar = new menuBar::MenuBar(isStandalone);
|
||||
return menuBar;
|
||||
}
|
||||
|
129
src/override/diffs/Model.cpp.diff
Normal file
129
src/override/diffs/Model.cpp.diff
Normal file
|
@ -0,0 +1,129 @@
|
|||
--- ../Rack/src/plugin/Model.cpp 2021-10-17 13:57:23.257633662 +0100
|
||||
+++ Model.cpp 2022-01-23 17:13:22.080013846 +0000
|
||||
@@ -1,3 +1,30 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's plugin/Model.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <algorithm>
|
||||
|
||||
#include <plugin/Model.hpp>
|
||||
@@ -17,7 +44,7 @@
|
||||
|
||||
|
||||
void Model::fromJson(json_t* rootJ) {
|
||||
- assert(plugin);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(plugin != nullptr,);
|
||||
|
||||
json_t* nameJ = json_object_get(rootJ, "name");
|
||||
if (nameJ)
|
||||
@@ -54,11 +81,6 @@
|
||||
if (manualUrlJ)
|
||||
manualUrl = json_string_value(manualUrlJ);
|
||||
|
||||
- // modularGridUrl
|
||||
- json_t* modularGridUrlJ = json_object_get(rootJ, "modularGridUrl");
|
||||
- if (modularGridUrlJ)
|
||||
- modularGridUrl = json_string_value(modularGridUrlJ);
|
||||
-
|
||||
// hidden
|
||||
json_t* hiddenJ = json_object_get(rootJ, "hidden");
|
||||
// Use `disabled` as an alias which was deprecated in Rack 2.0
|
||||
@@ -73,7 +95,7 @@
|
||||
|
||||
|
||||
std::string Model::getFullName() {
|
||||
- assert(plugin);
|
||||
+ DISTRHO_SAFE_ASSERT_RETURN(plugin, {});
|
||||
return plugin->getBrand() + " " + name;
|
||||
}
|
||||
|
||||
@@ -95,7 +117,7 @@
|
||||
}
|
||||
|
||||
|
||||
-void Model::appendContextMenu(ui::Menu* menu, bool inBrowser) {
|
||||
+void Model::appendContextMenu(ui::Menu* menu, bool) {
|
||||
// plugin
|
||||
menu->addChild(createMenuItem("Plugin: " + plugin->name, "", [=]() {
|
||||
system::openBrowser(plugin->pluginUrl);
|
||||
@@ -132,18 +154,6 @@
|
||||
|
||||
menu->addChild(new ui::MenuSeparator);
|
||||
|
||||
- // VCV Library page
|
||||
- menu->addChild(createMenuItem("VCV Library page", "", [=]() {
|
||||
- system::openBrowser("https://library.vcvrack.com/" + plugin->slug + "/" + slug);
|
||||
- }));
|
||||
-
|
||||
- // modularGridUrl
|
||||
- if (modularGridUrl != "") {
|
||||
- menu->addChild(createMenuItem("ModularGrid page", "", [=]() {
|
||||
- system::openBrowser(modularGridUrl);
|
||||
- }));
|
||||
- }
|
||||
-
|
||||
// manual
|
||||
std::string manualUrl = getManualUrl();
|
||||
if (manualUrl != "") {
|
||||
@@ -172,35 +182,15 @@
|
||||
system::openBrowser(plugin->changelogUrl);
|
||||
}));
|
||||
}
|
||||
-
|
||||
- // plugin folder
|
||||
- if (plugin->path != "") {
|
||||
- menu->addChild(createMenuItem("Open plugin folder", "", [=]() {
|
||||
- system::openDirectory(plugin->path);
|
||||
- }));
|
||||
- }
|
||||
-
|
||||
- // Favorite
|
||||
- std::string favoriteRightText = inBrowser ? (RACK_MOD_CTRL_NAME "+click") : "";
|
||||
- if (isFavorite())
|
||||
- favoriteRightText += " " CHECKMARK_STRING;
|
||||
- menu->addChild(createMenuItem("Favorite", favoriteRightText,
|
||||
- [=]() {
|
||||
- setFavorite(!isFavorite());
|
||||
- }
|
||||
- ));
|
||||
}
|
||||
|
||||
|
||||
bool Model::isFavorite() {
|
||||
- const settings::ModuleInfo* mi = settings::getModuleInfo(plugin->slug, slug);
|
||||
- return mi && mi->favorite;
|
||||
+ return false;
|
||||
}
|
||||
|
||||
|
||||
-void Model::setFavorite(bool favorite) {
|
||||
- settings::ModuleInfo& mi = settings::moduleInfos[plugin->slug][slug];
|
||||
- mi.favorite = favorite;
|
||||
+void Model::setFavorite(bool) {
|
||||
}
|
||||
|
||||
|
234
src/override/diffs/Scene.cpp.diff
Normal file
234
src/override/diffs/Scene.cpp.diff
Normal file
|
@ -0,0 +1,234 @@
|
|||
--- ../Rack/src/app/Scene.cpp 2021-12-14 21:35:44.414568198 +0000
|
||||
+++ Scene.cpp 2022-01-23 17:13:24.715889665 +0000
|
||||
@@ -1,3 +1,30 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's app/Scene.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <thread>
|
||||
|
||||
#include <osdialog.h>
|
||||
@@ -14,31 +41,49 @@
|
||||
#include <patch.hpp>
|
||||
#include <asset.hpp>
|
||||
|
||||
+#include "../CardinalCommon.hpp"
|
||||
+
|
||||
|
||||
namespace rack {
|
||||
namespace app {
|
||||
|
||||
|
||||
struct ResizeHandle : widget::OpaqueWidget {
|
||||
- math::Vec size;
|
||||
-
|
||||
void draw(const DrawArgs& args) override {
|
||||
+ nvgStrokeColor(args.vg, nvgRGBf(1, 1, 1));
|
||||
+ nvgStrokeWidth(args.vg, 1);
|
||||
+
|
||||
nvgBeginPath(args.vg);
|
||||
- nvgMoveTo(args.vg, box.size.x, box.size.y);
|
||||
+ nvgMoveTo(args.vg, box.size.x, 0);
|
||||
nvgLineTo(args.vg, 0, box.size.y);
|
||||
- nvgLineTo(args.vg, box.size.x, 0);
|
||||
- nvgClosePath(args.vg);
|
||||
- nvgFillColor(args.vg, nvgRGBAf(1, 1, 1, 0.15));
|
||||
- nvgFill(args.vg);
|
||||
- }
|
||||
+ nvgStroke(args.vg);
|
||||
|
||||
- void onDragStart(const DragStartEvent& e) override {
|
||||
- size = APP->window->getSize();
|
||||
- }
|
||||
+ nvgBeginPath(args.vg);
|
||||
+ nvgMoveTo(args.vg, box.size.x + 5, 0);
|
||||
+ nvgLineTo(args.vg, 0, box.size.y + 5);
|
||||
+ nvgStroke(args.vg);
|
||||
+
|
||||
+ nvgBeginPath(args.vg);
|
||||
+ nvgMoveTo(args.vg, box.size.x + 10, 0);
|
||||
+ nvgLineTo(args.vg, 0, box.size.y + 10);
|
||||
+ nvgStroke(args.vg);
|
||||
+
|
||||
+ nvgStrokeColor(args.vg, nvgRGBf(0, 0, 0));
|
||||
+
|
||||
+ nvgBeginPath(args.vg);
|
||||
+ nvgMoveTo(args.vg, box.size.x+1, 0);
|
||||
+ nvgLineTo(args.vg, 0, box.size.y+1);
|
||||
+ nvgStroke(args.vg);
|
||||
|
||||
- void onDragMove(const DragMoveEvent& e) override {
|
||||
- size = size.plus(e.mouseDelta);
|
||||
- APP->window->setSize(size.round());
|
||||
+ nvgBeginPath(args.vg);
|
||||
+ nvgMoveTo(args.vg, box.size.x + 6, 0);
|
||||
+ nvgLineTo(args.vg, 0, box.size.y + 6);
|
||||
+ nvgStroke(args.vg);
|
||||
+
|
||||
+ nvgBeginPath(args.vg);
|
||||
+ nvgMoveTo(args.vg, box.size.x + 11, 0);
|
||||
+ nvgLineTo(args.vg, 0, box.size.y + 11);
|
||||
+ nvgStroke(args.vg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -46,12 +91,15 @@
|
||||
struct Scene::Internal {
|
||||
ResizeHandle* resizeHandle;
|
||||
|
||||
- double lastAutosaveTime = 0.0;
|
||||
-
|
||||
bool heldArrowKeys[4] = {};
|
||||
};
|
||||
|
||||
|
||||
+void hideResizeHandle(Scene* scene) {
|
||||
+ scene->internal->resizeHandle->hide();
|
||||
+}
|
||||
+
|
||||
+
|
||||
Scene::Scene() {
|
||||
internal = new Internal;
|
||||
|
||||
@@ -67,13 +115,8 @@
|
||||
browser->hide();
|
||||
addChild(browser);
|
||||
|
||||
- if (settings::showTipsOnLaunch) {
|
||||
- addChild(tipWindowCreate());
|
||||
- }
|
||||
-
|
||||
internal->resizeHandle = new ResizeHandle;
|
||||
- internal->resizeHandle->box.size = math::Vec(15, 15);
|
||||
- internal->resizeHandle->hide();
|
||||
+ internal->resizeHandle->box.size = math::Vec(16, 16);
|
||||
addChild(internal->resizeHandle);
|
||||
}
|
||||
|
||||
@@ -89,32 +132,13 @@
|
||||
|
||||
|
||||
void Scene::step() {
|
||||
- if (APP->window->isFullScreen()) {
|
||||
- // Expand RackScrollWidget to cover entire screen if fullscreen
|
||||
- rackScroll->box.pos.y = 0;
|
||||
- }
|
||||
- else {
|
||||
- // Always show MenuBar if not fullscreen
|
||||
- menuBar->show();
|
||||
- rackScroll->box.pos.y = menuBar->box.size.y;
|
||||
- }
|
||||
-
|
||||
internal->resizeHandle->box.pos = box.size.minus(internal->resizeHandle->box.size);
|
||||
|
||||
// Resize owned descendants
|
||||
menuBar->box.size.x = box.size.x;
|
||||
+ rackScroll->box.pos.y = menuBar->box.size.y;
|
||||
rackScroll->box.size = box.size.minus(rackScroll->box.pos);
|
||||
|
||||
- // Autosave periodically
|
||||
- if (settings::autosaveInterval > 0.0) {
|
||||
- double time = system::getTime();
|
||||
- if (time - internal->lastAutosaveTime >= settings::autosaveInterval) {
|
||||
- internal->lastAutosaveTime = time;
|
||||
- APP->patch->saveAutosave();
|
||||
- settings::save();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
// Scroll RackScrollWidget with arrow keys
|
||||
math::Vec arrowDelta;
|
||||
if (internal->heldArrowKeys[0]) {
|
||||
@@ -172,7 +196,7 @@
|
||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
|
||||
// DEBUG("key '%d '%c' scancode %d '%c' keyName '%s'", e.key, e.key, e.scancode, e.scancode, e.keyName.c_str());
|
||||
if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
- APP->patch->loadTemplateDialog();
|
||||
+ patchUtils::loadTemplateDialog();
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
@@ -180,19 +204,20 @@
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
- APP->patch->loadDialog();
|
||||
+ patchUtils::loadDialog();
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
|
||||
- APP->patch->revertDialog();
|
||||
+ patchUtils::revertDialog();
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
- APP->patch->saveDialog();
|
||||
+ // NOTE: will do nothing if path is empty, intentionally
|
||||
+ patchUtils::saveDialog(APP->patch->path);
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "s" && (e.mods & RACK_MOD_MASK) == (RACK_MOD_CTRL | GLFW_MOD_SHIFT)) {
|
||||
- APP->patch->saveAsDialog();
|
||||
+ patchUtils::saveAsDialog();
|
||||
e.consume(this);
|
||||
}
|
||||
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
@@ -232,10 +257,8 @@
|
||||
settings::cpuMeter ^= true;
|
||||
e.consume(this);
|
||||
}
|
||||
- if (e.key == GLFW_KEY_F11 && (e.mods & RACK_MOD_MASK) == 0) {
|
||||
- APP->window->setFullScreen(!APP->window->isFullScreen());
|
||||
- // The MenuBar will be hidden when the mouse moves over the RackScrollWidget.
|
||||
- // menuBar->hide();
|
||||
+ if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) {
|
||||
+ patchUtils::deployToMOD();
|
||||
e.consume(this);
|
||||
}
|
||||
|
||||
@@ -326,13 +349,6 @@
|
||||
|
||||
// Key commands that can be overridden by children
|
||||
if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) {
|
||||
- // Alternate key command for exiting fullscreen, since F11 doesn't work reliably on Mac due to "Show desktop" OS binding.
|
||||
- if (e.key == GLFW_KEY_ESCAPE && (e.mods & RACK_MOD_MASK) == 0) {
|
||||
- if (APP->window->isFullScreen()) {
|
||||
- APP->window->setFullScreen(false);
|
||||
- e.consume(this);
|
||||
- }
|
||||
- }
|
||||
if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) {
|
||||
rack->pasteClipboardAction();
|
||||
e.consume(this);
|
||||
@@ -351,7 +367,7 @@
|
||||
std::string extension = system::getExtension(path);
|
||||
|
||||
if (extension == ".vcv") {
|
||||
- APP->patch->loadPathDialog(path);
|
||||
+ patchUtils::loadPathDialog(path);
|
||||
e.consume(this);
|
||||
return;
|
||||
}
|
1052
src/override/diffs/Window.cpp.diff
Normal file
1052
src/override/diffs/Window.cpp.diff
Normal file
File diff suppressed because it is too large
Load diff
29
src/override/diffs/blendish.c.diff
Normal file
29
src/override/diffs/blendish.c.diff
Normal file
|
@ -0,0 +1,29 @@
|
|||
--- ../Rack/dep/oui-blendish/blendish.c 2021-10-17 13:57:24.613620711 +0100
|
||||
+++ blendish.c 2021-12-13 09:36:22.182673256 +0000
|
||||
@@ -61,7 +61,7 @@
|
||||
}
|
||||
|
||||
#else
|
||||
- #define BND_INLINE inline
|
||||
+ #define BND_INLINE static inline
|
||||
#define bnd_fminf(a, b) fminf(a, b)
|
||||
#define bnd_fmaxf(a, b) fmaxf(a, b)
|
||||
#define bnd_fmin(a, b) fmin(a, b)
|
||||
@@ -1061,7 +1061,7 @@
|
||||
// search horizontal position
|
||||
static NVGglyphPosition glyphs[BND_MAX_GLYPHS];
|
||||
int nglyphs = nvgTextGlyphPositions(
|
||||
- ctx, x, y, rows[row].start, rows[row].end + 1, glyphs, BND_MAX_GLYPHS);
|
||||
+ ctx, x, y, rows[row].start, rows[row].end, glyphs, BND_MAX_GLYPHS);
|
||||
int col, p = 0;
|
||||
for (col = 0; col < nglyphs && glyphs[col].x < px; ++col)
|
||||
p = glyphs[col].str - label;
|
||||
@@ -1083,7 +1083,7 @@
|
||||
if (nrows == 0) return;
|
||||
*cx = rows[r].minx;
|
||||
nglyphs = nvgTextGlyphPositions(
|
||||
- ctx, x, y, rows[r].start, rows[r].end+1, glyphs, BND_MAX_GLYPHS);
|
||||
+ ctx, x, y, rows[r].start, rows[r].end, glyphs, BND_MAX_GLYPHS);
|
||||
for (int i=0; i < nglyphs; ++i) {
|
||||
*cx=glyphs[i].x;
|
||||
if (glyphs[i].str == caret) break;
|
69
src/override/diffs/common.cpp.diff
Normal file
69
src/override/diffs/common.cpp.diff
Normal file
|
@ -0,0 +1,69 @@
|
|||
--- ../Rack/src/common.cpp 2021-11-23 19:57:23.719015894 +0000
|
||||
+++ common.cpp 2022-01-23 17:13:08.824652617 +0000
|
||||
@@ -1,6 +1,38 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's common.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <common.hpp>
|
||||
#include <string.hpp>
|
||||
|
||||
+#ifdef NDEBUG
|
||||
+# undef DEBUG
|
||||
+#endif
|
||||
+
|
||||
+#include "DistrhoPluginUtils.hpp"
|
||||
|
||||
#if defined ARCH_WIN
|
||||
#include <windows.h>
|
||||
@@ -14,20 +46,21 @@
|
||||
|
||||
namespace rack {
|
||||
|
||||
-
|
||||
-const std::string APP_NAME = "VCV Rack";
|
||||
-const std::string APP_EDITION = "Free";
|
||||
-const std::string APP_EDITION_NAME = "Free";
|
||||
+const std::string APP_NAME = "Cardinal";
|
||||
+const std::string APP_EDITION = getPluginFormatName();
|
||||
+const std::string APP_EDITION_NAME = "Audio Plugin";
|
||||
const std::string APP_VERSION_MAJOR = "2";
|
||||
-const std::string APP_VERSION = TOSTRING(_APP_VERSION);
|
||||
+const std::string APP_VERSION = "2.0";
|
||||
#if defined ARCH_WIN
|
||||
const std::string APP_OS = "win";
|
||||
#elif ARCH_MAC
|
||||
const std::string APP_OS = "mac";
|
||||
#elif defined ARCH_LIN
|
||||
const std::string APP_OS = "lin";
|
||||
+#else
|
||||
+ #error ARCH_LIN undefined
|
||||
#endif
|
||||
-const std::string API_URL = "https://api.vcvrack.com";
|
||||
+const std::string API_URL = "";
|
||||
|
||||
|
||||
Exception::Exception(const char* format, ...) {
|
57
src/override/diffs/context.cpp.diff
Normal file
57
src/override/diffs/context.cpp.diff
Normal file
|
@ -0,0 +1,57 @@
|
|||
--- ../Rack/src/context.cpp 2022-01-15 14:44:46.391280963 +0000
|
||||
+++ context.cpp 2022-01-23 17:13:11.652514338 +0000
|
||||
@@ -1,3 +1,30 @@
|
||||
+/*
|
||||
+ * DISTRHO Cardinal Plugin
|
||||
+ * Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ * GNU General Public License for more details.
|
||||
+ *
|
||||
+ * For a full copy of the GNU General Public License see the LICENSE file.
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * This file is an edited version of VCVRack's context.cpp
|
||||
+ * Copyright (C) 2016-2021 VCV.
|
||||
+ *
|
||||
+ * This program is free software: you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License as
|
||||
+ * published by the Free Software Foundation; either version 3 of
|
||||
+ * the License, or (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
#include <context.hpp>
|
||||
#include <window/Window.hpp>
|
||||
#include <patch.hpp>
|
||||
@@ -6,9 +33,13 @@
|
||||
#include <history.hpp>
|
||||
#include <settings.hpp>
|
||||
|
||||
+#ifdef NDEBUG
|
||||
+# undef DEBUG
|
||||
+#endif
|
||||
|
||||
-namespace rack {
|
||||
+#include "DistrhoUtils.hpp"
|
||||
|
||||
+namespace rack {
|
||||
|
||||
Context::~Context() {
|
||||
// Deleting NULL is safe in C++.
|
||||
@@ -44,7 +75,7 @@
|
||||
static thread_local Context* threadContext = NULL;
|
||||
|
||||
Context* contextGet() {
|
||||
- assert(threadContext);
|
||||
+ DISTRHO_SAFE_ASSERT(threadContext != nullptr);
|
||||
return threadContext;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue