Signed-off-by: falkTX <falktx@falktx.com>tags/22.02
| @@ -37,17 +37,12 @@ | |||||
| #include <string.hpp> | #include <string.hpp> | ||||
| #include <system.hpp> | #include <system.hpp> | ||||
| #include <app/Scene.hpp> | #include <app/Scene.hpp> | ||||
| #include <engine/Engine.hpp> | |||||
| #include <window/Window.hpp> | #include <window/Window.hpp> | ||||
| #ifdef NDEBUG | #ifdef NDEBUG | ||||
| # undef DEBUG | # undef DEBUG | ||||
| #endif | #endif | ||||
| #ifdef HAVE_LIBLO | |||||
| # include <lo/lo.h> | |||||
| #endif | |||||
| // for finding home dir | // for finding home dir | ||||
| #ifndef ARCH_WIN | #ifndef ARCH_WIN | ||||
| # include <pwd.h> | # include <pwd.h> | ||||
| @@ -215,27 +210,6 @@ void saveAsDialog() | |||||
| #endif | #endif | ||||
| } | } | ||||
| void deployToMOD() | |||||
| { | |||||
| #ifdef HAVE_LIBLO | |||||
| const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); | |||||
| DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | |||||
| APP->engine->prepareSave(); | |||||
| APP->patch->saveAutosave(); | |||||
| APP->patch->cleanAutosave(); | |||||
| std::vector<uint8_t> data(rack::system::archiveDirectory(APP->patch->autosavePath, 1)); | |||||
| if (const lo_blob blob = lo_blob_new(data.size(), data.data())) | |||||
| { | |||||
| lo_send(addr, "/load", "b", blob); | |||||
| lo_blob_free(blob); | |||||
| } | |||||
| lo_address_free(addr); | |||||
| #endif | |||||
| } | |||||
| } | } | ||||
| void async_dialog_filebrowser(const bool saving, | void async_dialog_filebrowser(const bool saving, | ||||
| @@ -25,8 +25,7 @@ | |||||
| # define REMOTE_HOST_PORT "2228" | # define REMOTE_HOST_PORT "2228" | ||||
| #endif | #endif | ||||
| namespace rack | |||||
| { | |||||
| namespace rack { | |||||
| namespace settings { | namespace settings { | ||||
| extern int rateLimit; | extern int rateLimit; | ||||
| @@ -36,10 +35,9 @@ namespace ui { | |||||
| struct Menu; | struct Menu; | ||||
| } | } | ||||
| } | |||||
| } // namespace rack | |||||
| namespace patchUtils | |||||
| { | |||||
| namespace patchUtils { | |||||
| void loadDialog(); | void loadDialog(); | ||||
| void loadPathDialog(const std::string& path); | void loadPathDialog(const std::string& path); | ||||
| @@ -49,6 +47,11 @@ void revertDialog(); | |||||
| void saveDialog(const std::string& path); | void saveDialog(const std::string& path); | ||||
| void saveAsDialog(); | void saveAsDialog(); | ||||
| void appendSelectionContextMenu(rack::ui::Menu* menu); | void appendSelectionContextMenu(rack::ui::Menu* menu); | ||||
| void deployToMOD(); | |||||
| } | |||||
| bool connectToRemote(); | |||||
| bool isRemoteConnected(); | |||||
| bool isRemoteAutoDeployed(); | |||||
| void setRemoteAutoDeploy(bool autoDeploy); | |||||
| void deployToRemote(); | |||||
| } // namespace patchUtils | |||||
| @@ -1,6 +1,6 @@ | |||||
| #!/bin/bash | #!/bin/bash | ||||
| set -e | |||||
| cd $(dirname ${0}) | |||||
| diff -U3 ../Rack/dep/oui-blendish/blendish.c blendish.c > diffs/blendish.c.diff | 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/common.cpp common.cpp > diffs/common.cpp.diff | ||||
| @@ -86,27 +86,6 @@ struct MenuButton : ui::Button { | |||||
| struct FileButton : MenuButton { | struct FileButton : MenuButton { | ||||
| const bool isStandalone; | 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) | FileButton(const bool standalone) | ||||
| : MenuButton(), isStandalone(standalone) {} | : MenuButton(), isStandalone(standalone) {} | ||||
| @@ -133,21 +112,19 @@ struct FileButton : MenuButton { | |||||
| })); | })); | ||||
| #ifdef HAVE_LIBLO | #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); | |||||
| if (patchUtils::isRemoteConnected()) { | |||||
| menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||||
| patchUtils::deployToRemote(); | |||||
| })); | })); | ||||
| const bool autoDeploy = patchUtils::isRemoteAutoDeployed(); | |||||
| menu->addChild(createCheckMenuItem("Auto deploy to MOD", "", | |||||
| [=]() {return autoDeploy;}, | |||||
| [=]() {patchUtils::setRemoteAutoDeploy(!autoDeploy);} | |||||
| )); | |||||
| } else { | } else { | ||||
| menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||||
| patchUtils::deployToMOD(); | |||||
| menu->addChild(createMenuItem("Connect to MOD", "", [this]() { | |||||
| patchUtils::connectToRemote(); | |||||
| })); | })); | ||||
| } | } | ||||
| #endif | #endif | ||||
| @@ -171,15 +148,6 @@ struct FileButton : MenuButton { | |||||
| })); | })); | ||||
| }; | }; | ||||
| } | } | ||||
| #ifdef HAVE_LIBLO | |||||
| void step() override { | |||||
| MenuButton::step(); | |||||
| if (oscServer != nullptr) { | |||||
| while (lo_server_recv_noblock(oscServer, 0) != 0) {} | |||||
| } | |||||
| } | |||||
| #endif | |||||
| }; | }; | ||||
| @@ -34,6 +34,7 @@ | |||||
| #include <app/TipWindow.hpp> | #include <app/TipWindow.hpp> | ||||
| #include <app/MenuBar.hpp> | #include <app/MenuBar.hpp> | ||||
| #include <context.hpp> | #include <context.hpp> | ||||
| #include <engine/Engine.hpp> | |||||
| #include <system.hpp> | #include <system.hpp> | ||||
| #include <network.hpp> | #include <network.hpp> | ||||
| #include <history.hpp> | #include <history.hpp> | ||||
| @@ -41,7 +42,16 @@ | |||||
| #include <patch.hpp> | #include <patch.hpp> | ||||
| #include <asset.hpp> | #include <asset.hpp> | ||||
| #ifdef NDEBUG | |||||
| # undef DEBUG | |||||
| #endif | |||||
| #ifdef HAVE_LIBLO | |||||
| # include <lo/lo.h> | |||||
| #endif | |||||
| #include "../CardinalCommon.hpp" | #include "../CardinalCommon.hpp" | ||||
| #include "DistrhoUtils.hpp" | |||||
| namespace rack { | namespace rack { | ||||
| @@ -92,12 +102,32 @@ struct Scene::Internal { | |||||
| ResizeHandle* resizeHandle; | ResizeHandle* resizeHandle; | ||||
| bool heldArrowKeys[4] = {}; | bool heldArrowKeys[4] = {}; | ||||
| }; | |||||
| #ifdef HAVE_LIBLO | |||||
| double lastSceneChangeTime = 0.0; | |||||
| int historyActionIndex = -1; | |||||
| void hideResizeHandle(Scene* scene) { | |||||
| scene->internal->resizeHandle->hide(); | |||||
| } | |||||
| bool oscAutoDeploy = false; | |||||
| 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<Internal*>(self)->oscConnected = true; | |||||
| } | |||||
| return 0; | |||||
| } | |||||
| ~Internal() { | |||||
| lo_server_free(oscServer); | |||||
| } | |||||
| #endif | |||||
| }; | |||||
| Scene::Scene() { | Scene::Scene() { | ||||
| @@ -121,6 +151,11 @@ Scene::Scene() { | |||||
| } | } | ||||
| void hideResizeHandle(Scene* scene) { | |||||
| scene->internal->resizeHandle->hide(); | |||||
| } | |||||
| Scene::~Scene() { | Scene::~Scene() { | ||||
| delete internal; | delete internal; | ||||
| } | } | ||||
| @@ -167,6 +202,22 @@ void Scene::step() { | |||||
| rackScroll->offset += arrowDelta * arrowSpeed; | rackScroll->offset += arrowDelta * arrowSpeed; | ||||
| } | } | ||||
| #ifdef HAVE_LIBLO | |||||
| if (internal->oscServer != nullptr) { | |||||
| while (lo_server_recv_noblock(internal->oscServer, 0) != 0) {} | |||||
| if (internal->oscAutoDeploy) { | |||||
| const int actionIndex = APP->history->actionIndex; | |||||
| const double time = system::getTime(); | |||||
| if (internal->historyActionIndex != actionIndex && time - internal->lastSceneChangeTime >= 5.0) { | |||||
| internal->historyActionIndex = actionIndex; | |||||
| internal->lastSceneChangeTime = time; | |||||
| patchUtils::deployToRemote(); | |||||
| } | |||||
| } | |||||
| } | |||||
| #endif | |||||
| Widget::step(); | Widget::step(); | ||||
| } | } | ||||
| @@ -258,7 +309,7 @@ void Scene::onHoverKey(const HoverKeyEvent& e) { | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | ||||
| patchUtils::deployToMOD(); | |||||
| patchUtils::deployToRemote(); | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| @@ -384,3 +435,73 @@ void Scene::onPathDrop(const PathDropEvent& e) { | |||||
| } // namespace app | } // namespace app | ||||
| } // namespace rack | } // namespace rack | ||||
| namespace patchUtils { | |||||
| bool connectToRemote() { | |||||
| rack::app::Scene::Internal* const internal = APP->scene->internal; | |||||
| if (internal->oscServer == nullptr) { | |||||
| const lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, nullptr); | |||||
| DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr, false); | |||||
| lo_server_add_method(oscServer, "/resp", nullptr, rack::app::Scene::Internal::osc_handler, internal); | |||||
| internal->oscServer = oscServer; | |||||
| } | |||||
| const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); | |||||
| DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr, false); | |||||
| lo_send(addr, "/hello", ""); | |||||
| lo_address_free(addr); | |||||
| return true; | |||||
| } | |||||
| bool isRemoteConnected() { | |||||
| #ifdef HAVE_LIBLO | |||||
| return APP->scene->internal->oscConnected; | |||||
| #else | |||||
| return false; | |||||
| #endif | |||||
| } | |||||
| bool isRemoteAutoDeployed() { | |||||
| #ifdef HAVE_LIBLO | |||||
| return APP->scene->internal->oscAutoDeploy; | |||||
| #else | |||||
| return false; | |||||
| #endif | |||||
| } | |||||
| void setRemoteAutoDeploy(bool autoDeploy) { | |||||
| #ifdef HAVE_LIBLO | |||||
| APP->scene->internal->oscAutoDeploy = autoDeploy; | |||||
| #endif | |||||
| } | |||||
| void deployToRemote() { | |||||
| #ifdef HAVE_LIBLO | |||||
| const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); | |||||
| DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | |||||
| APP->engine->prepareSave(); | |||||
| APP->patch->saveAutosave(); | |||||
| APP->patch->cleanAutosave(); | |||||
| std::vector<uint8_t> data(rack::system::archiveDirectory(APP->patch->autosavePath, 1)); | |||||
| if (const lo_blob blob = lo_blob_new(data.size(), data.data())) { | |||||
| lo_send(addr, "/load", "b", blob); | |||||
| lo_blob_free(blob); | |||||
| } | |||||
| lo_address_free(addr); | |||||
| #endif | |||||
| } | |||||
| } // namespace patchUtils | |||||
| @@ -1,5 +1,5 @@ | |||||
| --- ../Rack/src/app/MenuBar.cpp 2022-01-15 14:44:46.391280963 +0000 | --- ../Rack/src/app/MenuBar.cpp 2022-01-15 14:44:46.391280963 +0000 | ||||
| +++ MenuBar.cpp 2022-01-23 17:13:16.500279828 +0000 | |||||
| +++ MenuBar.cpp 2022-01-24 11:25:15.507061204 +0000 | |||||
| @@ -1,8 +1,33 @@ | @@ -1,8 +1,33 @@ | ||||
| +/* | +/* | ||||
| + * DISTRHO Cardinal Plugin | + * DISTRHO Cardinal Plugin | ||||
| @@ -48,7 +48,7 @@ | |||||
| namespace rack { | namespace rack { | ||||
| namespace app { | namespace app { | ||||
| @@ -48,80 +78,108 @@ | |||||
| @@ -48,79 +78,75 @@ | |||||
| }; | }; | ||||
| @@ -73,27 +73,6 @@ | |||||
| struct FileButton : MenuButton { | struct FileButton : MenuButton { | ||||
| + const bool isStandalone; | + 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) | + FileButton(const bool standalone) | ||||
| + : MenuButton(), isStandalone(standalone) {} | + : MenuButton(), isStandalone(standalone) {} | ||||
| + | + | ||||
| @@ -124,10 +103,6 @@ | |||||
| - | - | ||||
| menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { | menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { | ||||
| - APP->patch->saveDialog(); | - 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 | + // NOTE: will do nothing if path is empty, intentionally | ||||
| + patchUtils::saveDialog(APP->patch->path); | + patchUtils::saveDialog(APP->patch->path); | ||||
| + }, APP->patch->path.empty())); | + }, APP->patch->path.empty())); | ||||
| @@ -136,25 +111,26 @@ | |||||
| + patchUtils::saveAsDialog(); | + patchUtils::saveAsDialog(); | ||||
| })); | })); | ||||
| - menu->addChild(createMenuItem("Save a copy", "", []() { | |||||
| - APP->patch->saveAsDialog(false); | |||||
| - menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() { | |||||
| - APP->patch->saveAsDialog(); | |||||
| - })); | - })); | ||||
| +#ifdef HAVE_LIBLO | +#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); | |||||
| + 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 { | + } else { | ||||
| + menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||||
| + patchUtils::deployToMOD(); | |||||
| + menu->addChild(createMenuItem("Connect to MOD", "", [this]() { | |||||
| + patchUtils::connectToRemote(); | |||||
| + })); | + })); | ||||
| + } | + } | ||||
| +#endif | +#endif | ||||
| @@ -189,19 +165,9 @@ | |||||
| + })); | + })); | ||||
| + }; | + }; | ||||
| } | } | ||||
| + | |||||
| +#ifdef HAVE_LIBLO | |||||
| + void step() override { | |||||
| + MenuButton::step(); | |||||
| + if (oscServer != nullptr) { | |||||
| + while (lo_server_recv_noblock(oscServer, 0) != 0) {} | |||||
| + } | |||||
| + } | |||||
| +#endif | |||||
| }; | }; | ||||
| @@ -166,7 +224,7 @@ | |||||
| @@ -166,7 +192,7 @@ | |||||
| menu->addChild(new ui::MenuSeparator); | menu->addChild(new ui::MenuSeparator); | ||||
| @@ -210,7 +176,7 @@ | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -256,7 +314,7 @@ | |||||
| @@ -256,7 +282,7 @@ | |||||
| return settings::cableTension; | return settings::cableTension; | ||||
| } | } | ||||
| float getDefaultValue() override { | float getDefaultValue() override { | ||||
| @@ -219,7 +185,7 @@ | |||||
| } | } | ||||
| float getDisplayValue() override { | float getDisplayValue() override { | ||||
| return getValue() * 100; | return getValue() * 100; | ||||
| @@ -421,28 +479,9 @@ | |||||
| @@ -421,28 +447,9 @@ | |||||
| haloBrightnessSlider->box.size.x = 250.0; | haloBrightnessSlider->box.size.x = 250.0; | ||||
| menu->addChild(haloBrightnessSlider); | menu->addChild(haloBrightnessSlider); | ||||
| @@ -249,7 +215,7 @@ | |||||
| static const std::vector<std::string> knobModeLabels = { | static const std::vector<std::string> knobModeLabels = { | ||||
| "Linear", | "Linear", | ||||
| @@ -467,6 +506,21 @@ | |||||
| @@ -467,6 +474,21 @@ | |||||
| menu->addChild(knobScrollSensitivitySlider); | menu->addChild(knobScrollSensitivitySlider); | ||||
| menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); | menu->addChild(createBoolPtrMenuItem("Lock module positions", "", &settings::lockModules)); | ||||
| @@ -271,7 +237,7 @@ | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -476,47 +530,6 @@ | |||||
| @@ -476,47 +498,6 @@ | |||||
| //////////////////// | //////////////////// | ||||
| @@ -319,7 +285,7 @@ | |||||
| struct EngineButton : MenuButton { | struct EngineButton : MenuButton { | ||||
| void onAction(const ActionEvent& e) override { | void onAction(const ActionEvent& e) override { | ||||
| ui::Menu* menu = createMenu(); | ui::Menu* menu = createMenu(); | ||||
| @@ -529,269 +542,6 @@ | |||||
| @@ -529,269 +510,6 @@ | |||||
| menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() { | menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() { | ||||
| settings::cpuMeter ^= true; | settings::cpuMeter ^= true; | ||||
| })); | })); | ||||
| @@ -589,7 +555,7 @@ | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -802,63 +552,24 @@ | |||||
| @@ -802,63 +520,24 @@ | |||||
| struct HelpButton : MenuButton { | struct HelpButton : MenuButton { | ||||
| @@ -616,14 +582,14 @@ | |||||
| - menu->addChild(createMenuItem("VCVRack.com", "", [=]() { | - menu->addChild(createMenuItem("VCVRack.com", "", [=]() { | ||||
| - system::openBrowser("https://vcvrack.com/"); | - system::openBrowser("https://vcvrack.com/"); | ||||
| - })); | |||||
| - | |||||
| - menu->addChild(createMenuItem("Open user folder", "", [=]() { | |||||
| - system::openDirectory(asset::user("")); | |||||
| + menu->addChild(createMenuItem("Cardinal Project page", "", [=]() { | + menu->addChild(createMenuItem("Cardinal Project page", "", [=]() { | ||||
| + system::openBrowser("https://github.com/DISTRHO/Cardinal/"); | + system::openBrowser("https://github.com/DISTRHO/Cardinal/"); | ||||
| })); | })); | ||||
| - menu->addChild(createMenuItem("Open user folder", "", [=]() { | |||||
| - system::openDirectory(asset::user("")); | |||||
| - })); | |||||
| - | |||||
| - if (library::isAppUpdateAvailable()) { | - if (library::isAppUpdateAvailable()) { | ||||
| - menu->addChild(new ui::MenuSeparator); | - menu->addChild(new ui::MenuSeparator); | ||||
| - | - | ||||
| @@ -658,7 +624,7 @@ | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -908,7 +619,9 @@ | |||||
| @@ -908,7 +587,9 @@ | |||||
| struct MenuBar : widget::OpaqueWidget { | struct MenuBar : widget::OpaqueWidget { | ||||
| MeterLabel* meterLabel; | MeterLabel* meterLabel; | ||||
| @@ -669,7 +635,7 @@ | |||||
| const float margin = 5; | const float margin = 5; | ||||
| box.size.y = BND_WIDGET_HEIGHT + 2 * margin; | box.size.y = BND_WIDGET_HEIGHT + 2 * margin; | ||||
| @@ -917,7 +630,7 @@ | |||||
| @@ -917,7 +598,7 @@ | |||||
| layout->spacing = math::Vec(0, 0); | layout->spacing = math::Vec(0, 0); | ||||
| addChild(layout); | addChild(layout); | ||||
| @@ -678,7 +644,7 @@ | |||||
| fileButton->text = "File"; | fileButton->text = "File"; | ||||
| layout->addChild(fileButton); | layout->addChild(fileButton); | ||||
| @@ -933,10 +646,6 @@ | |||||
| @@ -933,10 +614,6 @@ | |||||
| engineButton->text = "Engine"; | engineButton->text = "Engine"; | ||||
| layout->addChild(engineButton); | layout->addChild(engineButton); | ||||
| @@ -689,7 +655,7 @@ | |||||
| HelpButton* helpButton = new HelpButton; | HelpButton* helpButton = new HelpButton; | ||||
| helpButton->text = "Help"; | helpButton->text = "Help"; | ||||
| layout->addChild(helpButton); | layout->addChild(helpButton); | ||||
| @@ -971,7 +680,11 @@ | |||||
| @@ -971,7 +648,11 @@ | |||||
| widget::Widget* createMenuBar() { | widget::Widget* createMenuBar() { | ||||
| @@ -1,5 +1,5 @@ | |||||
| --- ../Rack/src/app/Scene.cpp 2021-12-14 21:35:44.414568198 +0000 | --- ../Rack/src/app/Scene.cpp 2021-12-14 21:35:44.414568198 +0000 | ||||
| +++ Scene.cpp 2022-01-23 17:13:24.715889665 +0000 | |||||
| +++ Scene.cpp 2022-01-24 11:12:33.268767988 +0000 | |||||
| @@ -1,3 +1,30 @@ | @@ -1,3 +1,30 @@ | ||||
| +/* | +/* | ||||
| + * DISTRHO Cardinal Plugin | + * DISTRHO Cardinal Plugin | ||||
| @@ -31,11 +31,28 @@ | |||||
| #include <thread> | #include <thread> | ||||
| #include <osdialog.h> | #include <osdialog.h> | ||||
| @@ -14,31 +41,49 @@ | |||||
| @@ -7,6 +34,7 @@ | |||||
| #include <app/TipWindow.hpp> | |||||
| #include <app/MenuBar.hpp> | |||||
| #include <context.hpp> | |||||
| +#include <engine/Engine.hpp> | |||||
| #include <system.hpp> | |||||
| #include <network.hpp> | |||||
| #include <history.hpp> | |||||
| @@ -14,31 +42,58 @@ | |||||
| #include <patch.hpp> | #include <patch.hpp> | ||||
| #include <asset.hpp> | #include <asset.hpp> | ||||
| +#ifdef NDEBUG | |||||
| +# undef DEBUG | |||||
| +#endif | |||||
| + | |||||
| +#ifdef HAVE_LIBLO | |||||
| +# include <lo/lo.h> | |||||
| +#endif | |||||
| + | |||||
| +#include "../CardinalCommon.hpp" | +#include "../CardinalCommon.hpp" | ||||
| +#include "DistrhoUtils.hpp" | |||||
| + | + | ||||
| namespace rack { | namespace rack { | ||||
| @@ -74,16 +91,16 @@ | |||||
| + nvgStroke(args.vg); | + nvgStroke(args.vg); | ||||
| + | + | ||||
| + nvgStrokeColor(args.vg, nvgRGBf(0, 0, 0)); | + 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 { | - void onDragMove(const DragMoveEvent& e) override { | ||||
| - size = size.plus(e.mouseDelta); | - size = size.plus(e.mouseDelta); | ||||
| - APP->window->setSize(size.round()); | - APP->window->setSize(size.round()); | ||||
| + nvgBeginPath(args.vg); | + nvgBeginPath(args.vg); | ||||
| + nvgMoveTo(args.vg, box.size.x+1, 0); | |||||
| + nvgLineTo(args.vg, 0, box.size.y+1); | |||||
| + nvgStroke(args.vg); | |||||
| + | |||||
| + nvgBeginPath(args.vg); | |||||
| + nvgMoveTo(args.vg, box.size.x + 6, 0); | + nvgMoveTo(args.vg, box.size.x + 6, 0); | ||||
| + nvgLineTo(args.vg, 0, box.size.y + 6); | + nvgLineTo(args.vg, 0, box.size.y + 6); | ||||
| + nvgStroke(args.vg); | + nvgStroke(args.vg); | ||||
| @@ -95,25 +112,42 @@ | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -46,12 +91,15 @@ | |||||
| @@ -46,9 +101,32 @@ | |||||
| struct Scene::Internal { | struct Scene::Internal { | ||||
| ResizeHandle* resizeHandle; | ResizeHandle* resizeHandle; | ||||
| - double lastAutosaveTime = 0.0; | - double lastAutosaveTime = 0.0; | ||||
| - | - | ||||
| bool heldArrowKeys[4] = {}; | bool heldArrowKeys[4] = {}; | ||||
| }; | |||||
| +void hideResizeHandle(Scene* scene) { | |||||
| + scene->internal->resizeHandle->hide(); | |||||
| +} | |||||
| + | + | ||||
| +#ifdef HAVE_LIBLO | |||||
| + double lastSceneChangeTime = 0.0; | |||||
| + int historyActionIndex = -1; | |||||
| + | |||||
| + bool oscAutoDeploy = false; | |||||
| + 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); | |||||
| + | + | ||||
| Scene::Scene() { | |||||
| internal = new Internal; | |||||
| + 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<Internal*>(self)->oscConnected = true; | |||||
| + } | |||||
| + return 0; | |||||
| + } | |||||
| + | |||||
| + ~Internal() { | |||||
| + lo_server_free(oscServer); | |||||
| + } | |||||
| +#endif | |||||
| }; | |||||
| @@ -67,13 +115,8 @@ | |||||
| @@ -67,17 +145,17 @@ | |||||
| browser->hide(); | browser->hide(); | ||||
| addChild(browser); | addChild(browser); | ||||
| @@ -128,7 +162,16 @@ | |||||
| addChild(internal->resizeHandle); | addChild(internal->resizeHandle); | ||||
| } | } | ||||
| @@ -89,32 +132,13 @@ | |||||
| +void hideResizeHandle(Scene* scene) { | |||||
| + scene->internal->resizeHandle->hide(); | |||||
| +} | |||||
| + | |||||
| + | |||||
| Scene::~Scene() { | |||||
| delete internal; | |||||
| } | |||||
| @@ -89,32 +167,13 @@ | |||||
| void Scene::step() { | void Scene::step() { | ||||
| @@ -162,7 +205,30 @@ | |||||
| // Scroll RackScrollWidget with arrow keys | // Scroll RackScrollWidget with arrow keys | ||||
| math::Vec arrowDelta; | math::Vec arrowDelta; | ||||
| if (internal->heldArrowKeys[0]) { | if (internal->heldArrowKeys[0]) { | ||||
| @@ -172,7 +196,7 @@ | |||||
| @@ -143,6 +202,22 @@ | |||||
| rackScroll->offset += arrowDelta * arrowSpeed; | |||||
| } | |||||
| +#ifdef HAVE_LIBLO | |||||
| + if (internal->oscServer != nullptr) { | |||||
| + while (lo_server_recv_noblock(internal->oscServer, 0) != 0) {} | |||||
| + | |||||
| + if (internal->oscAutoDeploy) { | |||||
| + const int actionIndex = APP->history->actionIndex; | |||||
| + const double time = system::getTime(); | |||||
| + if (internal->historyActionIndex != actionIndex && time - internal->lastSceneChangeTime >= 5.0) { | |||||
| + internal->historyActionIndex = actionIndex; | |||||
| + internal->lastSceneChangeTime = time; | |||||
| + patchUtils::deployToRemote(); | |||||
| + } | |||||
| + } | |||||
| + } | |||||
| +#endif | |||||
| + | |||||
| Widget::step(); | |||||
| } | |||||
| @@ -172,7 +247,7 @@ | |||||
| if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | 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()); | // 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) { | if (e.keyName == "n" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
| @@ -171,7 +237,7 @@ | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
| @@ -180,19 +204,20 @@ | |||||
| @@ -180,19 +255,20 @@ | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
| @@ -196,7 +262,7 @@ | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
| @@ -232,10 +257,8 @@ | |||||
| @@ -232,10 +308,8 @@ | |||||
| settings::cpuMeter ^= true; | settings::cpuMeter ^= true; | ||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| @@ -205,11 +271,11 @@ | |||||
| - // The MenuBar will be hidden when the mouse moves over the RackScrollWidget. | - // The MenuBar will be hidden when the mouse moves over the RackScrollWidget. | ||||
| - // menuBar->hide(); | - // menuBar->hide(); | ||||
| + if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | + if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | ||||
| + patchUtils::deployToMOD(); | |||||
| + patchUtils::deployToRemote(); | |||||
| e.consume(this); | e.consume(this); | ||||
| } | } | ||||
| @@ -326,13 +349,6 @@ | |||||
| @@ -326,13 +400,6 @@ | |||||
| // Key commands that can be overridden by children | // Key commands that can be overridden by children | ||||
| if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | if (e.action == GLFW_PRESS || e.action == GLFW_REPEAT) { | ||||
| @@ -223,7 +289,7 @@ | |||||
| if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | if (e.keyName == "v" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | ||||
| rack->pasteClipboardAction(); | rack->pasteClipboardAction(); | ||||
| e.consume(this); | e.consume(this); | ||||
| @@ -351,7 +367,7 @@ | |||||
| @@ -351,7 +418,7 @@ | |||||
| std::string extension = system::getExtension(path); | std::string extension = system::getExtension(path); | ||||
| if (extension == ".vcv") { | if (extension == ".vcv") { | ||||
| @@ -232,3 +298,77 @@ | |||||
| e.consume(this); | e.consume(this); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -368,3 +435,73 @@ | |||||
| } // namespace app | |||||
| } // namespace rack | |||||
| + | |||||
| + | |||||
| +namespace patchUtils { | |||||
| + | |||||
| + | |||||
| +bool connectToRemote() { | |||||
| + rack::app::Scene::Internal* const internal = APP->scene->internal; | |||||
| + | |||||
| + if (internal->oscServer == nullptr) { | |||||
| + const lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, nullptr); | |||||
| + DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr, false); | |||||
| + lo_server_add_method(oscServer, "/resp", nullptr, rack::app::Scene::Internal::osc_handler, internal); | |||||
| + internal->oscServer = oscServer; | |||||
| + } | |||||
| + | |||||
| + const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); | |||||
| + DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr, false); | |||||
| + lo_send(addr, "/hello", ""); | |||||
| + lo_address_free(addr); | |||||
| + | |||||
| + return true; | |||||
| +} | |||||
| + | |||||
| + | |||||
| +bool isRemoteConnected() { | |||||
| +#ifdef HAVE_LIBLO | |||||
| + return APP->scene->internal->oscConnected; | |||||
| +#else | |||||
| + return false; | |||||
| +#endif | |||||
| +} | |||||
| + | |||||
| + | |||||
| +bool isRemoteAutoDeployed() { | |||||
| +#ifdef HAVE_LIBLO | |||||
| + return APP->scene->internal->oscAutoDeploy; | |||||
| +#else | |||||
| + return false; | |||||
| +#endif | |||||
| +} | |||||
| + | |||||
| + | |||||
| +void setRemoteAutoDeploy(bool autoDeploy) { | |||||
| +#ifdef HAVE_LIBLO | |||||
| + APP->scene->internal->oscAutoDeploy = autoDeploy; | |||||
| +#endif | |||||
| +} | |||||
| + | |||||
| + | |||||
| +void deployToRemote() { | |||||
| +#ifdef HAVE_LIBLO | |||||
| + const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT); | |||||
| + DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); | |||||
| + | |||||
| + APP->engine->prepareSave(); | |||||
| + APP->patch->saveAutosave(); | |||||
| + APP->patch->cleanAutosave(); | |||||
| + std::vector<uint8_t> data(rack::system::archiveDirectory(APP->patch->autosavePath, 1)); | |||||
| + | |||||
| + if (const lo_blob blob = lo_blob_new(data.size(), data.data())) { | |||||
| + lo_send(addr, "/load", "b", blob); | |||||
| + lo_blob_free(blob); | |||||
| + } | |||||
| + | |||||
| + lo_address_free(addr); | |||||
| +#endif | |||||
| +} | |||||
| + | |||||
| + | |||||
| +} // namespace patchUtils | |||||