Move code related to push-to-remote into a central file

Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
falkTX 2022-12-29 12:16:43 +00:00
parent cebb66f290
commit b71acc9f22
No known key found for this signature in database
GPG key ID: CDBAA37ABC74FBA0
15 changed files with 278 additions and 211 deletions

View file

@ -0,0 +1 @@
../CardinalRemote.cpp

View file

@ -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,);
oscServerThread = lo_server_thread_new_with_proto(REMOTE_HOST_PORT, LO_UDP, osc_error_handler);
DISTRHO_SAFE_ASSERT_RETURN(oscServerThread != 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);
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

View file

@ -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

View file

@ -0,0 +1 @@
../CardinalRemote.cpp

View file

@ -0,0 +1 @@
../CardinalRemote.cpp

View file

@ -0,0 +1 @@
../CardinalRemote.cpp

View file

@ -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;
}

162
src/CardinalRemote.cpp Normal file
View file

@ -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
}
}
// -----------------------------------------------------------------------------------------------------------

45
src/CardinalRemote.hpp Normal file
View file

@ -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);
}
// -----------------------------------------------------------------------------------------------------------

View file

@ -0,0 +1 @@
../CardinalRemote.cpp

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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