diff --git a/source/backend/Makefile b/source/backend/Makefile index 7164daf79..80db29b77 100644 --- a/source/backend/Makefile +++ b/source/backend/Makefile @@ -45,15 +45,13 @@ endif # -------------------------------------------------------------- -STANDALONE_FLAGS = $(LIBLO_LIBS) -STANDALONE_FLAGS += $(QTCORE_LIBS) - -STANDALONE_FLAGS += $(JACKBRIDGE_LIBS) +STANDALONE_FLAGS = $(JACKBRIDGE_LIBS) STANDALONE_FLAGS += $(JUCE_CORE_LIBS) STANDALONE_FLAGS += $(JUCE_AUDIO_BASICS_LIBS) STANDALONE_FLAGS += $(JUCE_AUDIO_DEVICES_LIBS) STANDALONE_FLAGS += $(JUCE_AUDIO_FORMATS_LIBS) STANDALONE_FLAGS += $(JUCE_EVENTS_LIBS) +STANDALONE_FLAGS += $(LIBLO_LIBS) STANDALONE_FLAGS += $(NATIVE_PLUGINS_LIBS) STANDALONE_FLAGS += $(RTAUDIO_LIBS) STANDALONE_FLAGS += $(RTMEMPOOL_LIBS) diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index 9b3d1747a..f4f3ad05d 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -848,9 +848,9 @@ void CarlaPlugin::loadStateSave(const StateSave& stateSave) const uint availOptions(getOptionsAvailable()); - for (int i=0; i<10; ++i) // FIXME - get this value somehow... + for (uint i=0; i<10; ++i) // FIXME - get this value somehow... { - const uint option(1 << i); + const uint option(1u << i); if (availOptions & option) setOption(option, (stateSave.options & option) != 0, true); @@ -941,7 +941,7 @@ void CarlaPlugin::setOption(const uint option, const bool yesNo, const bool send pData->options &= ~option; if (sendCallback) - pData->engine->callback(ENGINE_CALLBACK_OPTION_CHANGED, pData->id, option, yesNo ? 1 : 0, 0.0f, nullptr); + pData->engine->callback(ENGINE_CALLBACK_OPTION_CHANGED, pData->id, static_cast(option), yesNo ? 1 : 0, 0.0f, nullptr); } void CarlaPlugin::setEnabled(const bool yesNo) noexcept diff --git a/source/backend/plugin/CarlaPluginThread.cpp b/source/backend/plugin/CarlaPluginThread.cpp index e53677130..6d11018d0 100644 --- a/source/backend/plugin/CarlaPluginThread.cpp +++ b/source/backend/plugin/CarlaPluginThread.cpp @@ -19,12 +19,15 @@ #include "CarlaPluginThread.hpp" #include "CarlaEngine.hpp" -// FIXME -#include -#include +#include "juce_core.h" + +using juce::String; +using juce::StringArray; CARLA_BACKEND_START_NAMESPACE +// ----------------------------------------------------------------------- + #ifdef DEBUG static inline const char* PluginThreadMode2str(const CarlaPluginThread::Mode mode) noexcept @@ -48,6 +51,8 @@ const char* PluginThreadMode2str(const CarlaPluginThread::Mode mode) noexcept } #endif +// ----------------------------------------------------------------------- + CarlaPluginThread::CarlaPluginThread(CarlaBackend::CarlaEngine* const engine, CarlaBackend::CarlaPlugin* const plugin, const Mode mode) noexcept : CarlaThread("CarlaPluginThread"), fEngine(engine), @@ -64,9 +69,10 @@ CarlaPluginThread::~CarlaPluginThread() noexcept if (fProcess != nullptr) { - try { - delete fProcess; - } CARLA_SAFE_EXCEPTION("~CarlaPluginThread(): delete QProcess"); + //fProcess.release(); + //try { + //delete fProcess; + //} CARLA_SAFE_EXCEPTION("~CarlaPluginThread(): delete ChildProcess"); fProcess = nullptr; } } @@ -94,7 +100,8 @@ uintptr_t CarlaPluginThread::getPid() const { CARLA_SAFE_ASSERT_RETURN(fProcess != nullptr, 0); - return (uintptr_t)fProcess->pid(); + return 0; + //return (uintptr_t)fProcess->pid(); } void CarlaPluginThread::run() @@ -103,10 +110,10 @@ void CarlaPluginThread::run() if (fProcess == nullptr) { - fProcess = new QProcess(nullptr); - fProcess->setProcessChannelMode(QProcess::ForwardedChannels); + fProcess = new ChildProcess; + //fProcess->setProcessChannelMode(QProcess::ForwardedChannels); } - else if (fProcess->state() == QProcess::Running) + else if (fProcess->isRunning()) { carla_stderr("CarlaPluginThread::run() - already running, giving up..."); @@ -119,7 +126,8 @@ void CarlaPluginThread::run() case PLUGIN_THREAD_LV2_GUI: case PLUGIN_THREAD_VST_GUI: fEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, fPlugin->getId(), 0, 0, 0.0f, nullptr); - fProcess->terminate(); + fProcess->kill(); + fProcess = nullptr; return; case PLUGIN_THREAD_BRIDGE: @@ -127,41 +135,19 @@ void CarlaPluginThread::run() } } - QString name(fPlugin->getName()); + String name(fPlugin->getName()); if (name.isEmpty()) name = "(none)"; - QStringList arguments; - QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); - const EngineOptions& options(fEngine->getOptions()); - - char strBuf[STR_MAX+1]; - env.insert("ENGINE_OPTION_UIS_ALWAYS_ON_TOP", options.uisAlwaysOnTop ? "true" : "false"); - - if (options.maxParameters != 0) - { - std::sprintf(strBuf, "%u", options.maxParameters); - env.insert("ENGINE_OPTION_MAX_PARAMETERS", strBuf); - } - - if (options.uiBridgesTimeout != 0) - { - std::sprintf(strBuf, "%u", options.uiBridgesTimeout); - env.insert("ENGINE_OPTION_UI_BRIDGES_TIMEOUT", strBuf); - } - - if (options.frontendWinId != 0) - { - std::sprintf(strBuf, P_UINTPTR, options.frontendWinId); - env.insert("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf); - } + StringArray arguments; - if (options.binaryDir != nullptr) - env.insert("ENGINE_OPTION_PATH_BINARIES", options.binaryDir); +#ifndef CARLA_OS_WIN + if (fBinary.endsWith(".exe")) + arguments.add("wine"); +#endif - if (options.resourceDir != nullptr) - env.insert("ENGINE_OPTION_PATH_RESOURCES", options.resourceDir); + arguments.add(fBinary.buffer()); switch (fMode) { @@ -169,54 +155,45 @@ void CarlaPluginThread::run() break; case PLUGIN_THREAD_DSSI_GUI: - /* osc-url */ arguments << QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId()); - /* filename */ arguments << fPlugin->getFilename(); - /* label */ arguments << fLabel.buffer(); - /* ui-title */ arguments << QString("%1 (GUI)").arg(fPlugin->getName()); + /* osc-url */ arguments.add(String(fEngine->getOscServerPathUDP()) + String("/") + String(fPlugin->getId())); + /* filename */ arguments.add(fPlugin->getFilename()); + /* label */ arguments.add(fLabel.buffer()); + /* ui-title */ arguments.add(name + String(" (GUI)")); break; case PLUGIN_THREAD_LV2_GUI: - /* osc-url */ arguments << QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId()); - /* URI */ arguments << fLabel.buffer(); - /* ui-URI */ arguments << fExtra1.buffer(); - /* ui-title */ arguments << QString("%1 (GUI)").arg(fPlugin->getName()); + /* osc-url */ arguments.add(String(fEngine->getOscServerPathUDP()) + String("/") + String(fPlugin->getId())); + /* URI */ arguments.add(fLabel.buffer()); + /* ui-URI */ arguments.add(fExtra1.buffer()); + /* ui-title */ arguments.add(name + String(" (GUI)")); break; case PLUGIN_THREAD_VST_GUI: - /* osc-url */ arguments << QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId()); - /* filename */ arguments << fPlugin->getFilename(); - /* ui-title */ arguments << QString("%1 (GUI)").arg(fPlugin->getName()); + /* osc-url */ arguments.add(String(fEngine->getOscServerPathUDP()) + String("/") + String(fPlugin->getId())); + /* filename */ arguments.add(fPlugin->getFilename()); + /* ui-title */ arguments.add(name + String(" (GUI)")); break; case PLUGIN_THREAD_BRIDGE: - env.insert("ENGINE_BRIDGE_SHM_IDS", fExtra2.buffer()); - env.insert("ENGINE_BRIDGE_CLIENT_NAME", name); - env.insert("ENGINE_BRIDGE_OSC_URL", QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId())); - -#ifndef CARLA_OS_WIN - if (fBinary.endsWith(".exe")) - { - env.insert("WINEDEBUG", "-all"); - arguments << fBinary.buffer(); - fBinary = "wine"; - } -#endif - /* osc-url */ arguments << QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId()); - /* stype */ arguments << fExtra1.buffer(); - /* filename */ arguments << fPlugin->getFilename(); - /* name */ arguments << name; - /* label */ arguments << fLabel.buffer(); - /* uniqueId */ arguments << QString("%1").arg(fPlugin->getUniqueId()); + //env.insert("ENGINE_BRIDGE_SHM_IDS", fExtra2.buffer()); + //env.insert("ENGINE_BRIDGE_CLIENT_NAME", name); + //env.insert("ENGINE_BRIDGE_OSC_URL", QString("%1/%2").arg(fEngine->getOscServerPathUDP()).arg(fPlugin->getId())); + //env.insert("WINEDEBUG", "-all"); + + /* osc-url */ arguments.add(String(fEngine->getOscServerPathUDP()) + String("/") + String(fPlugin->getId())); + /* stype */ arguments.add(fExtra1.buffer()); + /* filename */ arguments.add(fPlugin->getFilename()); + /* name */ arguments.add(name); + /* label */ arguments.add(fLabel.buffer()); + /* uniqueId */ arguments.add(String(static_cast(fPlugin->getUniqueId()))); break; } - fProcess->setProcessEnvironment(env); - carla_stdout("starting app.."); - qWarning() << arguments; + //qWarning() << arguments; - fProcess->start(fBinary.buffer(), arguments); - fProcess->waitForStarted(); + fProcess->start(arguments); + //fProcess->waitForStarted(); switch (fMode) { @@ -228,18 +205,15 @@ void CarlaPluginThread::run() case PLUGIN_THREAD_VST_GUI: if (fPlugin->waitForOscGuiShow()) { - //fProcess->waitForFinished(-1); - - while (fProcess->state() != QProcess::NotRunning && ! shouldThreadExit()) + while (fProcess->isRunning() && ! shouldThreadExit()) carla_sleep(1); // we only get here if UI was closed or thread asked to exit - - if (fProcess->state() != QProcess::NotRunning && shouldThreadExit()) + if (fProcess->isRunning() && shouldThreadExit()) { - fProcess->waitForFinished(static_cast(fEngine->getOptions().uiBridgesTimeout)); + //fProcess->waitForFinished(static_cast(fEngine->getOptions().uiBridgesTimeout)); - if (fProcess->state() == QProcess::Running) + if (fProcess->isRunning()) { carla_stdout("CarlaPluginThread::run() - UI refused to close, force kill now"); fProcess->kill(); @@ -249,7 +223,7 @@ void CarlaPluginThread::run() carla_stdout("CarlaPluginThread::run() - UI auto-closed successfully"); } } - else if (fProcess->exitCode() != 0 || fProcess->exitStatus() == QProcess::CrashExit) + else if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) carla_stderr("CarlaPluginThread::run() - UI crashed while running"); else carla_stdout("CarlaPluginThread::run() - UI closed cleanly"); @@ -258,14 +232,9 @@ void CarlaPluginThread::run() } else { - fProcess->close(); - CARLA_SAFE_ASSERT(fProcess->state() == QProcess::NotRunning); - - if (fProcess->exitCode() != 0 || fProcess->exitStatus() == QProcess::CrashExit) - carla_stderr("CarlaPluginThread::run() - GUI crashed while opening"); - else - carla_stdout("CarlaPluginThread::run() - GUI timeout"); + fProcess->kill(); + carla_stdout("CarlaPluginThread::run() - GUI timeout"); fEngine->callback(CarlaBackend::ENGINE_CALLBACK_UI_STATE_CHANGED, fPlugin->getId(), 0, 0, 0.0f, nullptr); } break; @@ -273,22 +242,21 @@ void CarlaPluginThread::run() case PLUGIN_THREAD_BRIDGE: //fProcess->waitForFinished(-1); - while (fProcess->state() != QProcess::NotRunning && ! shouldThreadExit()) + while (fProcess->isRunning() && ! shouldThreadExit()) carla_sleep(1); // we only get here if bridge crashed or thread asked to exit - if (shouldThreadExit()) { - fProcess->waitForFinished(500); + fProcess->getExitCode(); // TEST - if (fProcess->state() == QProcess::Running) - fProcess->close(); + if (fProcess->isRunning()) + fProcess->kill(); } else { // forced quit, may have crashed - if (fProcess->exitCode() != 0 || fProcess->exitStatus() == QProcess::CrashExit) + if (fProcess->getExitCode() != 0 /*|| fProcess->exitStatus() == QProcess::CrashExit*/) { carla_stderr("CarlaPluginThread::run() - bridge crashed"); @@ -302,6 +270,45 @@ void CarlaPluginThread::run() } carla_stdout("app finished"); + fProcess = nullptr; } +// ----------------------------------------------------------------------- + +#if 0 + QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); + const EngineOptions& options(fEngine->getOptions()); + + char strBuf[STR_MAX+1]; + env.insert("ENGINE_OPTION_UIS_ALWAYS_ON_TOP", options.uisAlwaysOnTop ? "true" : "false"); + + if (options.maxParameters != 0) + { + std::sprintf(strBuf, "%u", options.maxParameters); + env.insert("ENGINE_OPTION_MAX_PARAMETERS", strBuf); + } + + if (options.uiBridgesTimeout != 0) + { + std::sprintf(strBuf, "%u", options.uiBridgesTimeout); + env.insert("ENGINE_OPTION_UI_BRIDGES_TIMEOUT", strBuf); + } + + if (options.frontendWinId != 0) + { + std::sprintf(strBuf, P_UINTPTR, options.frontendWinId); + env.insert("ENGINE_OPTION_FRONTEND_WIN_ID", strBuf); + } + + if (options.binaryDir != nullptr) + env.insert("ENGINE_OPTION_PATH_BINARIES", options.binaryDir); + + if (options.resourceDir != nullptr) + env.insert("ENGINE_OPTION_PATH_RESOURCES", options.resourceDir); + + fProcess->setProcessEnvironment(env); +#endif + +// ----------------------------------------------------------------------- + CARLA_BACKEND_END_NAMESPACE diff --git a/source/backend/plugin/CarlaPluginThread.hpp b/source/backend/plugin/CarlaPluginThread.hpp index ff074d9fb..cb3c13186 100644 --- a/source/backend/plugin/CarlaPluginThread.hpp +++ b/source/backend/plugin/CarlaPluginThread.hpp @@ -19,15 +19,15 @@ #define CARLA_PLUGIN_THREAD_HPP_INCLUDED #include "CarlaBackend.h" +#include "CarlaJuceUtils.hpp" #include "CarlaThread.hpp" -class QProcess; +#include "juce_core.h" -CARLA_BACKEND_START_NAMESPACE +using juce::ChildProcess; +using juce::ScopedPointer; -#if 0 -} // Fix editor indentation -#endif +CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- @@ -62,7 +62,8 @@ private: CarlaString fLabel; CarlaString fExtra1; CarlaString fExtra2; - QProcess* fProcess; + + ScopedPointer fProcess; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginThread) }; diff --git a/source/backend/plugin/Makefile b/source/backend/plugin/Makefile index 39d202c8e..66acb40a0 100644 --- a/source/backend/plugin/Makefile +++ b/source/backend/plugin/Makefile @@ -56,7 +56,7 @@ CarlaPluginInternal.cpp.o: CarlaPluginInternal.cpp $(CARLA_PLUGIN_INTERNAL_CPP_D $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ CarlaPluginThread.cpp.o: CarlaPluginThread.cpp $(CARLA_PLUGIN_THREAD_CPP_DEPS) - $(CXX) $< $(BUILD_CXX_FLAGS) $(QTCORE_FLAGS) -c -o $@ + $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ CarlaPluginUi.cpp.o: CarlaPluginUi.cpp $(CARLA_PLUGIN_UI_CPP_DEPS) $(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@