diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index e6c6a6fe5..722503863 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -718,26 +718,9 @@ public: /*! * Update the plugin's internal OSC data according to @a source and @a url. * This is used for OSC-GUI bridges. + * TODO remove */ - void updateOscData(const lo_address& source, const char* const url); - - /*! - * Update the plugin's extra OSC data, called from the start of updateOscData(). - * The default implementation does nothing. - */ - virtual bool updateOscDataExtra(); - - /*! - * Update the plugin's OSC URL used in UI bridges. - * This is called when removing or switching plugins. - */ - virtual void updateOscURL(); - - /*! - * Show the plugin's OSC based GUI. - * This is a handy function that waits for the GUI to respond and automatically asks it to show itself. - */ - bool waitForOscGuiShow(); + virtual void updateOscData(const lo_address& source, const char* const url); #ifndef BUILD_BRIDGE // ------------------------------------------------------------------- diff --git a/source/backend/engine/CarlaEngine.cpp b/source/backend/engine/CarlaEngine.cpp index 390734adc..ec260e0db 100644 --- a/source/backend/engine/CarlaEngine.cpp +++ b/source/backend/engine/CarlaEngine.cpp @@ -593,12 +593,14 @@ bool CarlaEngine::removePlugin(const uint id) const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/); const ScopedActionLock sal(pData, kEnginePostActionRemovePlugin, id, 0, lockWait); + /* for (uint i=id; i < pData->curPluginCount; ++i) { CarlaPlugin* const plugin2(pData->plugins[i].plugin); CARLA_SAFE_ASSERT_BREAK(plugin2 != nullptr); plugin2->updateOscURL(); } + */ if (isOscControlRegistered()) oscSend_control_remove_plugin(id); @@ -778,6 +780,7 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept const bool lockWait(isRunning() /*&& pData->options.processMode != ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS*/); const ScopedActionLock sal(pData, kEnginePostActionSwitchPlugins, idA, idB, lockWait); + /* CarlaPlugin* const pluginA(pData->plugins[idA].plugin); CarlaPlugin* const pluginB(pData->plugins[idB].plugin); @@ -786,6 +789,7 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept pluginA->updateOscURL(); pluginB->updateOscURL(); } + */ // TODO //if (isOscControlRegistered()) diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 9b7dd5e96..5444d26dd 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1361,13 +1361,9 @@ void CarlaPlugin::idle() pData->transientTryCounter = 0; } -void CarlaPlugin::showCustomUI(const bool yesNo) +void CarlaPlugin::showCustomUI(const bool) { CARLA_SAFE_ASSERT(false); - return; - - // unused - (void)yesNo; } // ------------------------------------------------------------------- @@ -1586,114 +1582,10 @@ void CarlaPlugin::registerToOscClient() noexcept #endif } -void CarlaPlugin::updateOscData(const lo_address& source, const char* const url) +void CarlaPlugin::updateOscData(const lo_address&, const char* const) { - // FIXME - remove debug prints later - carla_stdout("CarlaPlugin::updateOscData(%p, \"%s\")", source, url); - - pData->oscData.clear(); - - const int proto = lo_address_get_protocol(source); - - { - const char* host = lo_address_get_hostname(source); - const char* port = lo_address_get_port(source); - pData->oscData.source = lo_address_new_with_proto(proto, host, port); - - carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port); - } - - { - char* host = lo_url_get_hostname(url); - char* port = lo_url_get_port(url); - pData->oscData.path = carla_strdup_free(lo_url_get_path(url)); - pData->oscData.target = lo_address_new_with_proto(proto, host, port); - carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, pData->oscData.path); - - std::free(host); - std::free(port); - } - -#ifndef BUILD_BRIDGE - if (pData->hints & PLUGIN_IS_BRIDGE) - { - carla_stdout("CarlaPlugin::updateOscData() - done"); - return; - } -#endif - - // send possible extra data first - if (updateOscDataExtra()) - pData->engine->idleOsc(); - - osc_send_sample_rate(pData->oscData, static_cast(pData->engine->getSampleRate())); - - for (LinkedList::Itenerator it = pData->custom.begin(); it.valid(); it.next()) - { - const CustomData& customData(it.getValue(kCustomDataFallback)); - CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); - - if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0) - osc_send_configure(pData->oscData, customData.key, customData.value); - } - - if (pData->prog.current >= 0) - osc_send_program(pData->oscData, static_cast(pData->prog.current)); - - if (pData->midiprog.current >= 0) - { - const MidiProgramData& curMidiProg(pData->midiprog.getCurrent()); - - if (getType() == PLUGIN_DSSI) - osc_send_program(pData->oscData, curMidiProg.bank, curMidiProg.program); - else - osc_send_midi_program(pData->oscData, curMidiProg.bank, curMidiProg.program); - } - - for (uint32_t i=0; i < pData->param.count; ++i) - osc_send_control(pData->oscData, pData->param.data[i].rindex, getParameterValue(i)); - - if ((pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0 && pData->engine->getOptions().frontendWinId != 0) - pData->transientTryCounter = 1; - - carla_stdout("CarlaPlugin::updateOscData() - done"); -} - -bool CarlaPlugin::updateOscDataExtra() -{ - return false; -} - -void CarlaPlugin::updateOscURL() -{ - const String newURL(String(pData->engine->getOscServerPathUDP()) + String("/") + String(pData->id)); - - osc_send_update_url(pData->oscData, newURL.toRawUTF8()); -} - -bool CarlaPlugin::waitForOscGuiShow() -{ - carla_stdout("CarlaPlugin::waitForOscGuiShow()"); - uint i=0, oscUiTimeout = pData->engine->getOptions().uiBridgesTimeout; - - // wait for UI 'update' call - for (; i < oscUiTimeout/100; ++i) - { - if (pData->oscData.target != nullptr) - { - carla_stdout("CarlaPlugin::waitForOscGuiShow() - got response, asking UI to show itself now"); - osc_send_show(pData->oscData); - return true; - } - - if (pData->childProcess != nullptr && pData->childProcess->isRunning()) - carla_msleep(100); - else - return false; - } - - carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout); - return false; + // should not happen + CARLA_SAFE_ASSERT(false); } // ------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPluginDSSI.cpp b/source/backend/plugin/CarlaPluginDSSI.cpp index 8f7d76e32..942bd3eb0 100644 --- a/source/backend/plugin/CarlaPluginDSSI.cpp +++ b/source/backend/plugin/CarlaPluginDSSI.cpp @@ -30,12 +30,19 @@ using juce::StringArray; CARLA_BACKEND_START_NAMESPACE -// ----------------------------------------------------- +class CarlaPluginDSSI; + +// ------------------------------------------------------------------- +// Fallback data + +static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr }; + +// ------------------------------------------------------------------- class CarlaThreadDSSIUI : public CarlaThread { public: - CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, ScopedPointer& childProcess) noexcept + CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPluginDSSI* const plugin, ScopedPointer& childProcess) noexcept : CarlaThread("CarlaThreadDSSIUI"), kEngine(engine), kPlugin(plugin), @@ -64,113 +71,11 @@ public: return (uintptr_t)fProcess->getPID(); } - void run() - { - if (fProcess == nullptr) - { - fProcess = new ChildProcess(); - } - else if (fProcess->isRunning()) - { - carla_stderr("CarlaThreadDSSI::run() - already running, giving up..."); - - kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); - fProcess->kill(); - fProcess = nullptr; - return; - } - -#if 0 //def CARLA_OS_LINUX - const char* const oldPreload(std::getenv("LD_PRELOAD")); - ::unsetenv("LD_PRELOAD"); - - if (oldPreload != nullptr) - ::setenv("LD_PRELOAD", oldPreload, 1); -#endif - - String name(kPlugin->getName()); - String filename(kPlugin->getFilename()); - - if (name.isEmpty()) - name = "(none)"; - - if (filename.isEmpty()) - filename = "\"\""; - - StringArray arguments; - -#ifndef CARLA_OS_WIN - // start with "wine" if needed - if (fBinary.endsWith(".exe")) - arguments.add("wine"); -#endif - - // binary - arguments.add(fBinary.buffer()); - - // osc-url - arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId())); - - // filename - arguments.add(filename); - - // label - arguments.add(fLabel.buffer()); - - // ui-title - arguments.add(name + String(" (GUI)")); - - carla_stdout("starting DSSI UI..."); - - if (! fProcess->start(arguments)) - { - carla_stdout("failed!"); - fProcess = nullptr; - return; - } - - if (kPlugin->waitForOscGuiShow()) - { - for (; fProcess->isRunning() && ! shouldThreadExit();) - carla_sleep(1); - - // we only get here if UI was closed or thread asked to exit - if (fProcess->isRunning() && shouldThreadExit()) - { - fProcess->waitForProcessToFinish(static_cast(kEngine->getOptions().uiBridgesTimeout)); - - if (fProcess->isRunning()) - { - carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now"); - fProcess->kill(); - } - else - { - carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully"); - } - } - else if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) - carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running"); - else - carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly"); - - kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); - } - else - { - fProcess->kill(); - - carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout"); - kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); - } - - carla_stdout("DSSI UI finished"); - fProcess = nullptr; - } + void run(); private: - CarlaEngine* const kEngine; - CarlaPlugin* const kPlugin; + CarlaEngine* const kEngine; + CarlaPluginDSSI* const kPlugin; CarlaString fBinary; CarlaString fLabel; @@ -2047,19 +1952,6 @@ public: carla_debug("CarlaPluginDSSI::clearBuffers() - end"); } - // ------------------------------------------------------------------- - // OSC stuff - - void updateOscURL() override - { - // DSSI does not support this - if (! fThreadUI.isThreadRunning()) - return; - - showCustomUI(false); - //showCustomUI(true); - } - // ------------------------------------------------------------------- // Post-poned UI Stuff @@ -2141,6 +2033,94 @@ public: // ------------------------------------------------------------------- + void updateOscData(const lo_address& source, const char* const url) override + { + // FIXME - remove debug prints later + carla_stdout("CarlaPluginDSSI::updateOscData(%p, \"%s\")", source, url); + + pData->oscData.clear(); + + const int proto = lo_address_get_protocol(source); + + { + const char* host = lo_address_get_hostname(source); + const char* port = lo_address_get_port(source); + pData->oscData.source = lo_address_new_with_proto(proto, host, port); + + carla_stdout("CarlaPlugin::updateOscData() - source: host \"%s\", port \"%s\"", host, port); + } + + { + char* host = lo_url_get_hostname(url); + char* port = lo_url_get_port(url); + pData->oscData.path = carla_strdup_free(lo_url_get_path(url)); + pData->oscData.target = lo_address_new_with_proto(proto, host, port); + carla_stdout("CarlaPlugin::updateOscData() - target: host \"%s\", port \"%s\", path \"%s\"", host, port, pData->oscData.path); + + std::free(host); + std::free(port); + } + + osc_send_sample_rate(pData->oscData, static_cast(pData->engine->getSampleRate())); + + for (LinkedList::Itenerator it = pData->custom.begin(); it.valid(); it.next()) + { + const CustomData& customData(it.getValue(kCustomDataFallback)); + CARLA_SAFE_ASSERT_CONTINUE(customData.isValid()); + + if (std::strcmp(customData.type, CUSTOM_DATA_TYPE_STRING) == 0) + osc_send_configure(pData->oscData, customData.key, customData.value); + } + + if (pData->prog.current >= 0) + osc_send_program(pData->oscData, static_cast(pData->prog.current)); + + if (pData->midiprog.current >= 0) + { + const MidiProgramData& curMidiProg(pData->midiprog.getCurrent()); + + if (getType() == PLUGIN_DSSI) + osc_send_program(pData->oscData, curMidiProg.bank, curMidiProg.program); + else + osc_send_midi_program(pData->oscData, curMidiProg.bank, curMidiProg.program); + } + + for (uint32_t i=0; i < pData->param.count; ++i) + osc_send_control(pData->oscData, pData->param.data[i].rindex, getParameterValue(i)); + + if ((pData->hints & PLUGIN_HAS_CUSTOM_UI) != 0 && pData->engine->getOptions().frontendWinId != 0) + pData->transientTryCounter = 1; + + carla_stdout("CarlaPluginDSSI::updateOscData() - done"); + } + + bool waitForOscGuiShow() + { + carla_stdout("CarlaPluginDSSI::waitForOscGuiShow()"); + uint i=0, oscUiTimeout = pData->engine->getOptions().uiBridgesTimeout; + + // wait for UI 'update' call + for (; i < oscUiTimeout/100; ++i) + { + if (pData->oscData.target != nullptr) + { + carla_stdout("CarlaPluginDSSI::waitForOscGuiShow() - got response, asking UI to show itself now"); + osc_send_show(pData->oscData); + return true; + } + + if (pData->childProcess != nullptr && pData->childProcess->isRunning()) + carla_msleep(100); + else + return false; + } + + carla_stdout("CarlaPluginDSSI::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout); + return false; + } + + // ------------------------------------------------------------------- + bool init(const char* const filename, const char* const name, const char* const label) { CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); @@ -2481,6 +2461,113 @@ private: LinkedList CarlaPluginDSSI::sMultiSynthList; + +// ------------------------------------------------------------------------------------------------------------------- + +void CarlaThreadDSSIUI::run() +{ + if (fProcess == nullptr) + { + fProcess = new ChildProcess(); + } + else if (fProcess->isRunning()) + { + carla_stderr("CarlaThreadDSSI::run() - already running, giving up..."); + + kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); + fProcess->kill(); + fProcess = nullptr; + return; + } + +#if 0 //def CARLA_OS_LINUX + const char* const oldPreload(std::getenv("LD_PRELOAD")); + ::unsetenv("LD_PRELOAD"); + + if (oldPreload != nullptr) + ::setenv("LD_PRELOAD", oldPreload, 1); +#endif + + String name(kPlugin->getName()); + String filename(kPlugin->getFilename()); + + if (name.isEmpty()) + name = "(none)"; + + if (filename.isEmpty()) + filename = "\"\""; + + StringArray arguments; + +#ifndef CARLA_OS_WIN + // start with "wine" if needed + if (fBinary.endsWith(".exe")) + arguments.add("wine"); +#endif + + // binary + arguments.add(fBinary.buffer()); + + // osc-url + arguments.add(String(kEngine->getOscServerPathUDP()) + String("/") + String(kPlugin->getId())); + + // filename + arguments.add(filename); + + // label + arguments.add(fLabel.buffer()); + + // ui-title + arguments.add(name + String(" (GUI)")); + + carla_stdout("starting DSSI UI..."); + + if (! fProcess->start(arguments)) + { + carla_stdout("failed!"); + fProcess = nullptr; + return; + } + + if (kPlugin->waitForOscGuiShow()) + { + for (; fProcess->isRunning() && ! shouldThreadExit();) + carla_sleep(1); + + // we only get here if UI was closed or thread asked to exit + if (fProcess->isRunning() && shouldThreadExit()) + { + fProcess->waitForProcessToFinish(static_cast(kEngine->getOptions().uiBridgesTimeout)); + + if (fProcess->isRunning()) + { + carla_stdout("CarlaThreadDSSIUI::run() - UI refused to close, force kill now"); + fProcess->kill(); + } + else + { + carla_stdout("CarlaThreadDSSIUI::run() - UI auto-closed successfully"); + } + } + else if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) + carla_stderr("CarlaThreadDSSIUI::run() - UI crashed while running"); + else + carla_stdout("CarlaThreadDSSIUI::run() - UI closed cleanly"); + + kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); + } + else + { + fProcess->kill(); + + carla_stdout("CarlaThreadDSSIUI::run() - GUI timeout"); + kEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, kPlugin->getId(), 0, 0, 0.0f, nullptr); + } + + carla_stdout("DSSI UI finished"); + fProcess = nullptr; +} + // ------------------------------------------------------------------------------------------------------------------- CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init) diff --git a/source/utils/CarlaOscUtils.hpp b/source/utils/CarlaOscUtils.hpp index 6240fac61..8a7230ef0 100644 --- a/source/utils/CarlaOscUtils.hpp +++ b/source/utils/CarlaOscUtils.hpp @@ -224,20 +224,6 @@ void osc_send_update(const CarlaOscData& oscData, const char* const url) noexcep try_lo_send(oscData.target, targetPath, "s", url); } -static inline -void osc_send_update_url(const CarlaOscData& oscData, const char* const url) noexcept -{ - CARLA_SAFE_ASSERT_RETURN(oscData.path != nullptr && oscData.path[0] != '\0',); - CARLA_SAFE_ASSERT_RETURN(oscData.target != nullptr,);; - CARLA_SAFE_ASSERT_RETURN(url != nullptr && url[0] != '\0',); - carla_debug("osc_send_update_url(path:\"%s\", \"%s\")", oscData.path, url); - - char targetPath[std::strlen(oscData.path)+12]; - std::strcpy(targetPath, oscData.path); - std::strcat(targetPath, "/update_url"); - try_lo_send(oscData.target, targetPath, "s", url); -} - static inline void osc_send_show(const CarlaOscData& oscData) noexcept {