Signed-off-by: falkTX <falktx@falktx.com>tags/23.02
@@ -0,0 +1 @@ | |||
../CardinalRemote.cpp |
@@ -42,6 +42,14 @@ | |||
#include <app/Scene.hpp> | |||
#include <window/Window.hpp> | |||
#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
# error wrong build | |||
#endif | |||
#if defined(STATIC_BUILD) || CARDINAL_VARIANT_MINI | |||
# undef CARDINAL_INIT_OSC_THREAD | |||
#endif | |||
#ifdef NDEBUG | |||
# undef DEBUG | |||
#endif | |||
@@ -54,12 +62,12 @@ | |||
# include <unistd.h> | |||
#endif | |||
#ifdef DISTRHO_OS_WASM | |||
# include <emscripten/emscripten.h> | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
# include <lo/lo.h> | |||
#endif | |||
#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
# error wrong build | |||
#ifdef DISTRHO_OS_WASM | |||
# include <emscripten/emscripten.h> | |||
#endif | |||
#if defined(CARDINAL_COMMON_DSP_ONLY) || defined(HEADLESS) | |||
@@ -230,7 +238,8 @@ static int osc_hello_handler(const char*, const char*, lo_arg**, int, const lo_m | |||
{ | |||
d_stdout("osc_hello_handler()"); | |||
const lo_address source = lo_message_get_source(m); | |||
lo_send_from(source, static_cast<Initializer*>(self)->oscServer, LO_TT_IMMEDIATE, "/resp", "ss", "hello", "ok"); | |||
const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread); | |||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "hello", "ok"); | |||
return 0; | |||
} | |||
@@ -248,7 +257,7 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a | |||
bool ok = false; | |||
if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->oscPlugin) | |||
if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->remotePluginInstance) | |||
{ | |||
CardinalPluginContext* const context = plugin->context; | |||
std::vector<uint8_t> data(size); | |||
@@ -269,8 +278,8 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a | |||
} | |||
const lo_address source = lo_message_get_source(m); | |||
lo_send_from(source, static_cast<Initializer*>(self)->oscServer, | |||
LO_TT_IMMEDIATE, "/resp", "ss", "load", ok ? "ok" : "fail"); | |||
const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread); | |||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "load", ok ? "ok" : "fail"); | |||
return 0; | |||
} | |||
@@ -288,12 +297,12 @@ static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv, | |||
bool ok = false; | |||
if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->oscPlugin) | |||
if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->remotePluginInstance) | |||
ok = plugin->updateStateValue("screenshot", String::asBase64(blob, size).buffer()); | |||
const lo_address source = lo_message_get_source(m); | |||
lo_send_from(source, static_cast<Initializer*>(self)->oscServer, | |||
LO_TT_IMMEDIATE, "/resp", "ss", "screenshot", ok ? "ok" : "fail"); | |||
const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread); | |||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "screenshot", ok ? "ok" : "fail"); | |||
return 0; | |||
} | |||
#endif | |||
@@ -432,15 +441,13 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
INFO("Initializing OSC Remote control"); | |||
oscServer = lo_server_new_with_proto(REMOTE_HOST_PORT, LO_UDP, osc_error_handler); | |||
DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr,); | |||
lo_server_add_method(oscServer, "/hello", "", osc_hello_handler, this); | |||
lo_server_add_method(oscServer, "/load", "b", osc_load_handler, this); | |||
lo_server_add_method(oscServer, "/screenshot", "b", osc_screenshot_handler, this); | |||
lo_server_add_method(oscServer, nullptr, nullptr, osc_fallback_handler, nullptr); | |||
oscServerThread = lo_server_thread_new_with_proto(REMOTE_HOST_PORT, LO_UDP, osc_error_handler); | |||
DISTRHO_SAFE_ASSERT_RETURN(oscServerThread != nullptr,); | |||
startThread(); | |||
lo_server_thread_add_method(oscServerThread, "/hello", "", osc_hello_handler, this); | |||
lo_server_thread_add_method(oscServerThread, "/load", "b", osc_load_handler, this); | |||
lo_server_thread_add_method(oscServerThread, "/screenshot", "b", osc_screenshot_handler, this); | |||
lo_server_thread_add_method(oscServerThread, nullptr, nullptr, osc_fallback_handler, nullptr); | |||
#else | |||
INFO("OSC Remote control is not enabled in this build"); | |||
#endif | |||
@@ -451,12 +458,11 @@ Initializer::~Initializer() | |||
using namespace rack; | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
if (oscServer != nullptr) | |||
if (oscServerThread != nullptr) | |||
{ | |||
stopThread(5000); | |||
lo_server_del_method(oscServer, nullptr, nullptr); | |||
lo_server_free(oscServer); | |||
oscServer = nullptr; | |||
lo_server_thread_del_method(oscServerThread, nullptr, nullptr); | |||
lo_server_thread_free(oscServerThread); | |||
oscServerThread = nullptr; | |||
} | |||
#endif | |||
@@ -478,21 +484,6 @@ Initializer::~Initializer() | |||
logger::destroy(); | |||
} | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
void Initializer::run() | |||
{ | |||
INFO("OSC Thread Listening for remote commands"); | |||
while (! shouldThreadExit()) | |||
{ | |||
d_msleep(200); | |||
while (lo_server_recv_noblock(oscServer, 0) != 0) {} | |||
} | |||
INFO("OSC Thread Closed"); | |||
} | |||
#endif | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
END_NAMESPACE_DISTRHO | |||
@@ -21,13 +21,6 @@ | |||
#include <string> | |||
#ifdef HAVE_LIBLO | |||
// # define REMOTE_HOST "localhost" | |||
# define REMOTE_HOST "192.168.51.1" | |||
# define REMOTE_HOST_PORT "2228" | |||
# include "extra/Thread.hpp" | |||
#endif | |||
#ifdef DISTRHO_OS_WASM | |||
# ifdef STATIC_BUILD | |||
# define CARDINAL_WASM_WELCOME_TEMPLATE_FILENAME "welcome-wasm-mini.vcv" | |||
@@ -85,21 +78,17 @@ void saveAsDialogUncompressed(); | |||
void appendSelectionContextMenu(rack::ui::Menu* menu); | |||
void openBrowser(const std::string& url); | |||
bool connectToRemote(); | |||
bool isRemoteConnected(); | |||
bool isRemoteAutoDeployed(); | |||
void setRemoteAutoDeploy(bool autoDeploy); | |||
void deployToRemote(); | |||
void sendScreenshotToRemote(const char* screenshot); | |||
} // namespace patchUtils | |||
// ----------------------------------------------------------------------------------------------------------- | |||
#if defined(HAVE_LIBLO) && defined(HEADLESS) && DISTRHO_PLUGIN_WANT_DIRECT_ACCESS | |||
// && defined(HEADLESS) | |||
#if defined(HAVE_LIBLO) | |||
# define CARDINAL_INIT_OSC_THREAD | |||
#endif | |||
typedef void* lo_server_thread; | |||
START_NAMESPACE_DISTRHO | |||
class CardinalBasePlugin; | |||
@@ -107,22 +96,16 @@ class CardinalBaseUI; | |||
struct CardinalPluginContext; | |||
struct Initializer | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
: public Thread | |||
#endif | |||
{ | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
lo_server oscServer = nullptr; | |||
CardinalBasePlugin* oscPlugin = nullptr; | |||
lo_server_thread oscServerThread = nullptr; | |||
CardinalBasePlugin* remotePluginInstance = nullptr; | |||
#endif | |||
std::string templatePath; | |||
std::string factoryTemplatePath; | |||
Initializer(const CardinalBasePlugin* plugin, const CardinalBaseUI* ui); | |||
~Initializer(); | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
void run() override; | |||
#endif | |||
}; | |||
#ifndef HEADLESS | |||
@@ -0,0 +1 @@ | |||
../CardinalRemote.cpp |
@@ -0,0 +1 @@ | |||
../CardinalRemote.cpp |
@@ -0,0 +1 @@ | |||
../CardinalRemote.cpp |
@@ -274,14 +274,15 @@ public: | |||
} | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
fInitializer->oscPlugin = this; | |||
fInitializer->remotePluginInstance = this; | |||
#endif | |||
} | |||
~CardinalPlugin() override | |||
{ | |||
#ifdef CARDINAL_INIT_OSC_THREAD | |||
fInitializer->oscPlugin = nullptr; | |||
if (fInitializer->remotePluginInstance == this) | |||
fInitializer->remotePluginInstance = nullptr; | |||
#endif | |||
{ | |||
@@ -844,9 +845,6 @@ protected: | |||
if (std::strcmp(key, "screenshot") == 0) | |||
{ | |||
fState.screenshot = value; | |||
#if defined(HAVE_LIBLO) && !defined(HEADLESS) | |||
patchUtils::sendScreenshotToRemote(value); | |||
#endif | |||
return; | |||
} | |||
@@ -0,0 +1,162 @@ | |||
/* | |||
* 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. | |||
*/ | |||
#include <engine/Engine.hpp> | |||
#include <patch.hpp> | |||
#include <system.hpp> | |||
#ifdef NDEBUG | |||
# undef DEBUG | |||
#endif | |||
#include "CardinalRemote.hpp" | |||
#include "PluginContext.hpp" | |||
#include "extra/Base64.hpp" | |||
#if defined(STATIC_BUILD) || CARDINAL_VARIANT_MINI | |||
# undef HAVE_LIBLO | |||
#endif | |||
#ifdef HAVE_LIBLO | |||
# include <lo/lo.h> | |||
#endif | |||
// ----------------------------------------------------------------------------------------------------------- | |||
namespace remoteUtils { | |||
#ifdef HAVE_LIBLO | |||
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<RemoteDetails*>(self)->connected = true; | |||
} | |||
return 0; | |||
} | |||
#endif | |||
RemoteDetails* getRemote() | |||
{ | |||
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); | |||
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, nullptr); | |||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context->ui); | |||
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, nullptr); | |||
return ui->remoteDetails; | |||
} | |||
bool connectToRemote() | |||
{ | |||
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); | |||
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr, false); | |||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context->ui); | |||
DISTRHO_SAFE_ASSERT_RETURN(ui != nullptr, false); | |||
RemoteDetails* remoteDetails = ui->remoteDetails; | |||
#ifdef HAVE_LIBLO | |||
if (remoteDetails == nullptr) | |||
{ | |||
const lo_server oscServer = lo_server_new_with_proto(nullptr, LO_UDP, nullptr); | |||
DISTRHO_SAFE_ASSERT_RETURN(oscServer != nullptr, false); | |||
remoteDetails = new RemoteDetails; | |||
remoteDetails->handle = oscServer; | |||
remoteDetails->connected = false; | |||
remoteDetails->autoDeploy = false; | |||
lo_server_add_method(oscServer, "/resp", nullptr, osc_handler, remoteDetails); | |||
} | |||
if (const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT)) | |||
{ | |||
lo_send(addr, "/hello", ""); | |||
lo_address_free(addr); | |||
} | |||
#endif | |||
return remoteDetails != nullptr; | |||
} | |||
void disconnectFromRemote(RemoteDetails* const remote) | |||
{ | |||
if (remote != nullptr) | |||
{ | |||
#ifdef HAVE_LIBLO | |||
lo_server_free(static_cast<lo_server>(remote->handle)); | |||
delete remote; | |||
#endif | |||
} | |||
} | |||
void idleRemote(RemoteDetails* const remote) | |||
{ | |||
#ifdef HAVE_LIBLO | |||
while (lo_server_recv_noblock(static_cast<lo_server>(remote->handle), 0) != 0) {} | |||
#endif | |||
} | |||
void deployToRemote(RemoteDetails* const remote) | |||
{ | |||
#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 sendScreenshotToRemote(RemoteDetails* const remote, const char* const screenshot) | |||
{ | |||
#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,); | |||
std::vector<uint8_t> data(d_getChunkFromBase64String(screenshot)); | |||
if (const lo_blob blob = lo_blob_new(data.size(), data.data())) | |||
{ | |||
lo_send(addr, "/screenshot", "b", blob); | |||
lo_blob_free(blob); | |||
} | |||
lo_address_free(addr); | |||
#endif | |||
} | |||
} | |||
// ----------------------------------------------------------------------------------------------------------- |
@@ -0,0 +1,45 @@ | |||
/* | |||
* 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. | |||
*/ | |||
#pragma once | |||
#ifdef HAVE_LIBLO | |||
// # define REMOTE_HOST "localhost" | |||
# define REMOTE_HOST "192.168.51.1" | |||
# define REMOTE_HOST_PORT "2228" | |||
#endif | |||
// ----------------------------------------------------------------------------------------------------------- | |||
namespace remoteUtils { | |||
struct RemoteDetails { | |||
void* handle; | |||
bool connected; | |||
bool autoDeploy; | |||
}; | |||
RemoteDetails* getRemote(); | |||
bool connectToRemote(); | |||
void disconnectFromRemote(RemoteDetails* remote); | |||
void idleRemote(RemoteDetails* remote); | |||
void deployToRemote(RemoteDetails* remote); | |||
void sendScreenshotToRemote(RemoteDetails* remote, const char* screenshot); | |||
} | |||
// ----------------------------------------------------------------------------------------------------------- |
@@ -0,0 +1 @@ | |||
../CardinalRemote.cpp |
@@ -96,6 +96,7 @@ endif | |||
FILES_DSP = CardinalPlugin.cpp | |||
FILES_DSP += CardinalCommon.cpp | |||
FILES_DSP += CardinalRemote.cpp | |||
FILES_DSP += common.cpp | |||
ifeq ($(CARDINAL_VARIANT),mini) | |||
@@ -251,6 +252,7 @@ ifeq ($(CARDINAL_VARIANT),mini) | |||
ifneq ($(HEADLESS),true) | |||
FILES_UI = CardinalUI.cpp | |||
FILES_UI += CardinalCommon-UI.cpp | |||
FILES_UI += CardinalRemote.cpp | |||
FILES_UI += common.cpp | |||
FILES_UI += glfw.cpp | |||
FILES_UI += Window.cpp | |||
@@ -25,8 +25,8 @@ | |||
# undef DEBUG | |||
#endif | |||
#include "CardinalRemote.hpp" | |||
#include "DistrhoPlugin.hpp" | |||
#include "extra/Mutex.hpp" | |||
#ifndef HEADLESS | |||
# include "DistrhoUI.hpp" | |||
@@ -148,6 +148,7 @@ struct WasmRemotePatchLoadingDialog; | |||
class CardinalBaseUI : public UI { | |||
public: | |||
CardinalPluginContext* const context; | |||
remoteUtils::RemoteDetails* remoteDetails; | |||
bool saving; | |||
bool savingUncompressed; | |||
@@ -166,6 +167,7 @@ public: | |||
#else | |||
context(new CardinalPluginContext(nullptr)), | |||
#endif | |||
remoteDetails(nullptr), | |||
saving(false), | |||
savingUncompressed(false), | |||
#ifdef DISTRHO_OS_WASM | |||
@@ -180,6 +182,8 @@ public: | |||
~CardinalBaseUI() override | |||
{ | |||
disconnectFromRemote(remoteDetails); | |||
if (filebrowserhandle != nullptr) | |||
fileBrowserClose(filebrowserhandle); | |||
@@ -52,6 +52,7 @@ | |||
#include <library.hpp> | |||
#include "../CardinalCommon.hpp" | |||
#include "../CardinalRemote.hpp" | |||
#include "DistrhoStandaloneUtils.hpp" | |||
#ifdef HAVE_LIBLO | |||
@@ -169,19 +170,20 @@ struct FileButton : MenuButton { | |||
#ifdef HAVE_LIBLO | |||
menu->addChild(new ui::MenuSeparator); | |||
if (patchUtils::isRemoteConnected()) { | |||
menu->addChild(createMenuItem("Deploy to MOD", "F7", []() { | |||
patchUtils::deployToRemote(); | |||
remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote(); | |||
if (remoteDetails != nullptr && remoteDetails->connected) { | |||
menu->addChild(createMenuItem("Deploy to MOD", "F7", [remoteDetails]() { | |||
remoteUtils::deployToRemote(remoteDetails); | |||
})); | |||
const bool autoDeploy = patchUtils::isRemoteAutoDeployed(); | |||
menu->addChild(createCheckMenuItem("Auto deploy to MOD", "", | |||
[=]() {return autoDeploy;}, | |||
[=]() {patchUtils::setRemoteAutoDeploy(!autoDeploy);} | |||
[remoteDetails]() {return remoteDetails->autoDeploy;}, | |||
[remoteDetails]() {remoteDetails->autoDeploy = !remoteDetails->autoDeploy;} | |||
)); | |||
} else { | |||
menu->addChild(createMenuItem("Connect to MOD", "", []() { | |||
patchUtils::connectToRemote(); | |||
remoteUtils::connectToRemote(); | |||
})); | |||
} | |||
#endif | |||
@@ -25,10 +25,6 @@ | |||
* the License, or (at your option) any later version. | |||
*/ | |||
#include <thread> | |||
#include <osdialog.h> | |||
#include <app/Scene.hpp> | |||
#include <app/Browser.hpp> | |||
#include <app/TipWindow.hpp> | |||
@@ -46,17 +42,8 @@ | |||
# undef DEBUG | |||
#endif | |||
#ifdef STATIC_BUILD | |||
# undef HAVE_LIBLO | |||
#endif | |||
#ifdef HAVE_LIBLO | |||
# include <lo/lo.h> | |||
#endif | |||
#include "../CardinalCommon.hpp" | |||
#include "extra/Base64.hpp" | |||
#include "DistrhoUtils.hpp" | |||
#include "../CardinalRemote.hpp" | |||
namespace rack { | |||
@@ -131,30 +118,8 @@ struct Scene::Internal { | |||
bool heldArrowKeys[4] = {}; | |||
#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); | |||
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 | |||
}; | |||
@@ -238,22 +203,20 @@ void Scene::step() { | |||
rackScroll->offset += arrowDelta * arrowSpeed; | |||
} | |||
#ifdef HAVE_LIBLO | |||
if (internal->oscServer != nullptr) { | |||
while (lo_server_recv_noblock(internal->oscServer, 0) != 0) {} | |||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) { | |||
idleRemote(remoteDetails); | |||
if (internal->oscAutoDeploy) { | |||
if (remoteDetails->autoDeploy) { | |||
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(); | |||
remoteUtils::deployToRemote(remoteDetails); | |||
window::generateScreenshot(); | |||
} | |||
} | |||
} | |||
#endif | |||
Widget::step(); | |||
} | |||
@@ -352,7 +315,7 @@ void Scene::onHoverKey(const HoverKeyEvent& e) { | |||
e.consume(this); | |||
} | |||
if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { | |||
patchUtils::deployToRemote(); | |||
remoteUtils::deployToRemote(remoteUtils::getRemote()); | |||
window::generateScreenshot(); | |||
e.consume(this); | |||
} | |||
@@ -489,94 +452,3 @@ void Scene::onPathDrop(const PathDropEvent& e) { | |||
} // namespace app | |||
} // namespace rack | |||
namespace patchUtils { | |||
bool connectToRemote() { | |||
#ifdef HAVE_LIBLO | |||
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; | |||
#else | |||
return false; | |||
#endif | |||
} | |||
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 | |||
} | |||
void sendScreenshotToRemote(const char* const screenshot) { | |||
#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,); | |||
std::vector<uint8_t> data(d_getChunkFromBase64String(screenshot)); | |||
if (const lo_blob blob = lo_blob_new(data.size(), data.data())) { | |||
lo_send(addr, "/screenshot", "b", blob); | |||
lo_blob_free(blob); | |||
} | |||
lo_address_free(addr); | |||
#endif | |||
} | |||
} // namespace patchUtils |
@@ -584,8 +584,11 @@ static void Window__downscaleBitmap(uint8_t* pixels, int& width, int& height) { | |||
static void Window__writeImagePNG(void* context, void* data, int size) { | |||
USE_NAMESPACE_DISTRHO | |||
UI* const ui = static_cast<UI*>(context); | |||
ui->setState("screenshot", String::asBase64(data, size).buffer()); | |||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context); | |||
if (const char* const screenshot = String::asBase64(data, size).buffer()) { | |||
ui->setState("screenshot", screenshot); | |||
remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); | |||
} | |||
} | |||
#endif | |||
#endif | |||