|
- --- ../Rack/src/app/MenuBar.cpp 2022-01-15 14:44:46.391280963 +0000
- +++ MenuBar.cpp 2022-01-24 11:25:15.507061204 +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,79 +78,75 @@
- };
-
-
- -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;
- +
- + 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();
- + // 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 as", RACK_MOD_CTRL_NAME "+Shift+S", []() {
- - APP->patch->saveAsDialog();
- - }));
- +#ifdef HAVE_LIBLO
- + if (patchUtils::isRemoteConnected()) {
- + menu->addChild(createMenuItem("Deploy to MOD", "F7", []() {
- + patchUtils::deployToRemote();
- + }));
-
- - menu->addChild(createMenuItem("Save a copy", "", []() {
- - APP->patch->saveAsDialog(false);
- - }));
- + const bool autoDeploy = patchUtils::isRemoteAutoDeployed();
- + menu->addChild(createCheckMenuItem("Auto deploy to MOD", "",
- + [=]() {return autoDeploy;},
- + [=]() {patchUtils::setRemoteAutoDeploy(!autoDeploy);}
- + ));
- + } else {
- + menu->addChild(createMenuItem("Connect to MOD", "", [this]() {
- + patchUtils::connectToRemote();
- + }));
- + }
- +#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();
- + }));
- + };
- }
- };
-
- @@ -166,7 +192,7 @@
-
- menu->addChild(new ui::MenuSeparator);
-
- - APP->scene->rack->appendSelectionContextMenu(menu);
- + patchUtils::appendSelectionContextMenu(menu);
- }
- };
-
- @@ -256,7 +282,7 @@
- return settings::cableTension;
- }
- float getDefaultValue() override {
- - return 0.5;
- + return 0.75;
- }
- float getDisplayValue() override {
- return getValue() * 100;
- @@ -421,28 +447,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 +474,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 +498,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 +510,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 +520,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("Cardinal Project page", "", [=]() {
- + system::openBrowser("https://github.com/DISTRHO/Cardinal/");
- }));
-
- - menu->addChild(createMenuItem("Open user folder", "", [=]() {
- - system::openDirectory(asset::user(""));
- - }));
- -
- - 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 +587,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 +598,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 +614,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 +648,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;
- }
-
|