|
- --- ../Rack/src/app/MenuBar.cpp 2022-09-21 19:49:12.198540676 +0100
- +++ MenuBar.cpp 2022-12-30 14:50:06.801891005 +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>
- @@ -15,6 +40,7 @@
- #include <ui/ProgressBar.hpp>
- #include <ui/Label.hpp>
- #include <engine/Engine.hpp>
- +#include <widget/FramebufferWidget.hpp>
- #include <window/Window.hpp>
- #include <asset.hpp>
- #include <context.hpp>
- @@ -25,8 +51,28 @@
- #include <patch.hpp>
- #include <library.hpp>
-
- +#include "../CardinalCommon.hpp"
- +#include "../CardinalRemote.hpp"
- +#include "DistrhoPlugin.hpp"
- +#include "DistrhoStandaloneUtils.hpp"
- +
- +#ifdef HAVE_LIBLO
- +# include <lo/lo.h>
- +#endif
- +
- +void switchDarkMode(bool darkMode);
-
- namespace rack {
- +namespace asset {
- +std::string patchesPath();
- +}
- +namespace engine {
- +void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*);
- +}
- +namespace plugin {
- +void updateStaticPluginsDarkMode();
- +}
- +
- namespace app {
- namespace menuBar {
-
- @@ -48,79 +94,160 @@
- };
-
-
- -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;
- +#if ! CARDINAL_VARIANT_MINI
- + std::vector<std::string> demoPatches;
- +#endif
- +
- + FileButton(const bool standalone)
- + : MenuButton(), isStandalone(standalone)
- + {
- +#if ! CARDINAL_VARIANT_MINI
- + const std::string patchesDir = asset::patchesPath() + DISTRHO_OS_SEP_STR "examples";
- +
- + if (system::isDirectory(patchesDir))
- + {
- + demoPatches = system::getEntries(patchesDir);
- + std::sort(demoPatches.begin(), demoPatches.end(), [](const std::string& a, const std::string& b){
- + return string::lowercase(a) < string::lowercase(b);
- + });
- + }
- +#endif
- + }
- +
- 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();
- +#ifndef DISTRHO_OS_WASM
- + const char* const NewShortcut = RACK_MOD_CTRL_NAME "+N";
- +#else
- + const char* const NewShortcut = "";
- +#endif
- + menu->addChild(createMenuItem("New", NewShortcut, []() {
- + patchUtils::loadTemplateDialog();
- }));
-
- - menu->addChild(createMenuItem("Open", RACK_MOD_CTRL_NAME "+O", []() {
- - APP->patch->loadDialog();
- +#if ! CARDINAL_VARIANT_MINI
- +#ifndef DISTRHO_OS_WASM
- + 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();
- + // 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();
- + }));
- +#else
- + menu->addChild(createMenuItem("Import patch...", RACK_MOD_CTRL_NAME "+O", []() {
- + patchUtils::loadDialog();
- }));
-
- - menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() {
- - APP->patch->saveAsDialog();
- + menu->addChild(createMenuItem("Import selection...", "", [=]() {
- + patchUtils::loadSelectionDialog();
- + }, false, true));
- +
- + menu->addChild(createMenuItem("Save and download compressed", RACK_MOD_CTRL_NAME "+Shift+S", []() {
- + patchUtils::saveAsDialog();
- }));
-
- - menu->addChild(createMenuItem("Save a copy", "", []() {
- - APP->patch->saveAsDialog(false);
- + menu->addChild(createMenuItem("Save and download uncompressed", "", []() {
- + patchUtils::saveAsDialogUncompressed();
- }));
- +#endif
- +#endif
-
- menu->addChild(createMenuItem("Revert", RACK_MOD_CTRL_NAME "+" RACK_MOD_SHIFT_NAME "+O", []() {
- - APP->patch->revertDialog();
- - }, APP->patch->path == ""));
- + patchUtils::revertDialog();
- + }, APP->patch->path.empty()));
-
- - menu->addChild(createMenuItem("Overwrite template", "", []() {
- - APP->patch->saveTemplateDialog();
- - }));
- +#if defined(HAVE_LIBLO) && ! CARDINAL_VARIANT_MINI
- + menu->addChild(new ui::MenuSeparator);
- +
- + remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote();
- +
- + if (remoteDetails != nullptr && remoteDetails->connected) {
- + menu->addChild(createMenuItem("Deploy to MOD", "F7", [remoteDetails]() {
- + remoteUtils::sendFullPatchToRemote(remoteDetails);
- + }));
-
- + menu->addChild(createCheckMenuItem("Auto deploy to MOD", "",
- + [remoteDetails]() {return remoteDetails->autoDeploy;},
- + [remoteDetails]() {
- + remoteDetails->autoDeploy = !remoteDetails->autoDeploy;
- + Engine_setRemoteDetails(APP->engine, remoteDetails->autoDeploy ? remoteDetails : nullptr);
- + }
- + ));
- + } else {
- + menu->addChild(createMenuItem("Connect to MOD", "", []() {
- + DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote());
- + }));
- + }
- +#endif
- +
- +#if ! CARDINAL_VARIANT_MINI
- +#ifndef DISTRHO_OS_WASM
- menu->addChild(new ui::MenuSeparator);
-
- // Load selection
- - menu->addChild(createMenuItem("Import selection", "", [=]() {
- - APP->scene->rack->loadSelectionDialog();
- + menu->addChild(createMenuItem("Import selection...", "", [=]() {
- + patchUtils::loadSelectionDialog();
- }, false, true));
-
- - menu->addChild(new ui::MenuSeparator);
- -
- - menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() {
- - APP->window->close();
- + menu->addChild(createMenuItem("Export uncompressed json...", "", []() {
- + patchUtils::saveAsDialogUncompressed();
- }));
- +#endif
- +#endif
- +
- +#if ! CARDINAL_VARIANT_MINI
- + if (!demoPatches.empty())
- + {
- + menu->addChild(new ui::MenuSeparator);
- +
- + menu->addChild(createSubmenuItem("Open Demo / Example project", "", [=](ui::Menu* const menu) {
- + for (std::string path : demoPatches) {
- + std::string label = system::getStem(path);
- +
- + for (size_t i=0, len=label.size(); i<len; ++i) {
- + if (label[i] == '_')
- + label[i] = ' ';
- + }
- +
- + menu->addChild(createMenuItem(label, "", [path]() {
- + patchUtils::loadPathDialog(path, true);
- + }));
- + }
- +
- + menu->addChild(new ui::MenuSeparator);
- +
- + menu->addChild(createMenuItem("Open PatchStorage.com for more patches", "", []() {
- + patchUtils::openBrowser("https://patchstorage.com/platform/cardinal/");
- + }));
- + }));
- + }
- +#endif
- +
- +#ifndef DISTRHO_OS_WASM
- + if (isStandalone) {
- + menu->addChild(new ui::MenuSeparator);
- +
- + menu->addChild(createMenuItem("Quit", RACK_MOD_CTRL_NAME "+Q", []() {
- + APP->window->close();
- + }));
- + }
- +#endif
- }
- };
-
- @@ -166,7 +293,7 @@
-
- menu->addChild(new ui::MenuSeparator);
-
- - APP->scene->rack->appendSelectionContextMenu(menu);
- + patchUtils::appendSelectionContextMenu(menu);
- }
- };
-
- @@ -256,7 +383,7 @@
- return settings::cableTension;
- }
- float getDefaultValue() override {
- - return 0.5;
- + return 0.75;
- }
- float getDisplayValue() override {
- return getValue() * 100;
- @@ -393,36 +520,37 @@
- };
-
-
- +static void setAllFramebufferWidgetsDirty(widget::Widget* const widget)
- +{
- + for (widget::Widget* child : widget->children)
- + {
- + if (widget::FramebufferWidget* const fbw = dynamic_cast<widget::FramebufferWidget*>(child))
- + {
- + fbw->setDirty();
- + break;
- + }
- + setAllFramebufferWidgetsDirty(child);
- + }
- +}
- +
- +
- struct ViewButton : MenuButton {
- 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(createMenuLabel("Window"));
- -
- - 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(createMenuLabel("Appearance"));
-
- - 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;}
- - ));
- - }
- + std::string darkModeText;
- + if (settings::darkMode)
- + darkModeText = CHECKMARK_STRING;
- + menu->addChild(createMenuItem("Dark Mode", darkModeText, []() {
- + switchDarkMode(!settings::darkMode);
- + plugin::updateStaticPluginsDarkMode();
- + setAllFramebufferWidgetsDirty(APP->scene);
- }));
-
- - menu->addChild(new ui::MenuSeparator);
- - menu->addChild(createMenuLabel("Appearance"));
- -
- menu->addChild(createBoolPtrMenuItem("Show tooltips", "", &settings::tooltips));
-
- ZoomSlider* zoomSlider = new ZoomSlider;
- @@ -446,9 +574,18 @@
- menu->addChild(haloBrightnessSlider);
-
- menu->addChild(new ui::MenuSeparator);
- + menu->addChild(createMenuLabel("Module dragging"));
- +
- + menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules));
- +
- + menu->addChild(createBoolPtrMenuItem("Auto-squeeze modules when dragging", "", &settings::squeezeModules));
- +
- + menu->addChild(new ui::MenuSeparator);
- menu->addChild(createMenuLabel("Parameters"));
-
- +#ifdef DISTRHO_OS_WASM
- menu->addChild(createBoolPtrMenuItem("Lock cursor while dragging", "", &settings::allowCursorLock));
- +#endif
-
- static const std::vector<std::string> knobModeLabels = {
- "Linear",
- @@ -473,11 +610,34 @@
- menu->addChild(knobScrollSensitivitySlider);
-
- menu->addChild(new ui::MenuSeparator);
- - menu->addChild(createMenuLabel("Module dragging"));
- + menu->addChild(createMenuLabel("Window"));
- +
- +#ifdef DISTRHO_OS_WASM
- + const bool fullscreen = APP->window->isFullScreen();
- + std::string rightText = "F11";
- + if (fullscreen)
- + rightText += " " CHECKMARK_STRING;
- + menu->addChild(createMenuItem("Fullscreen", rightText, [=]() {
- + APP->window->setFullScreen(!fullscreen);
- + }));
- +#endif
-
- - menu->addChild(createBoolPtrMenuItem("Lock positions", "", &settings::lockModules));
- + menu->addChild(createBoolPtrMenuItem("Invert zoom", "", &settings::invertZoom));
-
- - menu->addChild(createBoolPtrMenuItem("Auto-squeeze algorithm (experimental)", "", &settings::squeezeModules));
- + 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;}
- + ));
- + }
- + }));
- }
- };
-
- @@ -487,47 +647,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();
- @@ -541,268 +660,46 @@
- 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++) {
- + if (isUsingNativeAudio()) {
- + if (supportsAudioInput()) {
- + const bool enabled = isAudioInputEnabled();
- 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;
- + if (enabled)
- + rightText = CHECKMARK_STRING;
- + menu->addChild(createMenuItem("Enable Audio Input", rightText, [enabled]() {
- + if (!enabled)
- + requestAudioInput();
- + }));
- }
- - }
-
- - 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);
- - }
- + if (supportsMIDI()) {
- + std::string rightText;
- + if (isMIDIEnabled())
- + rightText = CHECKMARK_STRING;
- + menu->addChild(createMenuItem("Enable/Reconnect MIDI", rightText, []() {
- + requestMIDI();
- + }));
- }
- - }
- - }
- -};
- -
- -
- -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();
- + if (supportsBufferSizeChanges()) {
- + static const std::vector<uint32_t> bufferSizes = {
- + #ifdef DISTRHO_OS_WASM
- + 256, 512, 1024, 2048, 4096, 8192, 16384
- + #else
- + 128, 256, 512, 1024, 2048, 4096, 8192
- + #endif
- + };
- + const uint32_t currentBufferSize = getBufferSize();
- + menu->addChild(createSubmenuItem("Buffer Size", std::to_string(currentBufferSize), [=](ui::Menu* menu) {
- + for (uint32_t bufferSize : bufferSizes) {
- + menu->addChild(createCheckMenuItem(std::to_string(bufferSize), "",
- + [=]() {return currentBufferSize == bufferSize;},
- + [=]() {requestBufferSizeChange(bufferSize);}
- + ));
- + }
- + }));
- }
- }
- -
- - MenuButton::step();
- }
- };
-
- @@ -813,65 +710,23 @@
-
-
- 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", [=]() {
- - system::openBrowser("https://vcvrack.com/manual");
- - }));
- -
- - menu->addChild(createMenuItem("Support", "", [=]() {
- - system::openBrowser("https://vcvrack.com/support");
- + menu->addChild(createMenuItem("Rack User manual", "F1", [=]() {
- + patchUtils::openBrowser("https://vcvrack.com/manual");
- }));
-
- - menu->addChild(createMenuItem("VCVRack.com", "", [=]() {
- - system::openBrowser("https://vcvrack.com/");
- + menu->addChild(createMenuItem("Cardinal Project page", "", [=]() {
- + patchUtils::openBrowser("https://github.com/DISTRHO/Cardinal/");
- }));
-
- menu->addChild(new ui::MenuSeparator);
-
- - menu->addChild(createMenuLabel(APP_NAME + " " + APP_EDITION_NAME + " " + APP_VERSION));
- -
- - menu->addChild(createMenuItem("Open user folder", "", [=]() {
- - system::openDirectory(asset::user(""));
- - }));
- -
- - menu->addChild(createMenuItem("Changelog", "", [=]() {
- - system::openBrowser("https://github.com/VCVRack/Rack/blob/v2/CHANGELOG.md");
- - }));
- -
- - if (library::isAppUpdateAvailable()) {
- - menu->addChild(createMenuItem("Update " + APP_NAME, APP_VERSION + " → " + library::appVersion, [=]() {
- - system::openBrowser(library::appDownloadUrl);
- - }));
- - }
- - else if (!settings::autoCheckUpdates && !settings::devMode) {
- - menu->addChild(createMenuItem("Check for " + APP_NAME + " update", "", [=]() {
- - std::thread t([&]() {
- - library::checkAppUpdate();
- - });
- - t.detach();
- - }, false, true));
- - }
- - }
- -
- - void step() override {
- - notification->box.pos = math::Vec(0, 0);
- - notification->visible = library::isAppUpdateAvailable();
- - MenuButton::step();
- + menu->addChild(createMenuLabel("Cardinal " + APP_EDITION + " " + CARDINAL_VERSION));
- + menu->addChild(createMenuLabel("Rack " + APP_VERSION + " Compatible"));
- }
- };
-
- @@ -910,9 +765,14 @@
- // uiLastTime = time;
- // }
-
- +#if CARDINAL_VARIANT_MINI
- + text = string::f("%.1f fps", 1.0 / frameDurationAvg);
- +#else
- double meterAverage = APP->engine->getMeterAverage();
- double meterMax = APP->engine->getMeterMax();
- text = string::f("%.1f fps %.1f%% avg %.1f%% max", 1.0 / frameDurationAvg, meterAverage * 100, meterMax * 100);
- +#endif
- +
- Label::step();
- }
- };
- @@ -921,7 +781,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;
-
- @@ -930,7 +792,7 @@
- layout->spacing = math::Vec(0, 0);
- addChild(layout);
-
- - FileButton* fileButton = new FileButton;
- + FileButton* fileButton = new FileButton(isStandalone);
- fileButton->text = "File";
- layout->addChild(fileButton);
-
- @@ -942,13 +804,11 @@
- viewButton->text = "View";
- layout->addChild(viewButton);
-
- +#if ! CARDINAL_VARIANT_MINI
- EngineButton* engineButton = new EngineButton;
- engineButton->text = "Engine";
- layout->addChild(engineButton);
- -
- - LibraryButton* libraryButton = new LibraryButton;
- - libraryButton->text = "Library";
- - layout->addChild(libraryButton);
- +#endif
-
- HelpButton* helpButton = new HelpButton;
- helpButton->text = "Help";
- @@ -984,7 +844,7 @@
-
-
- widget::Widget* createMenuBar() {
- - menuBar::MenuBar* menuBar = new menuBar::MenuBar;
- + menuBar::MenuBar* menuBar = new menuBar::MenuBar(isStandalone());
- return menuBar;
- }
-
|