Browse Source

Add direct parameter changes to remote control, for LV2 and OSC

Signed-off-by: falkTX <falktx@falktx.com>
tags/23.02
falkTX 2 years ago
parent
commit
d0eba9e1ae
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
11 changed files with 136 additions and 33 deletions
  1. +1
    -1
      plugins/plugins.cpp
  2. +46
    -5
      src/CardinalCommon.cpp
  3. +1
    -1
      src/CardinalMini/DistrhoPluginInfo.h
  4. +16
    -0
      src/CardinalPlugin.cpp
  5. +28
    -4
      src/CardinalRemote.cpp
  6. +3
    -6
      src/CardinalRemote.hpp
  7. +4
    -2
      src/CardinalUI.cpp
  8. +16
    -3
      src/override/Engine.cpp
  9. +11
    -6
      src/override/MenuBar.cpp
  10. +8
    -4
      src/override/Scene.cpp
  11. +2
    -1
      src/override/Window.cpp

+ 1
- 1
plugins/plugins.cpp View File

@@ -1550,7 +1550,7 @@ static void initStatic__BogaudioModules()
{ {
// Make sure to use dark theme as default // Make sure to use dark theme as default
Skins& skins(Skins::skins()); Skins& skins(Skins::skins());
skins._default = "dark";
skins._default = settings::darkMode ? "dark" : "light";
#define modelADSR modelBogaudioADSR #define modelADSR modelBogaudioADSR
#define modelLFO modelBogaudioLFO #define modelLFO modelBogaudioLFO
#define modelNoise modelBogaudioNoise #define modelNoise modelBogaudioNoise


+ 46
- 5
src/CardinalCommon.cpp View File

@@ -40,6 +40,7 @@
#include <system.hpp> #include <system.hpp>
#include <app/Browser.hpp> #include <app/Browser.hpp>
#include <app/Scene.hpp> #include <app/Scene.hpp>
#include <engine/Engine.hpp>
#include <window/Window.hpp> #include <window/Window.hpp>


#ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS #ifndef DISTRHO_PLUGIN_WANT_DIRECT_ACCESS
@@ -236,7 +237,7 @@ static int osc_fallback_handler(const char* const path, const char* const types,


static int osc_hello_handler(const char*, const char*, lo_arg**, int, const lo_message m, void* const self) static int osc_hello_handler(const char*, const char*, lo_arg**, int, const lo_message m, void* const self)
{ {
d_stdout("osc_hello_handler()");
d_debug("osc_hello_handler()");
const lo_address source = lo_message_get_source(m); const lo_address source = lo_message_get_source(m);
const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread); 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"); lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "hello", "ok");
@@ -245,7 +246,7 @@ static int osc_hello_handler(const char*, const char*, lo_arg**, int, const lo_m


static int osc_load_handler(const char*, const char* types, lo_arg** argv, int argc, const lo_message m, void* const self) static int osc_load_handler(const char*, const char* types, lo_arg** argv, int argc, const lo_message m, void* const self)
{ {
d_stdout("osc_load_handler()");
d_debug("osc_load_handler()");
DISTRHO_SAFE_ASSERT_RETURN(argc == 1, 0); DISTRHO_SAFE_ASSERT_RETURN(argc == 1, 0);
DISTRHO_SAFE_ASSERT_RETURN(types != nullptr && types[0] == 'b', 0); DISTRHO_SAFE_ASSERT_RETURN(types != nullptr && types[0] == 'b', 0);


@@ -283,9 +284,35 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a
return 0; return 0;
} }


static int osc_param_handler(const char*, const char* types, lo_arg** argv, int argc, const lo_message m, void* const self)
{
d_debug("osc_param_handler()");
DISTRHO_SAFE_ASSERT_RETURN(argc == 3, 0);
DISTRHO_SAFE_ASSERT_RETURN(types != nullptr, 0);
DISTRHO_SAFE_ASSERT_RETURN(types[0] == 'h', 0);
DISTRHO_SAFE_ASSERT_RETURN(types[1] == 'i', 0);
DISTRHO_SAFE_ASSERT_RETURN(types[2] == 'f', 0);

if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->remotePluginInstance)
{
CardinalPluginContext* const context = plugin->context;

const int64_t moduleId = argv[0]->h;
const int paramId = argv[1]->i;
const float paramValue = argv[2]->f;

rack::engine::Module* const module = context->engine->getModule(moduleId);
DISTRHO_SAFE_ASSERT_RETURN(module != nullptr, 0);

context->engine->setParamValue(module, paramId, paramValue);
}

return 0;
}

static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv, int argc, const lo_message m, void* const self) static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv, int argc, const lo_message m, void* const self)
{ {
d_stdout("osc_screenshot_handler()");
d_debug("osc_screenshot_handler()");
DISTRHO_SAFE_ASSERT_RETURN(argc == 1, 0); DISTRHO_SAFE_ASSERT_RETURN(argc == 1, 0);
DISTRHO_SAFE_ASSERT_RETURN(types != nullptr && types[0] == 'b', 0); DISTRHO_SAFE_ASSERT_RETURN(types != nullptr && types[0] == 'b', 0);


@@ -298,7 +325,13 @@ static int osc_screenshot_handler(const char*, const char* types, lo_arg** argv,
bool ok = false; bool ok = false;


if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->remotePluginInstance) if (CardinalBasePlugin* const plugin = static_cast<Initializer*>(self)->remotePluginInstance)
ok = plugin->updateStateValue("screenshot", String::asBase64(blob, size).buffer());
{
if (char* const screenshot = String::asBase64(blob, size).getAndReleaseBuffer())
{
ok = plugin->updateStateValue("screenshot", screenshot);
std::free(screenshot);
}
}


const lo_address source = lo_message_get_source(m); const lo_address source = lo_message_get_source(m);
const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread); const lo_server server = lo_server_thread_get_server(static_cast<Initializer*>(self)->oscServerThread);
@@ -441,13 +474,20 @@ Initializer::Initializer(const CardinalBasePlugin* const plugin, const CardinalB


#ifdef CARDINAL_INIT_OSC_THREAD #ifdef CARDINAL_INIT_OSC_THREAD
INFO("Initializing OSC Remote control"); INFO("Initializing OSC Remote control");
oscServerThread = lo_server_thread_new_with_proto(REMOTE_HOST_PORT, LO_UDP, osc_error_handler);
const char* port;
if (const char* const portEnv = std::getenv("CARDINAL_REMOTE_HOST_PORT"))
port = portEnv;
else
port = CARDINAL_DEFAULT_REMOTE_HOST_PORT;
oscServerThread = lo_server_thread_new_with_proto(port, LO_UDP, osc_error_handler);
DISTRHO_SAFE_ASSERT_RETURN(oscServerThread != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(oscServerThread != nullptr,);


lo_server_thread_add_method(oscServerThread, "/hello", "", osc_hello_handler, this); 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, "/load", "b", osc_load_handler, this);
lo_server_thread_add_method(oscServerThread, "/param", "hif", osc_param_handler, this);
lo_server_thread_add_method(oscServerThread, "/screenshot", "b", osc_screenshot_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); lo_server_thread_add_method(oscServerThread, nullptr, nullptr, osc_fallback_handler, nullptr);
lo_server_thread_start(oscServerThread);
#else #else
INFO("OSC Remote control is not enabled in this build"); INFO("OSC Remote control is not enabled in this build");
#endif #endif
@@ -460,6 +500,7 @@ Initializer::~Initializer()
#ifdef CARDINAL_INIT_OSC_THREAD #ifdef CARDINAL_INIT_OSC_THREAD
if (oscServerThread != nullptr) if (oscServerThread != nullptr)
{ {
lo_server_thread_stop(oscServerThread);
lo_server_thread_del_method(oscServerThread, nullptr, nullptr); lo_server_thread_del_method(oscServerThread, nullptr, nullptr);
lo_server_thread_free(oscServerThread); lo_server_thread_free(oscServerThread);
oscServerThread = nullptr; oscServerThread = nullptr;


+ 1
- 1
src/CardinalMini/DistrhoPluginInfo.h View File

@@ -53,7 +53,7 @@
#define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Generator" #define DISTRHO_PLUGIN_VST3_CATEGORIES "Fx|Generator"


// #ifdef __MOD_DEVICES__ // #ifdef __MOD_DEVICES__
// # define DISTRHO_PLUGIN_USES_MODGUI 1
# define DISTRHO_PLUGIN_USES_MODGUI 1
// #endif // #endif


#endif // DISTRHO_PLUGIN_INFO_H_INCLUDED #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED

+ 16
- 0
src/CardinalPlugin.cpp View File

@@ -794,6 +794,22 @@ protected:
void setState(const char* const key, const char* const value) override void setState(const char* const key, const char* const value) override
{ {
#if CARDINAL_VARIANT_MINI
if (std::strcmp(key, "param") == 0)
{
int64_t moduleId = 0;
int paramId = 0;
float paramValue = 0.f;
std::sscanf(value, "%lu:%d:%f", &moduleId, &paramId, &paramValue);
rack::engine::Module* const module = context->engine->getModule(moduleId);
DISTRHO_SAFE_ASSERT_RETURN(module != nullptr,);
context->engine->setParamValue(module, paramId, paramValue);
return;
}
#endif
#ifndef HEADLESS #ifndef HEADLESS
if (std::strcmp(key, "moduleInfos") == 0) if (std::strcmp(key, "moduleInfos") == 0)
{ {


+ 28
- 4
src/CardinalRemote.cpp View File

@@ -35,6 +35,11 @@
# include <lo/lo.h> # include <lo/lo.h>
#endif #endif


#ifdef HAVE_LIBLO
// # define REMOTE_HOST "localhost"
# define REMOTE_HOST "192.168.51.1"
#endif

// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------


namespace remoteUtils { namespace remoteUtils {
@@ -98,7 +103,10 @@ bool connectToRemote()
lo_server_add_method(oscServer, "/resp", nullptr, osc_handler, remoteDetails); 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))
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT(addr != nullptr);

if (addr != nullptr)
{ {
lo_send(addr, "/hello", ""); lo_send(addr, "/hello", "");
lo_address_free(addr); lo_address_free(addr);
@@ -127,7 +135,23 @@ void idleRemote(RemoteDetails* const remote)
#endif #endif
} }


void deployToRemote(RemoteDetails* const remote)
void sendParamChangeToRemote(RemoteDetails* const remote, int64_t moduleId, int paramId, float value)
{
#if CARDINAL_VARIANT_MINI
char paramBuf[512] = {};
std::snprintf(paramBuf, sizeof(paramBuf), "%lu:%d:%f", moduleId, paramId, value);
static_cast<CardinalBaseUI*>(remote->handle)->setState("param", paramBuf);
#elif defined(HAVE_LIBLO)
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);

lo_send(addr, "/param", "hif", moduleId, paramId, value);

lo_address_free(addr);
#endif
}

void sendFullPatchToRemote(RemoteDetails* const remote)
{ {
CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP); CardinalPluginContext* const context = static_cast<CardinalPluginContext*>(APP);
DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(context != nullptr,);
@@ -146,7 +170,7 @@ void deployToRemote(RemoteDetails* const remote)
std::free(patch); std::free(patch);
} }
#elif defined(HAVE_LIBLO) #elif defined(HAVE_LIBLO)
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT);
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);


if (const lo_blob blob = lo_blob_new(data.size(), data.data())) if (const lo_blob blob = lo_blob_new(data.size(), data.data()))
@@ -162,7 +186,7 @@ void deployToRemote(RemoteDetails* const remote)
void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot) void sendScreenshotToRemote(RemoteDetails*, const char* const screenshot)
{ {
#ifdef HAVE_LIBLO #ifdef HAVE_LIBLO
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, REMOTE_HOST_PORT);
const lo_address addr = lo_address_new_with_proto(LO_UDP, REMOTE_HOST, CARDINAL_DEFAULT_REMOTE_HOST_PORT);
DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,); DISTRHO_SAFE_ASSERT_RETURN(addr != nullptr,);


std::vector<uint8_t> data(d_getChunkFromBase64String(screenshot)); std::vector<uint8_t> data(d_getChunkFromBase64String(screenshot));


+ 3
- 6
src/CardinalRemote.hpp View File

@@ -17,11 +17,7 @@


#pragma once #pragma once


#ifdef HAVE_LIBLO
// # define REMOTE_HOST "localhost"
# define REMOTE_HOST "192.168.51.1"
# define REMOTE_HOST_PORT "2228"
#endif
#define CARDINAL_DEFAULT_REMOTE_HOST_PORT "2228"


// ----------------------------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------------------------


@@ -37,7 +33,8 @@ RemoteDetails* getRemote();
bool connectToRemote(); bool connectToRemote();
void disconnectFromRemote(RemoteDetails* remote); void disconnectFromRemote(RemoteDetails* remote);
void idleRemote(RemoteDetails* remote); void idleRemote(RemoteDetails* remote);
void deployToRemote(RemoteDetails* remote);
void sendParamChangeToRemote(RemoteDetails* remote, int64_t moduleId, int paramId, float value);
void sendFullPatchToRemote(RemoteDetails* remote);
void sendScreenshotToRemote(RemoteDetails* remote, const char* screenshot); void sendScreenshotToRemote(RemoteDetails* remote, const char* screenshot);


} }


+ 4
- 2
src/CardinalUI.cpp View File

@@ -64,6 +64,7 @@
namespace rack { namespace rack {
namespace engine { namespace engine {
void Engine_setAboutToClose(Engine*); void Engine_setAboutToClose(Engine*);
void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*);
} }
namespace window { namespace window {
void WindowSetPluginUI(Window* window, DISTRHO_NAMESPACE::UI* ui); void WindowSetPluginUI(Window* window, DISTRHO_NAMESPACE::UI* ui);
@@ -344,8 +345,7 @@ public:
rack::contextSet(context); rack::contextSet(context);


#if CARDINAL_VARIANT_MINI #if CARDINAL_VARIANT_MINI
DISTRHO_SAFE_ASSERT_RETURN(remoteUtils::connectToRemote(),);
DISTRHO_SAFE_ASSERT_RETURN(remoteDetails != nullptr,);
remoteUtils::connectToRemote();


// create unique temporary path for this instance // create unique temporary path for this instance
try { try {
@@ -387,6 +387,8 @@ public:
context->window = new rack::window::Window; context->window = new rack::window::Window;


context->scene->rackScroll->reset(); context->scene->rackScroll->reset();

Engine_setRemoteDetails(context->engine, remoteDetails);
#endif #endif


Window& window(getWindow()); Window& window(getWindow());


+ 16
- 3
src/override/Engine.cpp View File

@@ -49,6 +49,7 @@
# undef DEBUG # undef DEBUG
#endif #endif


#include "../CardinalRemote.hpp"
#include "DistrhoUtils.hpp" #include "DistrhoUtils.hpp"




@@ -97,6 +98,9 @@ struct Engine::Internal {
int smoothParamId = 0; int smoothParamId = 0;
float smoothValue = 0.f; float smoothValue = 0.f;


// Remote control
remoteUtils::RemoteDetails* remoteDetails = nullptr;

/** Mutex that guards the Engine state, such as settings, Modules, and Cables. /** Mutex that guards the Engine state, such as settings, Modules, and Cables.
Writers lock when mutating the engine's state or stepping the block. Writers lock when mutating the engine's state or stepping the block.
Readers lock when using the engine's state. Readers lock when using the engine's state.
@@ -210,12 +214,13 @@ static void Engine_stepFrame(Engine* that) {
Param* smoothParam = &smoothModule->params[smoothParamId]; Param* smoothParam = &smoothModule->params[smoothParamId];
float value = smoothParam->value; float value = smoothParam->value;
float newValue; float newValue;
if (internal->blockFrames != 1) {
if (internal->remoteDetails != nullptr) {
newValue = value;
sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value);
} else {
// Use decay rate of roughly 1 graphics frame // Use decay rate of roughly 1 graphics frame
const float smoothLambda = 60.f; const float smoothLambda = 60.f;
newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime; newValue = value + (smoothValue - value) * smoothLambda * internal->sampleTime;
} else {
newValue = value;
} }
if (d_isEqual(value, newValue)) { if (d_isEqual(value, newValue)) {
// Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats) // Snap to actual smooth value if the value doesn't change enough (due to the granularity of floats)
@@ -1013,6 +1018,9 @@ void Engine::setParamValue(Module* module, int paramId, float value) {
internal->smoothModule = NULL; internal->smoothModule = NULL;
internal->smoothParamId = 0; internal->smoothParamId = 0;
} }
if (internal->remoteDetails != nullptr) {
sendParamChangeToRemote(internal->remoteDetails, module->id, paramId, value);
}
module->params[paramId].value = value; module->params[paramId].value = value;
} }


@@ -1263,5 +1271,10 @@ void Engine_setAboutToClose(Engine* const engine) {
} }




void Engine_setRemoteDetails(Engine* const engine, remoteUtils::RemoteDetails* const remoteDetails) {
engine->internal->remoteDetails = remoteDetails;
}


} // namespace engine } // namespace engine
} // namespace rack } // namespace rack

+ 11
- 6
src/override/MenuBar.cpp View File

@@ -66,7 +66,9 @@ namespace rack {
namespace asset { namespace asset {
std::string patchesPath(); std::string patchesPath();
} }

namespace engine {
void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*);
}
namespace plugin { namespace plugin {
void updateStaticPluginsDarkMode(); void updateStaticPluginsDarkMode();
} }
@@ -168,26 +170,29 @@ struct FileButton : MenuButton {
patchUtils::revertDialog(); patchUtils::revertDialog();
}, APP->patch->path.empty())); }, APP->patch->path.empty()));


// #if defined(HAVE_LIBLO) && ! CARDINAL_VARIANT_MINI
#if defined(HAVE_LIBLO) && ! CARDINAL_VARIANT_MINI
menu->addChild(new ui::MenuSeparator); menu->addChild(new ui::MenuSeparator);


remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote(); remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote();


if (remoteDetails != nullptr && remoteDetails->connected) { if (remoteDetails != nullptr && remoteDetails->connected) {
menu->addChild(createMenuItem("Deploy to MOD", "F7", [remoteDetails]() { menu->addChild(createMenuItem("Deploy to MOD", "F7", [remoteDetails]() {
remoteUtils::deployToRemote(remoteDetails);
remoteUtils::sendFullPatchToRemote(remoteDetails);
})); }));


menu->addChild(createCheckMenuItem("Auto deploy to MOD", "", menu->addChild(createCheckMenuItem("Auto deploy to MOD", "",
[remoteDetails]() {return remoteDetails->autoDeploy;}, [remoteDetails]() {return remoteDetails->autoDeploy;},
[remoteDetails]() {remoteDetails->autoDeploy = !remoteDetails->autoDeploy;}
[remoteDetails]() {
remoteDetails->autoDeploy = !remoteDetails->autoDeploy;
Engine_setRemoteDetails(APP->engine, remoteDetails->autoDeploy ? remoteDetails : nullptr);
}
)); ));
} else { } else {
menu->addChild(createMenuItem("Connect to MOD", "", []() { menu->addChild(createMenuItem("Connect to MOD", "", []() {
remoteUtils::connectToRemote();
DISTRHO_SAFE_ASSERT(remoteUtils::connectToRemote());
})); }));
} }
// #endif
#endif


#ifndef DISTRHO_OS_WASM #ifndef DISTRHO_OS_WASM
menu->addChild(new ui::MenuSeparator); menu->addChild(new ui::MenuSeparator);


+ 8
- 4
src/override/Scene.cpp View File

@@ -212,11 +212,15 @@ void Scene::step() {
if (remoteDetails->autoDeploy) { if (remoteDetails->autoDeploy) {
const int actionIndex = APP->history->actionIndex; const int actionIndex = APP->history->actionIndex;
const double time = system::getTime(); const double time = system::getTime();
if (internal->historyActionIndex != actionIndex && time - internal->lastSceneChangeTime >= 1.0) {
if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) {
const std::string& name(APP->history->actions[actionIndex - 1]->name);
if (/*std::abs(internal->historyActionIndex = actionIndex) > 1 ||*/ name != "move knob") {
printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str());
remoteUtils::sendFullPatchToRemote(remoteDetails);
window::generateScreenshot();
}
internal->historyActionIndex = actionIndex; internal->historyActionIndex = actionIndex;
internal->lastSceneChangeTime = time; internal->lastSceneChangeTime = time;
remoteUtils::deployToRemote(remoteDetails);
window::generateScreenshot();
} }
} }
} }
@@ -319,7 +323,7 @@ void Scene::onHoverKey(const HoverKeyEvent& e) {
} }
if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) { if (e.key == GLFW_KEY_F7 && (e.mods & RACK_MOD_MASK) == 0) {
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote())
remoteUtils::deployToRemote(remoteDetails);
remoteUtils::sendFullPatchToRemote(remoteDetails);
window::generateScreenshot(); window::generateScreenshot();
e.consume(this); e.consume(this);
} }


+ 2
- 1
src/override/Window.cpp View File

@@ -585,9 +585,10 @@ static void Window__downscaleBitmap(uint8_t* pixels, int& width, int& height) {
static void Window__writeImagePNG(void* context, void* data, int size) { static void Window__writeImagePNG(void* context, void* data, int size) {
USE_NAMESPACE_DISTRHO USE_NAMESPACE_DISTRHO
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context); CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context);
if (const char* const screenshot = String::asBase64(data, size).buffer()) {
if (char* const screenshot = String::asBase64(data, size).getAndReleaseBuffer()) {
ui->setState("screenshot", screenshot); ui->setState("screenshot", screenshot);
remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot);
std::free(screenshot);
} }
} }
#endif #endif


Loading…
Cancel
Save