diff --git a/src/CardinalCommon.cpp b/src/CardinalCommon.cpp index 3226cc0..eabdcd7 100644 --- a/src/CardinalCommon.cpp +++ b/src/CardinalCommon.cpp @@ -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/"); const lo_address source = lo_message_get_source(m); const lo_server server = static_cast(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"); return 0; } @@ -386,7 +395,10 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a std::vector data(size); std::memcpy(data.data(), blob, size); + #ifdef CARDINAL_INIT_OSC_THREAD rack::contextSet(context); + #endif + rack::system::removeRecursively(context->patch->autosavePath); rack::system::createDirectories(context->patch->autosavePath); try { @@ -397,7 +409,10 @@ static int osc_load_handler(const char*, const char* types, lo_arg** argv, int a catch (rack::Exception& e) { WARN("%s", e.what()); } + + #ifdef CARDINAL_INIT_OSC_THREAD rack::contextSet(nullptr); + #endif } 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 float paramValue = argv[2]->f; + #ifdef CARDINAL_INIT_OSC_THREAD + rack::contextSet(context); + #endif + rack::engine::Module* const module = context->engine->getModule(moduleId); DISTRHO_SAFE_ASSERT_RETURN(module != nullptr, 0); context->engine->setParamValue(module, paramId, paramValue); + + #ifdef CARDINAL_INIT_OSC_THREAD + rack::contextSet(nullptr); + #endif } return 0; diff --git a/src/CardinalRemote.cpp b/src/CardinalRemote.cpp index 14db71d..c52023e 100644 --- a/src/CardinalRemote.cpp +++ b/src/CardinalRemote.cpp @@ -1,18 +1,7 @@ /* * DISTRHO Cardinal Plugin * Copyright (C) 2021-2024 Filipe Coelho - * - * 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 @@ -40,6 +29,12 @@ # include #endif +namespace rack { +namespace engine { +void Engine_setRemoteDetails(Engine*, remoteUtils::RemoteDetails*); +} +} + // ----------------------------------------------------------------------------------------------------------- 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); - if (std::strcmp(&argv[0]->s, "hello") == 0 && std::strcmp(&argv[1]->s, "ok") == 0) - static_cast(self)->connected = true; + if (std::strcmp(&argv[0]->s, "hello") == 0) + { + if (std::strcmp(&argv[1]->s, "ok") == 0) + static_cast(self)->connected = true; + } + else if (std::strcmp(&argv[0]->s, "features") == 0) + { + static_cast(self)->screenshot = std::strstr(&argv[1]->s, ":screenshot:") != nullptr; + } } return 0; } @@ -92,8 +94,10 @@ bool connectToRemote(const char* const url) ui->remoteDetails = remoteDetails = new RemoteDetails; remoteDetails->handle = ui; remoteDetails->url = strdup(url); - remoteDetails->connected = true; remoteDetails->autoDeploy = true; + remoteDetails->connected = true; + remoteDetails->first = false; + remoteDetails->screenshot = false; } #elif defined(HAVE_LIBLO) 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; remoteDetails->handle = oscServer; remoteDetails->url = strdup(url); + remoteDetails->autoDeploy = true; + remoteDetails->first = true; remoteDetails->connected = false; - remoteDetails->autoDeploy = false; + remoteDetails->screenshot = false; 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) { diff --git a/src/CardinalRemote.hpp b/src/CardinalRemote.hpp index 991c995..6b67318 100644 --- a/src/CardinalRemote.hpp +++ b/src/CardinalRemote.hpp @@ -1,18 +1,7 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021-2023 Filipe Coelho - * - * 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 + * SPDX-License-Identifier: GPL-3.0-or-later */ #pragma once @@ -27,8 +16,10 @@ namespace remoteUtils { struct RemoteDetails { void* handle; const char* url; - bool connected; bool autoDeploy; + bool first; + bool connected; + bool screenshot; }; RemoteDetails* getRemote(); diff --git a/src/override/Engine.cpp b/src/override/Engine.cpp index de59842..ba95f4c 100644 --- a/src/override/Engine.cpp +++ b/src/override/Engine.cpp @@ -1,18 +1,7 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021-2023 Filipe Coelho - * - * 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 + * SPDX-License-Identifier: GPL-3.0-or-later */ /** @@ -295,7 +284,7 @@ static void Engine_stepFrame(Engine* that) { Param* smoothParam = &smoothModule->params[smoothParamId]; float value = smoothParam->value; float newValue; - if (internal->remoteDetails != nullptr) { + if (internal->remoteDetails != nullptr && internal->remoteDetails->connected) { newValue = value; sendParamChangeToRemote(internal->remoteDetails, smoothModule->id, smoothParamId, value); } else { @@ -1094,7 +1083,7 @@ void Engine::setParamValue(Module* module, int paramId, float value) { internal->smoothModule = NULL; internal->smoothParamId = 0; } - if (internal->remoteDetails != nullptr) { + if (internal->remoteDetails != nullptr && internal->remoteDetails->connected) { sendParamChangeToRemote(internal->remoteDetails, module->id, paramId, value); } module->params[paramId].setValue(value); diff --git a/src/override/Scene.cpp b/src/override/Scene.cpp index 07976df..909b498 100644 --- a/src/override/Scene.cpp +++ b/src/override/Scene.cpp @@ -1,18 +1,7 @@ /* * DISTRHO Cardinal Plugin - * Copyright (C) 2021-2023 Filipe Coelho - * - * 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 + * SPDX-License-Identifier: GPL-3.0-or-later */ /** @@ -207,14 +196,19 @@ void Scene::step() { if (remoteUtils::RemoteDetails* const remoteDetails = remoteUtils::getRemote()) { idleRemote(remoteDetails); - if (remoteDetails->autoDeploy) { + if (remoteDetails->autoDeploy && remoteDetails->connected) { const int actionIndex = APP->history->actionIndex; const double time = system::getTime(); if (internal->historyActionIndex == -1) { internal->historyActionIndex = actionIndex; 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); static const std::vector ignoredNames = { "move knob", @@ -224,7 +218,10 @@ void Scene::step() { if (std::find(ignoredNames.cbegin(), ignoredNames.cend(), name) == ignoredNames.cend()) { printf("action '%s'\n", APP->history->actions[actionIndex - 1]->name.c_str()); remoteUtils::sendFullPatchToRemote(remoteDetails); - window::generateScreenshot(); + + if (remoteDetails->screenshot) { + window::generateScreenshot(); + } } internal->historyActionIndex = actionIndex; 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 (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); } diff --git a/src/override/Window.cpp b/src/override/Window.cpp index e1b3bf3..6457d04 100644 --- a/src/override/Window.cpp +++ b/src/override/Window.cpp @@ -1,18 +1,7 @@ /* * DISTRHO Cardinal Plugin * Copyright (C) 2021-2024 Filipe Coelho - * - * 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(context); if (char* const screenshot = String::asBase64(data, size).getAndReleaseBuffer()) { ui->setState("screenshot", screenshot); - if (ui->remoteDetails != nullptr) + if (ui->remoteDetails != nullptr && ui->remoteDetails->connected && ui->remoteDetails->screenshot) remoteUtils::sendScreenshotToRemote(ui->remoteDetails, screenshot); std::free(screenshot); }