diff --git a/source/backend/CarlaPlugin.hpp b/source/backend/CarlaPlugin.hpp index f44f99c52..e6c6a6fe5 100644 --- a/source/backend/CarlaPlugin.hpp +++ b/source/backend/CarlaPlugin.hpp @@ -707,7 +707,6 @@ public: */ virtual void clearBuffers() noexcept; -#ifndef BUILD_BRIDGE // ------------------------------------------------------------------- // OSC stuff @@ -739,7 +738,6 @@ public: * This is a handy function that waits for the GUI to respond and automatically asks it to show itself. */ bool waitForOscGuiShow(); -#endif #ifndef BUILD_BRIDGE // ------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 9366ffabf..9b7dd5e96 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -1435,7 +1435,6 @@ void CarlaPlugin::clearBuffers() noexcept pData->clearBuffers(); } -#ifndef BUILD_BRIDGE // ------------------------------------------------------------------- // OSC stuff @@ -1696,7 +1695,6 @@ bool CarlaPlugin::waitForOscGuiShow() carla_stdout("CarlaPlugin::waitForOscGuiShow() - Timeout while waiting for UI to respond (waited %u msecs)", oscUiTimeout); return false; } -#endif // ------------------------------------------------------------------- // MIDI events diff --git a/source/backend/plugin/CarlaPluginDSSI.cpp b/source/backend/plugin/CarlaPluginDSSI.cpp index d6a25a873..8f7d76e32 100644 --- a/source/backend/plugin/CarlaPluginDSSI.cpp +++ b/source/backend/plugin/CarlaPluginDSSI.cpp @@ -23,10 +23,163 @@ #include "CarlaDssiUtils.hpp" #include "CarlaMathUtils.hpp" +#include "CarlaThread.hpp" + +using juce::String; +using juce::StringArray; CARLA_BACKEND_START_NAMESPACE -#if 0 +// ----------------------------------------------------- + +class CarlaThreadDSSIUI : public CarlaThread +{ +public: + CarlaThreadDSSIUI(CarlaEngine* const engine, CarlaPlugin* const plugin, ScopedPointer& childProcess) noexcept + : CarlaThread("CarlaThreadDSSIUI"), + kEngine(engine), + kPlugin(plugin), + fBinary(), + fLabel(), + fProcess(childProcess), + leakDetector_CarlaThreadDSSIUI() {} + + void setData(const char* const binary, const char* const label) noexcept + { + CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',); + CARLA_SAFE_ASSERT_RETURN(label != nullptr /*&& label[0] != '\0'*/,); + CARLA_SAFE_ASSERT(! isThreadRunning()); + + fBinary = binary; + fLabel = label; + + if (fLabel.isEmpty()) + fLabel = "\"\""; + } + + uintptr_t getPid() const + { + CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0); + + 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; + } + +private: + CarlaEngine* const kEngine; + CarlaPlugin* const kPlugin; + + CarlaString fBinary; + CarlaString fLabel; + + ScopedPointer& fProcess; + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThreadDSSIUI) +}; + // ----------------------------------------------------- class CarlaPluginDSSI : public CarlaPlugin @@ -45,11 +198,10 @@ public: fParamBuffers(nullptr), fLatencyChanged(false), fLatencyIndex(-1), + fThreadUI(engine, this, pData->childProcess), leakDetector_CarlaPluginDSSI() { carla_debug("CarlaPluginDSSI::CarlaPluginDSSI(%p, %i)", engine, id); - - pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_DSSI_GUI); } ~CarlaPluginDSSI() noexcept override @@ -61,7 +213,7 @@ public: { showCustomUI(false); - pData->osc.thread.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); + fThreadUI.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); } pData->singleMutex.lock(); @@ -335,8 +487,8 @@ public: } } - if (sendGui && pData->osc.data.target != nullptr) - osc_send_configure(pData->osc.data, key, value); + if (sendGui && pData->oscData.target != nullptr) + osc_send_configure(pData->oscData, key, value); if (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0) { @@ -410,21 +562,21 @@ public: { if (yesNo) { - pData->osc.data.clear(); - pData->osc.thread.startThread(); + pData->oscData.clear(); + fThreadUI.startThread(); } else { pData->transientTryCounter = 0; - if (pData->osc.data.target != nullptr) + if (pData->oscData.target != nullptr) { - osc_send_hide(pData->osc.data); - osc_send_quit(pData->osc.data); - pData->osc.data.clear(); + osc_send_hide(pData->oscData); + osc_send_quit(pData->oscData); + pData->oscData.clear(); } - pData->osc.thread.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); + fThreadUI.stopThread(static_cast(pData->engine->getOptions().uiBridgesTimeout * 2)); } } @@ -1901,7 +2053,7 @@ public: void updateOscURL() override { // DSSI does not support this - if (! pData->osc.thread.isThreadRunning()) + if (! fThreadUI.isThreadRunning()) return; showCustomUI(false); @@ -1915,20 +2067,20 @@ public: { CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); - if (pData->osc.data.target == nullptr) + if (pData->oscData.target == nullptr) return; - osc_send_control(pData->osc.data, pData->param.data[index].rindex, value); + osc_send_control(pData->oscData, pData->param.data[index].rindex, value); } void uiMidiProgramChange(const uint32_t index) noexcept override { CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); - if (pData->osc.data.target == nullptr) + if (pData->oscData.target == nullptr) return; - osc_send_program(pData->osc.data, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); + osc_send_program(pData->oscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); } void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override @@ -1937,7 +2089,7 @@ public: CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); - if (pData->osc.data.target == nullptr) + if (pData->oscData.target == nullptr) return; #if 0 @@ -1947,7 +2099,7 @@ public: midiData[2] = note; midiData[3] = velo; - osc_send_midi(pData->osc.data, midiData); + osc_send_midi(pData->oscData, midiData); #endif } @@ -1956,7 +2108,7 @@ public: CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); - if (pData->osc.data.target == nullptr) + if (pData->oscData.target == nullptr) return; #if 0 @@ -1966,7 +2118,7 @@ public: midiData[2] = note; midiData[3] = 0; - osc_send_midi(pData->osc.data, midiData); + osc_send_midi(pData->oscData, midiData); #endif } @@ -2154,7 +2306,7 @@ public: if (const char* const guiFilename = find_dssi_ui(filename, fDescriptor->Label)) { - pData->osc.thread.setOscData(guiFilename, fDescriptor->Label); + fThreadUI.setData(guiFilename, fDescriptor->Label); fUiFilename = guiFilename; } @@ -2215,6 +2367,8 @@ private: snd_seq_event_t fMidiEvents[kPluginMaxMidiEvents]; + CarlaThreadDSSIUI fThreadUI; + // ------------------------------------------------------------------- uint32_t getSafePortCount() const noexcept @@ -2326,7 +2480,6 @@ private: }; LinkedList CarlaPluginDSSI::sMultiSynthList; -#endif // ------------------------------------------------------------------------------------------------------------------- @@ -2334,7 +2487,6 @@ CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init) { carla_debug("CarlaPlugin::newDSSI({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.label, init.uniqueId); -#if 0 CarlaPluginDSSI* const plugin(new CarlaPluginDSSI(init.engine, init.id)); if (! plugin->init(init.filename, init.name, init.label)) @@ -2373,9 +2525,6 @@ CarlaPlugin* CarlaPlugin::newDSSI(const Initializer& init) } return plugin; -#endif - return nullptr; - (void)init; } // ------------------------------------------------------------------------------------------------------------------- diff --git a/source/backend/plugin/CarlaPluginInternal.cpp b/source/backend/plugin/CarlaPluginInternal.cpp index 3e90d7ea0..e19b01b56 100644 --- a/source/backend/plugin/CarlaPluginInternal.cpp +++ b/source/backend/plugin/CarlaPluginInternal.cpp @@ -468,10 +468,8 @@ CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx custom(), masterMutex(), singleMutex(), -#ifndef BUILD_BRIDGE childProcess(), oscData(), -#endif stateSave(), extNotes(), postRtEvents(), diff --git a/source/backend/plugin/CarlaPluginInternal.hpp b/source/backend/plugin/CarlaPluginInternal.hpp index c1d77b35d..9ee2f7e51 100644 --- a/source/backend/plugin/CarlaPluginInternal.hpp +++ b/source/backend/plugin/CarlaPluginInternal.hpp @@ -254,10 +254,8 @@ struct CarlaPlugin::ProtectedData { CarlaMutex masterMutex; // global master lock CarlaMutex singleMutex; // small lock used only in processSingle() -#ifndef BUILD_BRIDGE ScopedPointer childProcess; CarlaOscData oscData; -#endif CarlaStateSave stateSave; diff --git a/source/backend/plugin/CarlaPluginLV2.cpp b/source/backend/plugin/CarlaPluginLV2.cpp index a6f3e4199..bb1feb5ae 100644 --- a/source/backend/plugin/CarlaPluginLV2.cpp +++ b/source/backend/plugin/CarlaPluginLV2.cpp @@ -450,8 +450,6 @@ public: #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) # pragma GCC diagnostic pop #endif - - pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_LV2_GUI); } ~CarlaPluginLV2() override diff --git a/source/backend/plugin/CarlaPluginVST2.cpp b/source/backend/plugin/CarlaPluginVST2.cpp index 701a1a44a..d4f8588b6 100644 --- a/source/backend/plugin/CarlaPluginVST2.cpp +++ b/source/backend/plugin/CarlaPluginVST2.cpp @@ -83,8 +83,6 @@ public: for (ushort i=0; i < kPluginMaxMidiEvents*2; ++i) fEvents.data[i] = (VstEvent*)&fMidiEvents[i]; - pData->osc.thread.setMode(CarlaPluginThread::PLUGIN_THREAD_VST2_GUI); - #ifdef CARLA_OS_WIN fProcThread.p = nullptr; fProcThread.x = 0;