Signed-off-by: falkTX <falktx@falktx.com>tags/24.09
@@ -362,6 +362,15 @@ static int osc_hello_handler(const char*, const char*, lo_arg**, int, const lo_m | |||||
d_stdout("Hello received from OSC, saying hello back to them o/"); | d_stdout("Hello received from OSC, saying hello back to them o/"); | ||||
const lo_address source = lo_message_get_source(m); | const lo_address source = lo_message_get_source(m); | ||||
const lo_server server = static_cast<Initializer*>(self)->oscServer; | const lo_server server = static_cast<Initializer*>(self)->oscServer; | ||||
// send list of features first | |||||
#ifdef CARDINAL_INIT_OSC_THREAD | |||||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "features", ":screenshot:"); | |||||
#else | |||||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "features", ""); | |||||
#endif | |||||
// then finally hello reply | |||||
lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "hello", "ok"); | lo_send_from(source, server, LO_TT_IMMEDIATE, "/resp", "ss", "hello", "ok"); | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -386,7 +395,10 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a | |||||
std::vector<uint8_t> data(size); | std::vector<uint8_t> data(size); | ||||
std::memcpy(data.data(), blob, size); | std::memcpy(data.data(), blob, size); | ||||
#ifdef CARDINAL_INIT_OSC_THREAD | |||||
rack::contextSet(context); | rack::contextSet(context); | ||||
#endif | |||||
rack::system::removeRecursively(context->patch->autosavePath); | rack::system::removeRecursively(context->patch->autosavePath); | ||||
rack::system::createDirectories(context->patch->autosavePath); | rack::system::createDirectories(context->patch->autosavePath); | ||||
try { | try { | ||||
@@ -397,7 +409,10 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a | |||||
catch (rack::Exception& e) { | catch (rack::Exception& e) { | ||||
WARN("%s", e.what()); | WARN("%s", e.what()); | ||||
} | } | ||||
#ifdef CARDINAL_INIT_OSC_THREAD | |||||
rack::contextSet(nullptr); | rack::contextSet(nullptr); | ||||
#endif | |||||
} | } | ||||
const lo_address source = lo_message_get_source(m); | const lo_address source = lo_message_get_source(m); | ||||
@@ -423,10 +438,18 @@ static int osc_param_handler(const char*, const char* types, lo_arg** argv, int | |||||
const int paramId = argv[1]->i; | const int paramId = argv[1]->i; | ||||
const float paramValue = argv[2]->f; | const float paramValue = argv[2]->f; | ||||
#ifdef CARDINAL_INIT_OSC_THREAD | |||||
rack::contextSet(context); | |||||
#endif | |||||
rack::engine::Module* const module = context->engine->getModule(moduleId); | rack::engine::Module* const module = context->engine->getModule(moduleId); | ||||
DISTRHO_SAFE_ASSERT_RETURN(module != nullptr, 0); | DISTRHO_SAFE_ASSERT_RETURN(module != nullptr, 0); | ||||
context->engine->setParamValue(module, paramId, paramValue); | context->engine->setParamValue(module, paramId, paramValue); | ||||
#ifdef CARDINAL_INIT_OSC_THREAD | |||||
rack::contextSet(nullptr); | |||||
#endif | |||||
} | } | ||||
return 0; | return 0; | ||||
@@ -1,18 +1,7 @@ | |||||
/* | /* | ||||
* DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
* Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2021-2024 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. | |||||
* SPDX-License-Identifier: GPL-3.0-or-later | |||||
*/ | */ | ||||
#include <engine/Engine.hpp> | #include <engine/Engine.hpp> | ||||
@@ -40,6 +29,12 @@ | |||||
# include <lo/lo.h> | # include <lo/lo.h> | ||||
#endif | #endif | ||||
namespace rack { | |||||
namespace engine { | |||||
void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------------------------------------------- | // ----------------------------------------------------------------------------------------------------------- | ||||
namespace remoteUtils { | namespace remoteUtils { | ||||
@@ -53,8 +48,15 @@ static int osc_handler(const char* const path, const char* const types, lo_arg** | |||||
{ | { | ||||
d_stdout("osc_handler(\"%s\", ...) - got resp | '%s' '%s'", path, &argv[0]->s, &argv[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; | |||||
if (std::strcmp(&argv[0]->s, "hello") == 0) | |||||
{ | |||||
if (std::strcmp(&argv[1]->s, "ok") == 0) | |||||
static_cast<RemoteDetails*>(self)->connected = true; | |||||
} | |||||
else if (std::strcmp(&argv[0]->s, "features") == 0) | |||||
{ | |||||
static_cast<RemoteDetails*>(self)->screenshot = std::strstr(&argv[1]->s, ":screenshot:") != nullptr; | |||||
} | |||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
@@ -92,8 +94,10 @@ bool connectToRemote(const char* const url) | |||||
ui->remoteDetails = remoteDetails = new RemoteDetails; | ui->remoteDetails = remoteDetails = new RemoteDetails; | ||||
remoteDetails->handle = ui; | remoteDetails->handle = ui; | ||||
remoteDetails->url = strdup(url); | remoteDetails->url = strdup(url); | ||||
remoteDetails->connected = true; | |||||
remoteDetails->autoDeploy = true; | remoteDetails->autoDeploy = true; | ||||
remoteDetails->connected = true; | |||||
remoteDetails->first = false; | |||||
remoteDetails->screenshot = false; | |||||
} | } | ||||
#elif defined(HAVE_LIBLO) | #elif defined(HAVE_LIBLO) | ||||
const lo_address addr = lo_address_new_from_url(url); | const lo_address addr = lo_address_new_from_url(url); | ||||
@@ -107,10 +111,16 @@ bool connectToRemote(const char* const url) | |||||
ui->remoteDetails = remoteDetails = new RemoteDetails; | ui->remoteDetails = remoteDetails = new RemoteDetails; | ||||
remoteDetails->handle = oscServer; | remoteDetails->handle = oscServer; | ||||
remoteDetails->url = strdup(url); | remoteDetails->url = strdup(url); | ||||
remoteDetails->autoDeploy = true; | |||||
remoteDetails->first = true; | |||||
remoteDetails->connected = false; | remoteDetails->connected = false; | ||||
remoteDetails->autoDeploy = false; | |||||
remoteDetails->screenshot = false; | |||||
lo_server_add_method(oscServer, "/resp", nullptr, osc_handler, remoteDetails); | lo_server_add_method(oscServer, "/resp", nullptr, osc_handler, remoteDetails); | ||||
sendFullPatchToRemote(remoteDetails); | |||||
Engine_setRemoteDetails(context->engine, remoteDetails); | |||||
} | } | ||||
else if (std::strcmp(remoteDetails->url, url) != 0) | else if (std::strcmp(remoteDetails->url, url) != 0) | ||||
{ | { | ||||
@@ -1,18 +1,7 @@ | |||||
/* | /* | ||||
* DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
* Copyright (C) 2021-2023 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. | |||||
* Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||||
* SPDX-License-Identifier: GPL-3.0-or-later | |||||
*/ | */ | ||||
#pragma once | #pragma once | ||||
@@ -27,8 +16,10 @@ namespace remoteUtils { | |||||
struct RemoteDetails { | struct RemoteDetails { | ||||
void* handle; | void* handle; | ||||
const char* url; | const char* url; | ||||
bool connected; | |||||
bool autoDeploy; | bool autoDeploy; | ||||
bool first; | |||||
bool connected; | |||||
bool screenshot; | |||||
}; | }; | ||||
RemoteDetails* getRemote(); | RemoteDetails* getRemote(); | ||||
@@ -1,18 +1,7 @@ | |||||
/* | /* | ||||
* DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
* Copyright (C) 2021-2023 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. | |||||
* Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||||
* SPDX-License-Identifier: GPL-3.0-or-later | |||||
*/ | */ | ||||
/** | /** | ||||
@@ -295,7 +284,7 @@ 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->remoteDetails != nullptr) { | |||||
if (internal->remoteDetails != nullptr && internal->remoteDetails->connected) { | |||||
newValue = value; | newValue = value; | ||||
sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value); | sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value); | ||||
} else { | } else { | ||||
@@ -1094,7 +1083,7 @@ 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) { | |||||
if (internal->remoteDetails != nullptr && internal->remoteDetails->connected) { | |||||
sendParamChangeToRemote(internal->remoteDetails, module->id, paramId, value); | sendParamChangeToRemote(internal->remoteDetails, module->id, paramId, value); | ||||
} | } | ||||
module->params[paramId].setValue(value); | module->params[paramId].setValue(value); | ||||
@@ -1,18 +1,7 @@ | |||||
/* | /* | ||||
* DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
* Copyright (C) 2021-2023 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. | |||||
* Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | |||||
* SPDX-License-Identifier: GPL-3.0-or-later | |||||
*/ | */ | ||||
/** | /** | ||||
@@ -207,14 +196,19 @@ void Scene::step() { | |||||
if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) { | if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) { | ||||
idleRemote(remoteDetails); | idleRemote(remoteDetails); | ||||
if (remoteDetails->autoDeploy) { | |||||
if (remoteDetails->autoDeploy && remoteDetails->connected) { | |||||
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 == -1) { | if (internal->historyActionIndex == -1) { | ||||
internal->historyActionIndex = actionIndex; | internal->historyActionIndex = actionIndex; | ||||
internal->lastSceneChangeTime = time; | internal->lastSceneChangeTime = time; | ||||
} else if (internal->historyActionIndex != actionIndex && actionIndex > 0 && time - internal->lastSceneChangeTime >= 1.0) { | |||||
} else if (remoteDetails->first || | |||||
(internal->historyActionIndex != actionIndex | |||||
&& actionIndex > 0 | |||||
&& time - internal->lastSceneChangeTime >= 1.0)) { | |||||
remoteDetails->first = false; | |||||
const std::string& name(APP->history->actions[actionIndex - 1]->name); | const std::string& name(APP->history->actions[actionIndex - 1]->name); | ||||
static const std::vector<std::string> ignoredNames = { | static const std::vector<std::string> ignoredNames = { | ||||
"move knob", | "move knob", | ||||
@@ -224,7 +218,10 @@ void Scene::step() { | |||||
if (std::find(ignoredNames.cbegin(), ignoredNames.cend(), name) == ignoredNames.cend()) { | if (std::find(ignoredNames.cbegin(), ignoredNames.cend(), name) == ignoredNames.cend()) { | ||||
printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); | printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); | ||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | remoteUtils::sendFullPatchToRemote(remoteDetails); | ||||
window::generateScreenshot(); | |||||
if (remoteDetails->screenshot) { | |||||
window::generateScreenshot(); | |||||
} | |||||
} | } | ||||
internal->historyActionIndex = actionIndex; | internal->historyActionIndex = actionIndex; | ||||
internal->lastSceneChangeTime = time; | internal->lastSceneChangeTime = time; | ||||
@@ -334,8 +331,13 @@ 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::sendFullPatchToRemote(remoteDetails); | |||||
window::generateScreenshot(); | |||||
if (remoteDetails->connected) { | |||||
remoteUtils::sendFullPatchToRemote(remoteDetails); | |||||
if (remoteDetails->screenshot) { | |||||
window::generateScreenshot(); | |||||
} | |||||
} | |||||
} | } | ||||
e.consume(this); | e.consume(this); | ||||
} | } | ||||
@@ -1,18 +1,7 @@ | |||||
/* | /* | ||||
* DISTRHO Cardinal Plugin | * DISTRHO Cardinal Plugin | ||||
* Copyright (C) 2021-2024 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2021-2024 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. | |||||
* SPDX-License-Identifier: GPL-3.0-or-later | |||||
*/ | */ | ||||
/** | /** | ||||
@@ -598,7 +587,7 @@ static void Window__writeImagePNG(void* context, void* data, int size) { | |||||
CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context); | CardinalBaseUI* const ui = static_cast<CardinalBaseUI*>(context); | ||||
if (char* const screenshot = String::asBase64(data, size).getAndReleaseBuffer()) { | if (char* const screenshot = String::asBase64(data, size).getAndReleaseBuffer()) { | ||||
ui->setState("screenshot", screenshot); | ui->setState("screenshot", screenshot); | ||||
if (ui->remoteDetails != nullptr) | |||||
if (ui->remoteDetails != nullptr && ui->remoteDetails->connected && ui->remoteDetails->screenshot) | |||||
remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); | remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); | ||||
std::free(screenshot); | std::free(screenshot); | ||||
} | } | ||||