Signed-off-by: falkTX <falktx@falktx.com>tags/22.02
@@ -37,17 +37,12 @@ | |||
#include <string.hpp> | |||
#include <system.hpp> | |||
#include <app/Scene.hpp> | |||
#include <engine/Engine.hpp> | |||
#include <window/Window.hpp> | |||
#ifdef NDEBUG | |||
# undef DEBUG | |||
#endif | |||
#ifdef HAVE_LIBLO | |||
# include <lo/lo.h> | |||
#endif | |||
// for finding home dir | |||
#ifndef ARCH_WIN | |||
# include <pwd.h> | |||
@@ -215,27 +210,6 @@ void saveAsDialog() | |||
#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, | |||
@@ -25,8 +25,7 @@ | |||
# define REMOTE_HOST_PORT "2228" | |||
#endif | |||
namespace rack | |||
{ | |||
namespace rack { | |||
namespace settings { | |||
extern int rateLimit; | |||
@@ -36,10 +35,9 @@ namespace ui { | |||
struct Menu; | |||
} | |||
} | |||
} // namespace rack | |||
namespace patchUtils | |||
{ | |||
namespace patchUtils { | |||
void loadDialog(); | |||
void loadPathDialog(const std::string& path); | |||
@@ -49,6 +47,11 @@ void revertDialog(); | |||
void saveDialog(const std::string& path); | |||
void saveAsDialog(); | |||
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 | |||
set -e | |||
cd $(dirname ${0}) | |||
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 | |||
@@ -86,27 +86,6 @@ struct MenuButton : ui::Button { | |||
struct FileButton : MenuButton { | |||
const bool isStandalone; | |||
#ifdef HAVE_LIBLO | |||
bool oscConnected = false; | |||
lo_server oscServer = nullptr; | |||
static int osc_handler(const char* const path, const char* const types, lo_arg** argv, const int argc, lo_message, void* const self) | |||
{ | |||
d_stdout("osc_handler(\"%s\", \"%s\", %p, %i)", path, types, argv, argc); | |||
if (std::strcmp(path, "/resp") == 0 && argc == 2 && types[0] == 's' && types[1] == 's') { | |||
d_stdout("osc_handler(\"%s\", ...) - got resp | '%s' '%s'", path, &argv[0]->s, &argv[1]->s); | |||
if (std::strcmp(&argv[0]->s, "hello") == 0 && std::strcmp(&argv[1]->s, "ok") == 0) | |||
static_cast<FileButton*>(self)->oscConnected = true; | |||
} | |||
return 0; | |||
} | |||
~FileButton() { | |||
lo_server_free(oscServer); | |||
} | |||
#endif | |||
FileButton(const bool standalone) | |||
: MenuButton(), isStandalone(standalone) {} | |||
@@ -133,21 +112,19 @@ struct FileButton : MenuButton { | |||
})); | |||
#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 { | |||
menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||
patchUtils::deployToMOD(); | |||
menu->addChild(createMenuItem("Connect to MOD", "", [this]() { | |||
patchUtils::connectToRemote(); | |||
})); | |||
} | |||
#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/MenuBar.hpp> | |||
#include <context.hpp> | |||
#include <engine/Engine.hpp> | |||
#include <system.hpp> | |||
#include <network.hpp> | |||
#include <history.hpp> | |||
@@ -41,7 +42,16 @@ | |||
#include <patch.hpp> | |||
#include <asset.hpp> | |||
#ifdef NDEBUG | |||
# undef DEBUG | |||
#endif | |||
#ifdef HAVE_LIBLO | |||
# include <lo/lo.h> | |||
#endif | |||
#include "../CardinalCommon.hpp" | |||
#include "DistrhoUtils.hpp" | |||
namespace rack { | |||
@@ -92,12 +102,32 @@ struct Scene::Internal { | |||
ResizeHandle* resizeHandle; | |||
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() { | |||
@@ -121,6 +151,11 @@ Scene::Scene() { | |||
} | |||
void hideResizeHandle(Scene* scene) { | |||
scene->internal->resizeHandle->hide(); | |||
} | |||
Scene::~Scene() { | |||
delete internal; | |||
} | |||
@@ -167,6 +202,22 @@ void Scene::step() { | |||
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(); | |||
} | |||
@@ -258,7 +309,7 @@ void Scene::onHoverKey(const HoverKeyEvent& e) { | |||
e.consume(this); | |||
} | |||
if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | |||
patchUtils::deployToMOD(); | |||
patchUtils::deployToRemote(); | |||
e.consume(this); | |||
} | |||
@@ -384,3 +435,73 @@ void Scene::onPathDrop(const PathDropEvent& e) { | |||
} // 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 |
@@ -1,5 +1,5 @@ | |||
--- ../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 @@ | |||
+/* | |||
+ * DISTRHO Cardinal Plugin | |||
@@ -48,7 +48,7 @@ | |||
namespace rack { | |||
namespace app { | |||
@@ -48,80 +78,108 @@ | |||
@@ -48,79 +78,75 @@ | |||
}; | |||
@@ -73,27 +73,6 @@ | |||
struct FileButton : MenuButton { | |||
+ const bool isStandalone; | |||
+ | |||
+#ifdef HAVE_LIBLO | |||
+ bool oscConnected = false; | |||
+ lo_server oscServer = nullptr; | |||
+ | |||
+ static int osc_handler(const char* const path, const char* const types, lo_arg** argv, const int argc, lo_message, void* const self) | |||
+ { | |||
+ d_stdout("osc_handler(\"%s\", \"%s\", %p, %i)", path, types, argv, argc); | |||
+ | |||
+ if (std::strcmp(path, "/resp") == 0 && argc == 2 && types[0] == 's' && types[1] == 's') { | |||
+ d_stdout("osc_handler(\"%s\", ...) - got resp | '%s' '%s'", path, &argv[0]->s, &argv[1]->s); | |||
+ if (std::strcmp(&argv[0]->s, "hello") == 0 && std::strcmp(&argv[1]->s, "ok") == 0) | |||
+ static_cast<FileButton*>(self)->oscConnected = true; | |||
+ } | |||
+ return 0; | |||
+ } | |||
+ | |||
+ ~FileButton() { | |||
+ lo_server_free(oscServer); | |||
+ } | |||
+#endif | |||
+ | |||
+ FileButton(const bool standalone) | |||
+ : MenuButton(), isStandalone(standalone) {} | |||
+ | |||
@@ -124,10 +103,6 @@ | |||
- | |||
menu->addChild(createMenuItem("Save", RACK_MOD_CTRL_NAME "+S", []() { | |||
- APP->patch->saveDialog(); | |||
- })); | |||
- | |||
- menu->addChild(createMenuItem("Save as", RACK_MOD_CTRL_NAME "+Shift+S", []() { | |||
- APP->patch->saveAsDialog(); | |||
+ // NOTE: will do nothing if path is empty, intentionally | |||
+ patchUtils::saveDialog(APP->patch->path); | |||
+ }, APP->patch->path.empty())); | |||
@@ -136,25 +111,26 @@ | |||
+ 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 | |||
+ 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 { | |||
+ menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||
+ patchUtils::deployToMOD(); | |||
+ menu->addChild(createMenuItem("Connect to MOD", "", [this]() { | |||
+ patchUtils::connectToRemote(); | |||
+ })); | |||
+ } | |||
+#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); | |||
@@ -210,7 +176,7 @@ | |||
} | |||
}; | |||
@@ -256,7 +314,7 @@ | |||
@@ -256,7 +282,7 @@ | |||
return settings::cableTension; | |||
} | |||
float getDefaultValue() override { | |||
@@ -219,7 +185,7 @@ | |||
} | |||
float getDisplayValue() override { | |||
return getValue() * 100; | |||
@@ -421,28 +479,9 @@ | |||
@@ -421,28 +447,9 @@ | |||
haloBrightnessSlider->box.size.x = 250.0; | |||
menu->addChild(haloBrightnessSlider); | |||
@@ -249,7 +215,7 @@ | |||
static const std::vector<std::string> knobModeLabels = { | |||
"Linear", | |||
@@ -467,6 +506,21 @@ | |||
@@ -467,6 +474,21 @@ | |||
menu->addChild(knobScrollSensitivitySlider); | |||
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 { | |||
void onAction(const ActionEvent& e) override { | |||
ui::Menu* menu = createMenu(); | |||
@@ -529,269 +542,6 @@ | |||
@@ -529,269 +510,6 @@ | |||
menu->addChild(createMenuItem("Performance meters", cpuMeterText, [=]() { | |||
settings::cpuMeter ^= true; | |||
})); | |||
@@ -589,7 +555,7 @@ | |||
} | |||
}; | |||
@@ -802,63 +552,24 @@ | |||
@@ -802,63 +520,24 @@ | |||
struct HelpButton : MenuButton { | |||
@@ -616,14 +582,14 @@ | |||
- menu->addChild(createMenuItem("VCVRack.com", "", [=]() { | |||
- system::openBrowser("https://vcvrack.com/"); | |||
- })); | |||
- | |||
- menu->addChild(createMenuItem("Open user folder", "", [=]() { | |||
- system::openDirectory(asset::user("")); | |||
+ menu->addChild(createMenuItem("Cardinal Project page", "", [=]() { | |||
+ system::openBrowser("https://github.com/DISTRHO/Cardinal/"); | |||
})); | |||
- menu->addChild(createMenuItem("Open user folder", "", [=]() { | |||
- system::openDirectory(asset::user("")); | |||
- })); | |||
- | |||
- if (library::isAppUpdateAvailable()) { | |||
- menu->addChild(new ui::MenuSeparator); | |||
- | |||
@@ -658,7 +624,7 @@ | |||
} | |||
}; | |||
@@ -908,7 +619,9 @@ | |||
@@ -908,7 +587,9 @@ | |||
struct MenuBar : widget::OpaqueWidget { | |||
MeterLabel* meterLabel; | |||
@@ -669,7 +635,7 @@ | |||
const float margin = 5; | |||
box.size.y = BND_WIDGET_HEIGHT + 2 * margin; | |||
@@ -917,7 +630,7 @@ | |||
@@ -917,7 +598,7 @@ | |||
layout->spacing = math::Vec(0, 0); | |||
addChild(layout); | |||
@@ -678,7 +644,7 @@ | |||
fileButton->text = "File"; | |||
layout->addChild(fileButton); | |||
@@ -933,10 +646,6 @@ | |||
@@ -933,10 +614,6 @@ | |||
engineButton->text = "Engine"; | |||
layout->addChild(engineButton); | |||
@@ -689,7 +655,7 @@ | |||
HelpButton* helpButton = new HelpButton; | |||
helpButton->text = "Help"; | |||
layout->addChild(helpButton); | |||
@@ -971,7 +680,11 @@ | |||
@@ -971,7 +648,11 @@ | |||
widget::Widget* createMenuBar() { | |||
@@ -1,5 +1,5 @@ | |||
--- ../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 @@ | |||
+/* | |||
+ * DISTRHO Cardinal Plugin | |||
@@ -31,11 +31,28 @@ | |||
#include <thread> | |||
#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 <asset.hpp> | |||
+#ifdef NDEBUG | |||
+# undef DEBUG | |||
+#endif | |||
+ | |||
+#ifdef HAVE_LIBLO | |||
+# include <lo/lo.h> | |||
+#endif | |||
+ | |||
+#include "../CardinalCommon.hpp" | |||
+#include "DistrhoUtils.hpp" | |||
+ | |||
namespace rack { | |||
@@ -74,16 +91,16 @@ | |||
+ nvgStroke(args.vg); | |||
+ | |||
+ nvgStrokeColor(args.vg, nvgRGBf(0, 0, 0)); | |||
+ | |||
+ nvgBeginPath(args.vg); | |||
+ nvgMoveTo(args.vg, box.size.x+1, 0); | |||
+ nvgLineTo(args.vg, 0, box.size.y+1); | |||
+ nvgStroke(args.vg); | |||
- void onDragMove(const DragMoveEvent& e) override { | |||
- size = size.plus(e.mouseDelta); | |||
- APP->window->setSize(size.round()); | |||
+ nvgBeginPath(args.vg); | |||
+ nvgMoveTo(args.vg, box.size.x+1, 0); | |||
+ nvgLineTo(args.vg, 0, box.size.y+1); | |||
+ nvgStroke(args.vg); | |||
+ | |||
+ nvgBeginPath(args.vg); | |||
+ nvgMoveTo(args.vg, box.size.x + 6, 0); | |||
+ nvgLineTo(args.vg, 0, box.size.y + 6); | |||
+ nvgStroke(args.vg); | |||
@@ -95,25 +112,42 @@ | |||
} | |||
}; | |||
@@ -46,12 +91,15 @@ | |||
@@ -46,9 +101,32 @@ | |||
struct Scene::Internal { | |||
ResizeHandle* resizeHandle; | |||
- double lastAutosaveTime = 0.0; | |||
- | |||
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(); | |||
addChild(browser); | |||
@@ -128,7 +162,16 @@ | |||
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() { | |||
@@ -162,7 +205,30 @@ | |||
// Scroll RackScrollWidget with arrow keys | |||
math::Vec arrowDelta; | |||
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) { | |||
// 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) { | |||
@@ -171,7 +237,7 @@ | |||
e.consume(this); | |||
} | |||
if (e.keyName == "q" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||
@@ -180,19 +204,20 @@ | |||
@@ -180,19 +255,20 @@ | |||
e.consume(this); | |||
} | |||
if (e.keyName == "o" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||
@@ -196,7 +262,7 @@ | |||
e.consume(this); | |||
} | |||
if (e.keyName == "z" && (e.mods & RACK_MOD_MASK) == RACK_MOD_CTRL) { | |||
@@ -232,10 +257,8 @@ | |||
@@ -232,10 +308,8 @@ | |||
settings::cpuMeter ^= true; | |||
e.consume(this); | |||
} | |||
@@ -205,11 +271,11 @@ | |||
- // The MenuBar will be hidden when the mouse moves over the RackScrollWidget. | |||
- // menuBar->hide(); | |||
+ if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | |||
+ patchUtils::deployToMOD(); | |||
+ patchUtils::deployToRemote(); | |||
e.consume(this); | |||
} | |||
@@ -326,13 +349,6 @@ | |||
@@ -326,13 +400,6 @@ | |||
// Key commands that can be overridden by children | |||
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) { | |||
rack->pasteClipboardAction(); | |||
e.consume(this); | |||
@@ -351,7 +367,7 @@ | |||
@@ -351,7 +418,7 @@ | |||
std::string extension = system::getExtension(path); | |||
if (extension == ".vcv") { | |||
@@ -232,3 +298,77 @@ | |||
e.consume(this); | |||
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 |