Signed-off-by: falkTX <falktx@falktx.com>tags/23.02
| @@ -87,11 +87,6 @@ namespace plugin { | |||||
| void initStaticPlugins(); | void initStaticPlugins(); | ||||
| void destroyStaticPlugins(); | void destroyStaticPlugins(); | ||||
| } | } | ||||
| #ifndef HEADLESS | |||||
| namespace window { | |||||
| void WindowInit(Window* window, DISTRHO_NAMESPACE::Plugin* plugin); | |||||
| } | |||||
| #endif | |||||
| } | } | ||||
| START_NAMESPACE_DISTRHO | START_NAMESPACE_DISTRHO | ||||
| @@ -27,53 +27,31 @@ | |||||
| #include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
| #include "AsyncDialog.hpp" | #include "AsyncDialog.hpp" | ||||
| #include "WindowParameters.hpp" | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| namespace rack { | |||||
| namespace app { | |||||
| widget::Widget* createMenuBar(bool isStandalone); | |||||
| } | |||||
| namespace window { | |||||
| void WindowSetPluginRemote(Window* window, NanoTopLevelWidget* tlw); | |||||
| void WindowSetMods(Window* window, int mods); | |||||
| void WindowSetInternalSize(rack::window::Window* window, math::Vec size); | |||||
| } | |||||
| } | |||||
| // -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
| CardinalRemoteUI::CardinalRemoteUI(Window& window, const std::string& templatePath) | CardinalRemoteUI::CardinalRemoteUI(Window& window, const std::string& templatePath) | ||||
| : NanoTopLevelWidget(window) | : NanoTopLevelWidget(window) | ||||
| { | { | ||||
| CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet())); | |||||
| context.nativeWindowId = getWindow().getNativeWindowHandle(); | |||||
| context.tlw = this; | |||||
| window.setIgnoringKeyRepeat(true); | |||||
| context.nativeWindowId = window.getNativeWindowHandle(); | |||||
| const double scaleFactor = getScaleFactor(); | |||||
| CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(rack::contextGet()); | |||||
| context->nativeWindowId = window.getNativeWindowHandle(); | |||||
| context->tlw = this; | |||||
| setGeometryConstraints(648 * scaleFactor, 538 * scaleFactor); | |||||
| // -------------------------------------------------------------------------- | |||||
| if (scaleFactor != 1.0) | |||||
| setSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor); | |||||
| rack::window::WindowSetPluginRemote(context->window, this); | |||||
| rack::window::WindowSetPluginRemote(context.window, this); | |||||
| if (rack::widget::Widget* const menuBar = context.scene->menuBar) | |||||
| if (rack::widget::Widget* const menuBar = context->scene->menuBar) | |||||
| { | { | ||||
| context.scene->removeChild(menuBar); | |||||
| context->scene->removeChild(menuBar); | |||||
| delete menuBar; | delete menuBar; | ||||
| } | } | ||||
| context.scene->menuBar = rack::app::createMenuBar(true); | |||||
| context.scene->addChildBelow(context.scene->menuBar, context.scene->rackScroll); | |||||
| context->scene->menuBar = rack::app::createMenuBar(true); | |||||
| context->scene->addChildBelow(context->scene->menuBar, context->scene->rackScroll); | |||||
| // hide "Browse VCV Library" button | // hide "Browse VCV Library" button | ||||
| rack::widget::Widget* const browser = context.scene->browser->children.back(); | |||||
| rack::widget::Widget* const browser = context->scene->browser->children.back(); | |||||
| rack::widget::Widget* const headerLayout = browser->children.front(); | rack::widget::Widget* const headerLayout = browser->children.front(); | ||||
| rack::widget::Widget* const libraryButton = headerLayout->children.back(); | rack::widget::Widget* const libraryButton = headerLayout->children.back(); | ||||
| libraryButton->hide(); | libraryButton->hide(); | ||||
| @@ -84,46 +62,157 @@ CardinalRemoteUI::CardinalRemoteUI(Window& window, const std::string& templatePa | |||||
| if (rack::asset::systemDir.empty()) | if (rack::asset::systemDir.empty()) | ||||
| { | { | ||||
| errorMessage = "Failed to locate Cardinal plugin bundle.\n" | errorMessage = "Failed to locate Cardinal plugin bundle.\n" | ||||
| "Install Cardinal with its plugin bundle folder intact and try again."; | |||||
| "Install Cardinal with its plugin bundle folder intact and try again."; | |||||
| } | } | ||||
| else if (! rack::system::exists(rack::asset::systemDir)) | else if (! rack::system::exists(rack::asset::systemDir)) | ||||
| { | { | ||||
| errorMessage = rack::string::f("System directory \"%s\" does not exist. " | errorMessage = rack::string::f("System directory \"%s\" does not exist. " | ||||
| "Make sure Cardinal was downloaded and installed correctly.", | |||||
| rack::asset::systemDir.c_str()); | |||||
| "Make sure Cardinal was downloaded and installed correctly.", | |||||
| rack::asset::systemDir.c_str()); | |||||
| } | } | ||||
| if (! errorMessage.empty()) | if (! errorMessage.empty()) | ||||
| { | |||||
| static bool shown = false; | |||||
| asyncDialog::create(errorMessage.c_str()); | |||||
| if (! shown) | |||||
| { | |||||
| shown = true; | |||||
| asyncDialog::create(errorMessage.c_str()); | |||||
| } | |||||
| } | |||||
| context->window->step(); | |||||
| WindowParametersSetCallback(context->window, this); | |||||
| context.window->step(); | |||||
| // -------------------------------------------------------------------------- | |||||
| // WindowParametersSetCallback(context.window, this); | |||||
| addIdleCallback(this); | |||||
| } | } | ||||
| CardinalRemoteUI::~CardinalRemoteUI() | CardinalRemoteUI::~CardinalRemoteUI() | ||||
| { | { | ||||
| CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet())); | |||||
| context.nativeWindowId = 0; | |||||
| removeIdleCallback(this); | |||||
| // -------------------------------------------------------------------------- | |||||
| CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(rack::contextGet()); | |||||
| context->nativeWindowId = 0; | |||||
| if (rack::widget::Widget* const menuBar = context->scene->menuBar) | |||||
| { | |||||
| context->scene->removeChild(menuBar); | |||||
| delete menuBar; | |||||
| } | |||||
| context->scene->menuBar = rack::app::createMenuBar(true); | |||||
| context->scene->addChildBelow(context->scene->menuBar, context->scene->rackScroll); | |||||
| rack::window::WindowSetPluginRemote(context->window, nullptr); | |||||
| } | } | ||||
| void CardinalRemoteUI::onNanoDisplay() | void CardinalRemoteUI::onNanoDisplay() | ||||
| { | { | ||||
| CardinalPluginContext& context(*static_cast<CardinalPluginContext*>(rack::contextGet())); | |||||
| context.window->step(); | |||||
| CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(rack::contextGet()); | |||||
| const ScopedContext sc(context); | |||||
| context->window->step(); | |||||
| } | |||||
| // TODO | |||||
| void CardinalRemoteUI::idleCallback() | |||||
| { | |||||
| /* | |||||
| if (filebrowserhandle != nullptr && fileBrowserIdle(filebrowserhandle)) | |||||
| { | |||||
| { | |||||
| const char* const path = fileBrowserGetPath(filebrowserhandle); | |||||
| const ScopedContext sc(this); | |||||
| filebrowseraction(path != nullptr ? strdup(path) : nullptr); | |||||
| } | |||||
| fileBrowserClose(filebrowserhandle); | |||||
| filebrowseraction = nullptr; | |||||
| filebrowserhandle = nullptr; | |||||
| } | |||||
| */ | |||||
| if (windowParameters.rateLimit != 0 && ++rateLimitStep % (windowParameters.rateLimit * 2)) | |||||
| return; | |||||
| rateLimitStep = 0; | |||||
| repaint(); | repaint(); | ||||
| } | } | ||||
| void CardinalRemoteUI::WindowParametersChanged(const WindowParameterList param, float value) | |||||
| { | |||||
| float mult = 1.0f; | |||||
| switch (param) | |||||
| { | |||||
| case kWindowParameterShowTooltips: | |||||
| windowParameters.tooltips = value > 0.5f; | |||||
| break; | |||||
| case kWindowParameterCableOpacity: | |||||
| mult = 100.0f; | |||||
| windowParameters.cableOpacity = value; | |||||
| break; | |||||
| case kWindowParameterCableTension: | |||||
| mult = 100.0f; | |||||
| windowParameters.cableTension = value; | |||||
| break; | |||||
| case kWindowParameterRackBrightness: | |||||
| mult = 100.0f; | |||||
| windowParameters.rackBrightness = value; | |||||
| break; | |||||
| case kWindowParameterHaloBrightness: | |||||
| mult = 100.0f; | |||||
| windowParameters.haloBrightness = value; | |||||
| break; | |||||
| case kWindowParameterKnobMode: | |||||
| switch (static_cast<int>(value + 0.5f)) | |||||
| { | |||||
| case rack::settings::KNOB_MODE_LINEAR: | |||||
| value = 0; | |||||
| windowParameters.knobMode = rack::settings::KNOB_MODE_LINEAR; | |||||
| break; | |||||
| case rack::settings::KNOB_MODE_ROTARY_ABSOLUTE: | |||||
| value = 1; | |||||
| windowParameters.knobMode = rack::settings::KNOB_MODE_ROTARY_ABSOLUTE; | |||||
| break; | |||||
| case rack::settings::KNOB_MODE_ROTARY_RELATIVE: | |||||
| value = 2; | |||||
| windowParameters.knobMode = rack::settings::KNOB_MODE_ROTARY_RELATIVE; | |||||
| break; | |||||
| } | |||||
| break; | |||||
| case kWindowParameterWheelKnobControl: | |||||
| windowParameters.knobScroll = value > 0.5f; | |||||
| break; | |||||
| case kWindowParameterWheelSensitivity: | |||||
| mult = 1000.0f; | |||||
| windowParameters.knobScrollSensitivity = value; | |||||
| break; | |||||
| case kWindowParameterLockModulePositions: | |||||
| windowParameters.lockModules = value > 0.5f; | |||||
| break; | |||||
| case kWindowParameterUpdateRateLimit: | |||||
| windowParameters.rateLimit = static_cast<int>(value + 0.5f); | |||||
| rateLimitStep = 0; | |||||
| break; | |||||
| case kWindowParameterBrowserSort: | |||||
| windowParameters.browserSort = static_cast<int>(value + 0.5f); | |||||
| break; | |||||
| case kWindowParameterBrowserZoom: | |||||
| windowParameters.browserZoom = value; | |||||
| value = std::pow(2.f, value) * 100.0f; | |||||
| break; | |||||
| case kWindowParameterInvertZoom: | |||||
| windowParameters.invertZoom = value > 0.5f; | |||||
| break; | |||||
| case kWindowParameterSqueezeModulePositions: | |||||
| windowParameters.squeezeModules = value > 0.5f; | |||||
| break; | |||||
| default: | |||||
| return; | |||||
| } | |||||
| // setParameterValue(kModuleParameters + param + 1, value * mult); | |||||
| } | |||||
| // -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
| static int glfwMods(const uint mod) noexcept | static int glfwMods(const uint mod) noexcept | ||||
| @@ -187,6 +276,7 @@ bool CardinalRemoteUI::onMouse(const MouseEvent& ev) | |||||
| #endif | #endif | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| const ScopedContext sc(context, mods); | |||||
| return context->event->handleButton(lastMousePos, button, action, mods); | return context->event->handleButton(lastMousePos, button, action, mods); | ||||
| } | } | ||||
| @@ -198,6 +288,7 @@ bool CardinalRemoteUI::onMotion(const MotionEvent& ev) | |||||
| lastMousePos = mousePos; | lastMousePos = mousePos; | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| const ScopedContext sc(context); | |||||
| return context->event->handleHover(mousePos, mouseDelta); | return context->event->handleHover(mousePos, mouseDelta); | ||||
| } | } | ||||
| @@ -211,6 +302,7 @@ bool CardinalRemoteUI::onScroll(const ScrollEvent& ev) | |||||
| const int mods = glfwMods(ev.mod); | const int mods = glfwMods(ev.mod); | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| const ScopedContext sc(context, mods); | |||||
| return context->event->handleScroll(lastMousePos, scrollDelta); | return context->event->handleScroll(lastMousePos, scrollDelta); | ||||
| } | } | ||||
| @@ -222,6 +314,7 @@ bool CardinalRemoteUI::onCharacterInput(const CharacterInputEvent& ev) | |||||
| const int mods = glfwMods(ev.mod); | const int mods = glfwMods(ev.mod); | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| const ScopedContext sc(context, mods); | |||||
| return context->event->handleText(lastMousePos, ev.character); | return context->event->handleText(lastMousePos, ev.character); | ||||
| } | } | ||||
| @@ -303,6 +396,7 @@ bool CardinalRemoteUI::onKeyboard(const KeyboardEvent& ev) | |||||
| } | } | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| const ScopedContext sc(context, mods); | |||||
| return context->event->handleKey(lastMousePos, key, ev.keycode, action, mods); | return context->event->handleKey(lastMousePos, key, ev.keycode, action, mods); | ||||
| } | } | ||||
| @@ -311,8 +405,7 @@ void CardinalRemoteUI::onResize(const ResizeEvent& ev) | |||||
| NanoTopLevelWidget::onResize(ev); | NanoTopLevelWidget::onResize(ev); | ||||
| CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | CardinalPluginContext* context = static_cast<CardinalPluginContext*>(rack::contextGet()); | ||||
| if (context->window != nullptr) | |||||
| WindowSetInternalSize(context->window, rack::math::Vec(ev.size.getWidth(), ev.size.getHeight())); | |||||
| WindowSetInternalSize(context->window, rack::math::Vec(ev.size.getWidth(), ev.size.getHeight())); | |||||
| } | } | ||||
| // -------------------------------------------------------------------------------------------------------------------- | // -------------------------------------------------------------------------------------------------------------------- | ||||
| @@ -19,12 +19,54 @@ | |||||
| #include "NanoVG.hpp" | #include "NanoVG.hpp" | ||||
| #include "PluginContext.hpp" | #include "PluginContext.hpp" | ||||
| #include "WindowParameters.hpp" | |||||
| #include <app/common.hpp> | |||||
| #include <widget/Widget.hpp> | |||||
| class CardinalRemoteUI : public NanoTopLevelWidget | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| namespace rack { | |||||
| namespace app { | |||||
| widget::Widget* createMenuBar(bool isStandalone); | |||||
| } | |||||
| namespace window { | |||||
| void WindowSetPluginRemote(Window* window, NanoTopLevelWidget* tlw); | |||||
| void WindowSetMods(Window* window, int mods); | |||||
| void WindowSetInternalSize(rack::window::Window* window, math::Vec size); | |||||
| } | |||||
| } | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| class CardinalRemoteUI : public NanoTopLevelWidget, | |||||
| public IdleCallback, | |||||
| public WindowParametersCallback | |||||
| { | { | ||||
| rack::math::Vec lastMousePos; | rack::math::Vec lastMousePos; | ||||
| WindowParameters windowParameters; | |||||
| int rateLimitStep = 0; | |||||
| struct ScopedContext { | |||||
| CardinalPluginContext* const context; | |||||
| ScopedContext(CardinalPluginContext* const c) | |||||
| : context(c) | |||||
| { | |||||
| WindowParametersRestore(context->window); | |||||
| } | |||||
| ScopedContext(CardinalPluginContext* const c, const int mods) | |||||
| : context(c) | |||||
| { | |||||
| rack::window::WindowSetMods(context->window, mods); | |||||
| WindowParametersRestore(context->window); | |||||
| } | |||||
| ~ScopedContext() | |||||
| { | |||||
| WindowParametersSave(context->window); | |||||
| } | |||||
| }; | |||||
| public: | public: | ||||
| explicit CardinalRemoteUI(Window& window, const std::string& templatePath); | explicit CardinalRemoteUI(Window& window, const std::string& templatePath); | ||||
| @@ -32,6 +74,8 @@ public: | |||||
| protected: | protected: | ||||
| void onNanoDisplay() override; | void onNanoDisplay() override; | ||||
| void idleCallback() override; | |||||
| void WindowParametersChanged(const WindowParameterList param, float value) override; | |||||
| bool onMouse(const MouseEvent& ev) override; | bool onMouse(const MouseEvent& ev) override; | ||||
| bool onMotion(const MotionEvent& ev) override; | bool onMotion(const MotionEvent& ev) override; | ||||
| bool onScroll(const ScrollEvent& ev) override; | bool onScroll(const ScrollEvent& ev) override; | ||||
| @@ -41,3 +85,5 @@ protected: | |||||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CardinalRemoteUI) | DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CardinalRemoteUI) | ||||
| }; | }; | ||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| @@ -30,13 +30,24 @@ | |||||
| #include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
| #include <ui/common.hpp> | #include <ui/common.hpp> | ||||
| #include "PluginContext.hpp" | #include "PluginContext.hpp" | ||||
| #include "extra/ScopedValueSetter.hpp" | |||||
| #define CARDINAL_TEMPLATE_NAME "init/main.vcv" | |||||
| extern const std::string CARDINAL_VERSION; | |||||
| namespace rack { | namespace rack { | ||||
| namespace asset { | |||||
| std::string patchesPath(); | |||||
| void destroy(); | |||||
| } | |||||
| namespace engine { | |||||
| void Engine_setAboutToClose(Engine*); | |||||
| } | |||||
| namespace plugin { | namespace plugin { | ||||
| void initStaticPlugins(); | |||||
| void destroyStaticPlugins(); | |||||
| void initStaticPlugins(); | |||||
| void destroyStaticPlugins(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -54,17 +65,32 @@ bool requestBufferSizeChange(uint) { return false; } | |||||
| bool requestMIDI() { return false; } | bool requestMIDI() { return false; } | ||||
| const char* getPluginFormatName() noexcept { return "Remote"; } | const char* getPluginFormatName() noexcept { return "Remote"; } | ||||
| FileBrowserHandle fileBrowserCreate(bool, ulong, double, const FileBrowserOptions&) { return nullptr; } | |||||
| uint32_t Plugin::getBufferSize() const noexcept { return 128; } | uint32_t Plugin::getBufferSize() const noexcept { return 128; } | ||||
| double Plugin::getSampleRate() const noexcept { return 48000; } | double Plugin::getSampleRate() const noexcept { return 48000; } | ||||
| bool Plugin::writeMidiEvent(const MidiEvent&) noexcept { return false; } | bool Plugin::writeMidiEvent(const MidiEvent&) noexcept { return false; } | ||||
| void UI::editParameter(uint, bool) {} | |||||
| void UI::setParameterValue(uint, float) {} | |||||
| void UI::setState(const char*, const char*) {} | |||||
| bool UI::openFileBrowser(const FileBrowserOptions&) { return false; } | |||||
| END_NAMESPACE_DISTRHO | END_NAMESPACE_DISTRHO | ||||
| int main(const int argc, const char* argv[]) | int main(const int argc, const char* argv[]) | ||||
| { | { | ||||
| using namespace rack; | using namespace rack; | ||||
| std::string templatePath, factoryTemplatePath; | |||||
| // -------------------------------------------------------------------------- | |||||
| #ifdef DISTRHO_OS_WASM | |||||
| settings::allowCursorLock = true; | |||||
| #else | |||||
| settings::allowCursorLock = false; | settings::allowCursorLock = false; | ||||
| #endif | |||||
| settings::autoCheckUpdates = false; | settings::autoCheckUpdates = false; | ||||
| settings::autosaveInterval = 0; | settings::autosaveInterval = 0; | ||||
| settings::devMode = true; | settings::devMode = true; | ||||
| @@ -98,20 +124,18 @@ int main(const int argc, const char* argv[]) | |||||
| random::init(); | random::init(); | ||||
| ui::init(); | ui::init(); | ||||
| std::string templatePath; | |||||
| #ifdef CARDINAL_PLUGIN_SOURCE_DIR | #ifdef CARDINAL_PLUGIN_SOURCE_DIR | ||||
| // Make system dir point to source code location as fallback | // Make system dir point to source code location as fallback | ||||
| asset::systemDir = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "Rack"; | asset::systemDir = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "Rack"; | ||||
| asset::bundlePath.clear(); | |||||
| if (system::exists(system::join(asset::systemDir, "res"))) | |||||
| { | |||||
| templatePath = CARDINAL_PLUGIN_SOURCE_DIR DISTRHO_OS_SEP_STR "template.vcv"; | |||||
| } | |||||
| // If source code dir does not exist use install target prefix as system dir | // If source code dir does not exist use install target prefix as system dir | ||||
| else | |||||
| if (!system::exists(system::join(asset::systemDir, "res"))) | |||||
| #endif | #endif | ||||
| { | { | ||||
| #if defined(ARCH_MAC) | |||||
| #if defined(DISTRHO_OS_WASM) | |||||
| asset::systemDir = "/resources"; | |||||
| #elif defined(ARCH_MAC) | |||||
| asset::systemDir = "/Library/Application Support/Cardinal"; | asset::systemDir = "/Library/Application Support/Cardinal"; | ||||
| #elif defined(ARCH_WIN) | #elif defined(ARCH_WIN) | ||||
| const std::string commonprogfiles = getSpecialPath(kSpecialPathCommonProgramFiles); | const std::string commonprogfiles = getSpecialPath(kSpecialPathCommonProgramFiles); | ||||
| @@ -121,33 +145,37 @@ int main(const int argc, const char* argv[]) | |||||
| asset::systemDir = CARDINAL_PLUGIN_PREFIX "/share/cardinal"; | asset::systemDir = CARDINAL_PLUGIN_PREFIX "/share/cardinal"; | ||||
| #endif | #endif | ||||
| if (! asset::systemDir.empty()) | |||||
| { | |||||
| asset::bundlePath = system::join(asset::systemDir, "PluginManifests"); | |||||
| templatePath = system::join(asset::systemDir, "template.vcv"); | |||||
| } | |||||
| asset::bundlePath = system::join(asset::systemDir, "PluginManifests"); | |||||
| } | } | ||||
| asset::userDir = asset::systemDir; | asset::userDir = asset::systemDir; | ||||
| const std::string patchesPath = asset::patchesPath(); | |||||
| #ifdef DISTRHO_OS_WASM | |||||
| templatePath = system::join(patchesPath, CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME); | |||||
| #else | |||||
| templatePath = system::join(patchesPath, CARDINAL_TEMPLATE_NAME); | |||||
| #endif | |||||
| factoryTemplatePath = system::join(patchesPath, CARDINAL_TEMPLATE_NAME); | |||||
| // Log environment | // Log environment | ||||
| INFO("%s %s version %s", APP_NAME.c_str(), APP_EDITION.c_str(), APP_VERSION.c_str()); | |||||
| INFO("%s %s %s, compatible with Rack version %s", APP_NAME.c_str(), APP_EDITION.c_str(), CARDINAL_VERSION.c_str(), APP_VERSION.c_str()); | |||||
| INFO("%s", system::getOperatingSystemInfo().c_str()); | INFO("%s", system::getOperatingSystemInfo().c_str()); | ||||
| // INFO("Binary filename: %s", getBinaryFilename()); | |||||
| INFO("System directory: %s", asset::systemDir.c_str()); | INFO("System directory: %s", asset::systemDir.c_str()); | ||||
| INFO("User directory: %s", asset::userDir.c_str()); | INFO("User directory: %s", asset::userDir.c_str()); | ||||
| INFO("Template patch: %s", templatePath.c_str()); | INFO("Template patch: %s", templatePath.c_str()); | ||||
| INFO("System template patch: %s", factoryTemplatePath.c_str()); | |||||
| // Report to user if something is wrong with the installation | // Report to user if something is wrong with the installation | ||||
| if (asset::systemDir.empty()) | if (asset::systemDir.empty()) | ||||
| { | { | ||||
| d_stderr2("Failed to locate Cardinal plugin bundle.\n" | d_stderr2("Failed to locate Cardinal plugin bundle.\n" | ||||
| "Install Cardinal with its bundle folder intact and try again."); | |||||
| "Install Cardinal with its bundle folder intact and try again."); | |||||
| } | } | ||||
| else if (! system::exists(asset::systemDir)) | else if (! system::exists(asset::systemDir)) | ||||
| { | { | ||||
| d_stderr2("System directory \"%s\" does not exist.\n" | d_stderr2("System directory \"%s\" does not exist.\n" | ||||
| "Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str()); | |||||
| "Make sure Cardinal was downloaded and installed correctly.", asset::systemDir.c_str()); | |||||
| } | } | ||||
| INFO("Initializing plugins"); | INFO("Initializing plugins"); | ||||
| @@ -156,8 +184,10 @@ int main(const int argc, const char* argv[]) | |||||
| INFO("Initializing plugin browser DB"); | INFO("Initializing plugin browser DB"); | ||||
| app::browserInit(); | app::browserInit(); | ||||
| // -------------------------------------------------------------------------- | |||||
| // create unique temporary path for this instance | // create unique temporary path for this instance | ||||
| std::string autosavePath; | |||||
| std::string fAutosavePath; | |||||
| try { | try { | ||||
| char uidBuf[24]; | char uidBuf[24]; | ||||
| @@ -165,58 +195,92 @@ int main(const int argc, const char* argv[]) | |||||
| for (int i=1;; ++i) | for (int i=1;; ++i) | ||||
| { | { | ||||
| std::snprintf(uidBuf, sizeof(uidBuf), "CardinalRemote.%04d", i); | |||||
| std::snprintf(uidBuf, sizeof(uidBuf), "Cardinal.%04d", i); | |||||
| const std::string trypath = rack::system::join(tmp, uidBuf); | const std::string trypath = rack::system::join(tmp, uidBuf); | ||||
| if (! rack::system::exists(trypath)) | if (! rack::system::exists(trypath)) | ||||
| { | { | ||||
| if (rack::system::createDirectories(trypath)) | if (rack::system::createDirectories(trypath)) | ||||
| autosavePath = trypath; | |||||
| fAutosavePath = trypath; | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } DISTRHO_SAFE_EXCEPTION("create unique temporary path"); | } DISTRHO_SAFE_EXCEPTION("create unique temporary path"); | ||||
| CardinalPluginContext context(nullptr); | |||||
| rack::contextSet(&context); | |||||
| CardinalPluginContext* const context = new CardinalPluginContext(nullptr); | |||||
| rack::contextSet(context); | |||||
| const float sampleRate = 48000; | |||||
| rack::settings::sampleRate = sampleRate; | |||||
| context->bufferSize = 512; | |||||
| context->sampleRate = sampleRate; | |||||
| context.bufferSize = 512; | |||||
| rack::settings::sampleRate = context.sampleRate = 48000; | |||||
| context->engine = new rack::engine::Engine; | |||||
| context->engine->setSampleRate(sampleRate); | |||||
| context.engine = new rack::engine::Engine; | |||||
| context.engine->setSampleRate(context.sampleRate); | |||||
| context->history = new rack::history::State; | |||||
| context->patch = new rack::patch::Manager; | |||||
| context->patch->autosavePath = fAutosavePath; | |||||
| context->patch->templatePath = templatePath; | |||||
| context->patch->factoryTemplatePath = factoryTemplatePath; | |||||
| context.history = new rack::history::State; | |||||
| context.patch = new rack::patch::Manager; | |||||
| context.patch->autosavePath = autosavePath; | |||||
| context.patch->templatePath = templatePath; | |||||
| context->event = new rack::widget::EventState; | |||||
| context->scene = new rack::app::Scene; | |||||
| context->event->rootWidget = context->scene; | |||||
| context.event = new rack::widget::EventState; | |||||
| context.scene = new rack::app::Scene; | |||||
| context.event->rootWidget = context.scene; | |||||
| context.window = new rack::window::Window; | |||||
| context->window = new rack::window::Window; | |||||
| context.patch->loadTemplate(); | |||||
| context.scene->rackScroll->reset(); | |||||
| context->patch->loadTemplate(); | |||||
| context->scene->rackScroll->reset(); | |||||
| // swap to factory template after first load | |||||
| context->patch->templatePath = context->patch->factoryTemplatePath; | |||||
| // -------------------------------------------------------------------------- | |||||
| Application app; | Application app; | ||||
| Window win(app); | |||||
| win.setResizable(true); | |||||
| win.setTitle("CardinalRemote"); | |||||
| Window window(app); | |||||
| window.setIgnoringKeyRepeat(true); | |||||
| window.setResizable(true); | |||||
| window.setTitle("CardinalRemote"); | |||||
| // -------------------------------------------------------------------------- | |||||
| const double scaleFactor = window.getScaleFactor(); | |||||
| window.setGeometryConstraints(648 * scaleFactor, 538 * scaleFactor); | |||||
| if (scaleFactor != 1.0) | |||||
| window.setSize(DISTRHO_UI_DEFAULT_WIDTH * scaleFactor, | |||||
| DISTRHO_UI_DEFAULT_HEIGHT * scaleFactor); | |||||
| // -------------------------------------------------------------------------- | |||||
| ScopedPointer<CardinalRemoteUI> remoteUI; | ScopedPointer<CardinalRemoteUI> remoteUI; | ||||
| { | { | ||||
| const Window::ScopedGraphicsContext sgc(win); | |||||
| remoteUI = new CardinalRemoteUI(win, templatePath); | |||||
| const Window::ScopedGraphicsContext sgc(window); | |||||
| remoteUI = new CardinalRemoteUI(window, templatePath); | |||||
| } | } | ||||
| win.show(); | |||||
| window.show(); | |||||
| app.exec(); | app.exec(); | ||||
| context.patch->clear(); | |||||
| // -------------------------------------------------------------------------- | |||||
| { | |||||
| context->patch->clear(); | |||||
| // do a little dance to prevent context scene deletion from saving to temp dir | |||||
| const ScopedValueSetter<bool> svs(rack::settings::headless, true); | |||||
| Engine_setAboutToClose(context->engine); | |||||
| delete context; | |||||
| } | |||||
| if (! fAutosavePath.empty()) | |||||
| rack::system::removeRecursively(fAutosavePath); | |||||
| if (! autosavePath.empty()) | |||||
| rack::system::removeRecursively(autosavePath); | |||||
| // -------------------------------------------------------------------------- | |||||
| INFO("Clearing asset paths"); | INFO("Clearing asset paths"); | ||||
| asset::bundlePath.clear(); | asset::bundlePath.clear(); | ||||
| @@ -226,11 +290,16 @@ int main(const int argc, const char* argv[]) | |||||
| INFO("Destroying plugins"); | INFO("Destroying plugins"); | ||||
| plugin::destroyStaticPlugins(); | plugin::destroyStaticPlugins(); | ||||
| INFO("Destroying colourized assets"); | |||||
| asset::destroy(); | |||||
| INFO("Destroying settings"); | INFO("Destroying settings"); | ||||
| settings::destroy(); | settings::destroy(); | ||||
| INFO("Destroying logger"); | INFO("Destroying logger"); | ||||
| logger::destroy(); | logger::destroy(); | ||||
| // -------------------------------------------------------------------------- | |||||
| return 0; | return 0; | ||||
| } | } | ||||