Signed-off-by: falkTX <falktx@falktx.com>tags/v2.5.0
@@ -1311,13 +1311,13 @@ protected: | |||||
*/ | */ | ||||
friend class CarlaEngineEventPort; | friend class CarlaEngineEventPort; | ||||
friend class CarlaEngineOsc; | friend class CarlaEngineOsc; | ||||
friend class CarlaEngineThread; | |||||
friend class CarlaEngineRunner; | |||||
friend class CarlaPluginInstance; | friend class CarlaPluginInstance; | ||||
friend class EngineInternalGraph; | friend class EngineInternalGraph; | ||||
friend class PendingRtEventsRunner; | friend class PendingRtEventsRunner; | ||||
friend class ScopedActionLock; | friend class ScopedActionLock; | ||||
friend class ScopedEngineEnvironmentLocker; | friend class ScopedEngineEnvironmentLocker; | ||||
friend class ScopedThreadStopper; | |||||
friend class ScopedRunnerStopper; | |||||
friend class PatchbayGraph; | friend class PatchbayGraph; | ||||
friend struct ExternalGraph; | friend struct ExternalGraph; | ||||
friend struct RackGraph; | friend struct RackGraph; | ||||
@@ -854,7 +854,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, | |||||
{ | { | ||||
CARLA_SAFE_ASSERT(! pData->loadingProject); | CARLA_SAFE_ASSERT(! pData->loadingProject); | ||||
const ScopedThreadStopper sts(this); | |||||
const ScopedRunnerStopper srs(this); | |||||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | ||||
pData->graph.replacePlugin(oldPlugin, plugin); | pData->graph.replacePlugin(oldPlugin, plugin); | ||||
@@ -925,7 +925,7 @@ bool CarlaEngine::removePlugin(const uint id) | |||||
CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to remove"); | CARLA_SAFE_ASSERT_RETURN_ERR(plugin.get() != nullptr, "Could not find plugin to remove"); | ||||
CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); | CARLA_SAFE_ASSERT_RETURN_ERR(plugin->getId() == id, "Invalid engine internal data"); | ||||
const ScopedThreadStopper sts(this); | |||||
const ScopedRunnerStopper srs(this); | |||||
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH | ||||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | ||||
@@ -967,7 +967,7 @@ bool CarlaEngine::removeAllPlugins() | |||||
if (pData->curPluginCount == 0) | if (pData->curPluginCount == 0) | ||||
return true; | return true; | ||||
const ScopedThreadStopper sts(this); | |||||
const ScopedRunnerStopper srs(this); | |||||
const uint curPluginCount = pData->curPluginCount; | const uint curPluginCount = pData->curPluginCount; | ||||
@@ -1112,7 +1112,7 @@ bool CarlaEngine::switchPlugins(const uint idA, const uint idB) noexcept | |||||
CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); | CARLA_SAFE_ASSERT_RETURN_ERR(pluginA->getId() == idA, "Invalid engine internal data"); | ||||
CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); | CARLA_SAFE_ASSERT_RETURN_ERR(pluginB->getId() == idB, "Invalid engine internal data"); | ||||
const ScopedThreadStopper sts(this); | |||||
const ScopedRunnerStopper srs(this); | |||||
if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | ||||
pData->graph.switchPlugins(pluginA, pluginB); | pData->graph.switchPlugins(pluginA, pluginB); | ||||
@@ -377,7 +377,7 @@ EngineEvent* CarlaEngine::getInternalEventBuffer(const bool isInput) const noexc | |||||
// CarlaEngine::ProtectedData | // CarlaEngine::ProtectedData | ||||
CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) | CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) | ||||
: thread(engine), | |||||
: runner(engine), | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | ||||
osc(engine), | osc(engine), | ||||
#endif | #endif | ||||
@@ -511,7 +511,7 @@ bool CarlaEngine::ProtectedData::init(const char* const clientName) | |||||
#endif | #endif | ||||
nextAction.clearAndReset(); | nextAction.clearAndReset(); | ||||
thread.startThread(); | |||||
runner.start(); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -526,7 +526,7 @@ void CarlaEngine::ProtectedData::close() | |||||
aboutToClose = true; | aboutToClose = true; | ||||
thread.stopThread(500); | |||||
runner.stop(); | |||||
nextAction.clearAndReset(); | nextAction.clearAndReset(); | ||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | ||||
@@ -840,19 +840,19 @@ ScopedActionLock::~ScopedActionLock() noexcept | |||||
} | } | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// ScopedThreadStopper | |||||
// ScopedRunnerStopper | |||||
ScopedThreadStopper::ScopedThreadStopper(CarlaEngine* const e) noexcept | |||||
ScopedRunnerStopper::ScopedRunnerStopper(CarlaEngine* const e) noexcept | |||||
: engine(e), | : engine(e), | ||||
pData(e->pData) | pData(e->pData) | ||||
{ | { | ||||
pData->thread.stopThread(500); | |||||
pData->runner.stop(); | |||||
} | } | ||||
ScopedThreadStopper::~ScopedThreadStopper() noexcept | |||||
ScopedRunnerStopper::~ScopedRunnerStopper() noexcept | |||||
{ | { | ||||
if (engine->isRunning() && ! pData->aboutToClose) | if (engine->isRunning() && ! pData->aboutToClose) | ||||
pData->thread.startThread(); | |||||
pData->runner.start(); | |||||
} | } | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -18,7 +18,7 @@ | |||||
#ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED | #ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED | ||||
#define CARLA_ENGINE_INTERNAL_HPP_INCLUDED | #define CARLA_ENGINE_INTERNAL_HPP_INCLUDED | ||||
#include "CarlaEngineThread.hpp" | |||||
#include "CarlaEngineRunner.hpp" | |||||
#include "CarlaEngineUtils.hpp" | #include "CarlaEngineUtils.hpp" | ||||
#include "CarlaPlugin.hpp" | #include "CarlaPlugin.hpp" | ||||
#include "LinkedList.hpp" | #include "LinkedList.hpp" | ||||
@@ -244,7 +244,7 @@ struct EnginePluginData { | |||||
// CarlaEngineProtectedData | // CarlaEngineProtectedData | ||||
struct CarlaEngine::ProtectedData { | struct CarlaEngine::ProtectedData { | ||||
CarlaEngineThread thread; | |||||
CarlaEngineRunner runner; | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | ||||
CarlaEngineOsc osc; | CarlaEngineOsc osc; | ||||
@@ -268,7 +268,7 @@ struct CarlaEngine::ProtectedData { | |||||
uint32_t bufferSize; | uint32_t bufferSize; | ||||
double sampleRate; | double sampleRate; | ||||
bool aboutToClose; // don't re-activate thread if true | |||||
bool aboutToClose; // don't re-activate runner if true | |||||
int isIdling; // don't allow any operations while idling | int isIdling; // don't allow any operations while idling | ||||
uint curPluginCount; // number of plugins loaded (0...max) | uint curPluginCount; // number of plugins loaded (0...max) | ||||
uint maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255) | uint maxPluginNumber; // number of plugins allowed (0, 16, 99 or 255) | ||||
@@ -362,18 +362,18 @@ private: | |||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
class ScopedThreadStopper | |||||
class ScopedRunnerStopper | |||||
{ | { | ||||
public: | public: | ||||
ScopedThreadStopper(CarlaEngine* engine) noexcept; | |||||
~ScopedThreadStopper() noexcept; | |||||
ScopedRunnerStopper(CarlaEngine* engine) noexcept; | |||||
~ScopedRunnerStopper() noexcept; | |||||
private: | private: | ||||
CarlaEngine* const engine; | CarlaEngine* const engine; | ||||
CarlaEngine::ProtectedData* const pData; | CarlaEngine::ProtectedData* const pData; | ||||
CARLA_PREVENT_HEAP_ALLOCATION | CARLA_PREVENT_HEAP_ALLOCATION | ||||
CARLA_DECLARE_NON_COPYABLE(ScopedThreadStopper) | |||||
CARLA_DECLARE_NON_COPYABLE(ScopedRunnerStopper) | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
@@ -1520,8 +1520,8 @@ protected: | |||||
} | } | ||||
// stopped during removeAllPlugins() | // stopped during removeAllPlugins() | ||||
if (! pData->thread.isThreadRunning()) | |||||
pData->thread.startThread(); | |||||
if (! pData->runner.isRunnerActive()) | |||||
pData->runner.start(); | |||||
fOptionsForced = true; | fOptionsForced = true; | ||||
const String state(data); | const String state(data); | ||||
@@ -0,0 +1,170 @@ | |||||
/* | |||||
* Carla Plugin Host | |||||
* Copyright (C) 2011-2022 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 2 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 doc/GPL.txt file. | |||||
*/ | |||||
#include "CarlaEngineRunner.hpp" | |||||
#include "CarlaEngineInternal.hpp" | |||||
#include "CarlaPlugin.hpp" | |||||
#include "water/misc/Time.h" | |||||
CARLA_BACKEND_START_NAMESPACE | |||||
// ----------------------------------------------------------------------- | |||||
CarlaEngineRunner::CarlaEngineRunner(CarlaEngine* const engine) noexcept | |||||
: CarlaRunner("CarlaEngineRunner"), | |||||
kEngine(engine), | |||||
fIsAlwaysRunning(false), | |||||
fIsPlugin(false) | |||||
{ | |||||
CARLA_SAFE_ASSERT(engine != nullptr); | |||||
carla_debug("CarlaEngineRunner::CarlaEngineRunner(%p)", engine); | |||||
} | |||||
CarlaEngineRunner::~CarlaEngineRunner() noexcept | |||||
{ | |||||
carla_debug("CarlaEngineRunner::~CarlaEngineRunner()"); | |||||
} | |||||
void CarlaEngineRunner::start() | |||||
{ | |||||
carla_debug("CarlaEngineRunner::start()"); | |||||
if (isRunnerActive()) | |||||
stopRunner(); | |||||
fIsPlugin = kEngine->getType() == kEngineTypePlugin; | |||||
fIsAlwaysRunning = kEngine->getType() == kEngineTypeBridge || fIsPlugin; | |||||
startRunner(25); | |||||
} | |||||
void CarlaEngineRunner::stop() | |||||
{ | |||||
carla_debug("CarlaEngineRunner::stop()"); | |||||
stopRunner(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
bool CarlaEngineRunner::run() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(kEngine != nullptr, false); | |||||
float value; | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// int64_t lastPingTime = 0; | |||||
const CarlaEngineOsc& engineOsc(kEngine->pData->osc); | |||||
#endif | |||||
// runner must do something... | |||||
CARLA_SAFE_ASSERT_RETURN(fIsAlwaysRunning || kEngine->isRunning(), false); | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
const bool oscRegistedForUDP = engineOsc.isControlRegisteredForUDP(); | |||||
#else | |||||
const bool oscRegistedForUDP = false; | |||||
#endif | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||||
if (kIsPlugin) | |||||
engineOsc.idle(); | |||||
#endif | |||||
for (uint i=0, count = kEngine->getCurrentPluginCount(); i < count; ++i) | |||||
{ | |||||
const CarlaPluginPtr plugin = kEngine->getPluginUnchecked(i); | |||||
CARLA_SAFE_ASSERT_CONTINUE(plugin.get() != nullptr && plugin->isEnabled()); | |||||
CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId()); | |||||
const uint hints = plugin->getHints(); | |||||
const bool updateUI = (hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) == 0; | |||||
// ----------------------------------------------------------- | |||||
// DSP Idle | |||||
try { | |||||
plugin->idle(); | |||||
} CARLA_SAFE_EXCEPTION("idle()") | |||||
// ----------------------------------------------------------- | |||||
// Post-poned events | |||||
if (oscRegistedForUDP || updateUI) | |||||
{ | |||||
// ------------------------------------------------------- | |||||
// Update parameter outputs | |||||
for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j) | |||||
{ | |||||
if (! plugin->isParameterOutput(j)) | |||||
continue; | |||||
value = plugin->getParameterValue(j); | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// Update OSC engine client | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendParameterValue(i, j, value); | |||||
#endif | |||||
// Update UI | |||||
if (updateUI) | |||||
plugin->uiParameterChange(j, value); | |||||
} | |||||
if (updateUI) | |||||
{ | |||||
try { | |||||
plugin->uiIdle(); | |||||
} CARLA_SAFE_EXCEPTION("uiIdle()") | |||||
} | |||||
} | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// ----------------------------------------------------------- | |||||
// Update OSC control client peaks | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendPeaks(i, kEngine->getPeaks(i)); | |||||
#endif | |||||
} | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendRuntimeInfo(); | |||||
/* | |||||
if (engineOsc.isControlRegisteredForTCP()) | |||||
{ | |||||
const int64_t timeNow = water::Time::currentTimeMillis(); | |||||
if (timeNow - lastPingTime > 1000) | |||||
{ | |||||
engineOsc.sendPing(); | |||||
lastPingTime = timeNow; | |||||
} | |||||
} | |||||
*/ | |||||
#endif | |||||
return true; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -1,6 +1,6 @@ | |||||
/* | /* | ||||
* Carla Plugin Host | * Carla Plugin Host | ||||
* Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com> | |||||
* Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com> | |||||
* | * | ||||
* This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
* modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
@@ -19,28 +19,34 @@ | |||||
#define CARLA_ENGINE_THREAD_HPP_INCLUDED | #define CARLA_ENGINE_THREAD_HPP_INCLUDED | ||||
#include "CarlaBackend.h" | #include "CarlaBackend.h" | ||||
#include "CarlaThread.hpp" | |||||
#include "CarlaRunner.hpp" | |||||
#include "CarlaJuceUtils.hpp" | #include "CarlaJuceUtils.hpp" | ||||
CARLA_BACKEND_START_NAMESPACE | CARLA_BACKEND_START_NAMESPACE | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
// CarlaEngineThread | |||||
// CarlaEngineRunner | |||||
class CarlaEngineThread : public CarlaThread | |||||
class CarlaEngineRunner : public CarlaRunner | |||||
{ | { | ||||
public: | public: | ||||
CarlaEngineThread(CarlaEngine* engine) noexcept; | |||||
~CarlaEngineThread() noexcept override; | |||||
CarlaEngineRunner(CarlaEngine* engine) noexcept; | |||||
~CarlaEngineRunner() noexcept override; | |||||
void start(); | |||||
void stop(); | |||||
protected: | protected: | ||||
void run() noexcept override; | |||||
bool run() noexcept override; | |||||
private: | private: | ||||
CarlaEngine* const kEngine; | CarlaEngine* const kEngine; | ||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineThread) | |||||
bool fIsAlwaysRunning; | |||||
bool fIsPlugin; | |||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRunner) | |||||
}; | }; | ||||
// ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- |
@@ -1,159 +0,0 @@ | |||||
/* | |||||
* Carla Plugin Host | |||||
* Copyright (C) 2011-2020 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 2 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 doc/GPL.txt file. | |||||
*/ | |||||
#include "CarlaEngineThread.hpp" | |||||
#include "CarlaEngineInternal.hpp" | |||||
#include "CarlaPlugin.hpp" | |||||
#include "water/misc/Time.h" | |||||
CARLA_BACKEND_START_NAMESPACE | |||||
// ----------------------------------------------------------------------- | |||||
CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine) noexcept | |||||
: CarlaThread("CarlaEngineThread"), | |||||
kEngine(engine) | |||||
{ | |||||
CARLA_SAFE_ASSERT(engine != nullptr); | |||||
carla_debug("CarlaEngineThread::CarlaEngineThread(%p)", engine); | |||||
} | |||||
CarlaEngineThread::~CarlaEngineThread() noexcept | |||||
{ | |||||
carla_debug("CarlaEngineThread::~CarlaEngineThread()"); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
void CarlaEngineThread::run() noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(kEngine != nullptr,); | |||||
carla_debug("CarlaEngineThread::run()"); | |||||
const bool kIsPlugin = kEngine->getType() == kEngineTypePlugin; | |||||
const bool kIsAlwaysRunning = kEngine->getType() == kEngineTypeBridge || kIsPlugin; | |||||
float value; | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// int64_t lastPingTime = 0; | |||||
const CarlaEngineOsc& engineOsc(kEngine->pData->osc); | |||||
#endif | |||||
// thread must do something... | |||||
CARLA_SAFE_ASSERT_RETURN(kIsAlwaysRunning || kEngine->isRunning(),); | |||||
for (; (kIsAlwaysRunning || kEngine->isRunning()) && ! shouldThreadExit();) | |||||
{ | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
const bool oscRegistedForUDP = engineOsc.isControlRegisteredForUDP(); | |||||
#else | |||||
const bool oscRegistedForUDP = false; | |||||
#endif | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||||
if (kIsPlugin) | |||||
engineOsc.idle(); | |||||
#endif | |||||
for (uint i=0, count = kEngine->getCurrentPluginCount(); i < count; ++i) | |||||
{ | |||||
const CarlaPluginPtr plugin = kEngine->getPluginUnchecked(i); | |||||
CARLA_SAFE_ASSERT_CONTINUE(plugin.get() != nullptr && plugin->isEnabled()); | |||||
CARLA_SAFE_ASSERT_UINT2(i == plugin->getId(), i, plugin->getId()); | |||||
const uint hints(plugin->getHints()); | |||||
const bool updateUI((hints & PLUGIN_HAS_CUSTOM_UI) != 0 && (hints & PLUGIN_NEEDS_UI_MAIN_THREAD) == 0); | |||||
// ----------------------------------------------------------- | |||||
// DSP Idle | |||||
try { | |||||
plugin->idle(); | |||||
} CARLA_SAFE_EXCEPTION("idle()") | |||||
// ----------------------------------------------------------- | |||||
// Post-poned events | |||||
if (oscRegistedForUDP || updateUI) | |||||
{ | |||||
// ------------------------------------------------------- | |||||
// Update parameter outputs | |||||
for (uint32_t j=0, pcount=plugin->getParameterCount(); j < pcount; ++j) | |||||
{ | |||||
if (! plugin->isParameterOutput(j)) | |||||
continue; | |||||
value = plugin->getParameterValue(j); | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// Update OSC engine client | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendParameterValue(i, j, value); | |||||
#endif | |||||
// Update UI | |||||
if (updateUI) | |||||
plugin->uiParameterChange(j, value); | |||||
} | |||||
if (updateUI) | |||||
{ | |||||
try { | |||||
plugin->uiIdle(); | |||||
} CARLA_SAFE_EXCEPTION("uiIdle()") | |||||
} | |||||
} | |||||
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||||
// ----------------------------------------------------------- | |||||
// Update OSC control client peaks | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendPeaks(i, kEngine->getPeaks(i)); | |||||
#endif | |||||
} | |||||
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE) | |||||
if (oscRegistedForUDP) | |||||
engineOsc.sendRuntimeInfo(); | |||||
/* | |||||
if (engineOsc.isControlRegisteredForTCP()) | |||||
{ | |||||
const int64_t timeNow = water::Time::currentTimeMillis(); | |||||
if (timeNow - lastPingTime > 1000) | |||||
{ | |||||
engineOsc.sendPing(); | |||||
lastPingTime = timeNow; | |||||
} | |||||
} | |||||
*/ | |||||
#endif | |||||
carla_msleep(25); | |||||
} | |||||
carla_debug("CarlaEngineThread closed"); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
CARLA_BACKEND_END_NAMESPACE |
@@ -38,7 +38,7 @@ OBJS = \ | |||||
$(OBJDIR)/CarlaEngineGraph.cpp.o \ | $(OBJDIR)/CarlaEngineGraph.cpp.o \ | ||||
$(OBJDIR)/CarlaEngineInternal.cpp.o \ | $(OBJDIR)/CarlaEngineInternal.cpp.o \ | ||||
$(OBJDIR)/CarlaEnginePorts.cpp.o \ | $(OBJDIR)/CarlaEnginePorts.cpp.o \ | ||||
$(OBJDIR)/CarlaEngineThread.cpp.o | |||||
$(OBJDIR)/CarlaEngineRunner.cpp.o | |||||
ifeq ($(HAVE_LIBLO),true) | ifeq ($(HAVE_LIBLO),true) | ||||
OBJS += \ | OBJS += \ | ||||
@@ -0,0 +1,227 @@ | |||||
/* | |||||
* Carla Runner | |||||
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
#ifndef CARLA_RUNNER_HPP_INCLUDED | |||||
#define CARLA_RUNNER_HPP_INCLUDED | |||||
#include "CarlaUtils.hpp" | |||||
#ifndef CARLA_OS_WASM | |||||
# include "CarlaThread.hpp" | |||||
#else | |||||
# include "CarlaString.hpp" | |||||
# include <emscripten/emscripten.h> | |||||
#endif | |||||
// ------------------------------------------------------------------------------------------------------------------- | |||||
// CarlaRunner class | |||||
/** | |||||
This is a handy class that handles "idle" time in either background or main thread, | |||||
whichever is more suitable to the target platform. | |||||
Typically background threads on desktop platforms, main thread on web. | |||||
A single function is expected to be implemented by subclasses, | |||||
which directly allows it to stop the runner by returning false. | |||||
You can use it for quick operations that do not need to be handled in the main thread if possible. | |||||
The target is to spread out execution over many runs, instead of spending a lot of time on a single task. | |||||
*/ | |||||
class CarlaRunner | |||||
{ | |||||
protected: | |||||
/* | |||||
* Constructor. | |||||
*/ | |||||
CarlaRunner(const char* const runnerName = nullptr) noexcept | |||||
#ifndef CARLA_OS_WASM | |||||
: fRunnerThread(runnerName), | |||||
#else | |||||
: fRunnerName(runnerName), | |||||
fShouldStop(false), | |||||
#endif | |||||
fTimeInterval(0) {} | |||||
/* | |||||
* Destructor. | |||||
*/ | |||||
virtual ~CarlaRunner() /*noexcept*/ | |||||
{ | |||||
CARLA_SAFE_ASSERT(! isRunnerActive()); | |||||
stopRunner(); | |||||
} | |||||
/* | |||||
* Virtual function to be implemented by the subclass. | |||||
* Return true to keep running, false to stop execution. | |||||
*/ | |||||
virtual bool run() = 0; | |||||
/* | |||||
* Check if the runner should stop. | |||||
* To be called from inside the runner to know if a stop request has been made. | |||||
*/ | |||||
bool shouldRunnerStop() const noexcept | |||||
{ | |||||
#ifndef CARLA_OS_WASM | |||||
return fRunnerThread.shouldThreadExit(); | |||||
#else | |||||
return fShouldStop; | |||||
#endif | |||||
} | |||||
// --------------------------------------------------------------------------------------------------------------- | |||||
public: | |||||
/* | |||||
* Check if the runner is active. | |||||
*/ | |||||
bool isRunnerActive() noexcept | |||||
{ | |||||
#ifndef CARLA_OS_WASM | |||||
return fRunnerThread.isThreadRunning(); | |||||
#else | |||||
fShouldStop = false; | |||||
return true; | |||||
#endif | |||||
} | |||||
/* | |||||
* Start the thread. | |||||
*/ | |||||
bool startRunner(const uint timeIntervalMilliseconds = 0) noexcept | |||||
{ | |||||
fTimeInterval = timeIntervalMilliseconds; | |||||
#ifndef CARLA_OS_WASM | |||||
return fRunnerThread.startThread(); | |||||
#else | |||||
fShouldStop = false; | |||||
emscripten_async_call(_entryPoint, this, timeIntervalMilliseconds); | |||||
return true; | |||||
#endif | |||||
} | |||||
/* | |||||
* Stop the runner. | |||||
* This will signal the runner to stop if active, and wait until it finishes. | |||||
*/ | |||||
bool stopRunner() noexcept | |||||
{ | |||||
#ifndef CARLA_OS_WASM | |||||
return fRunnerThread.stopThread(); | |||||
#else | |||||
fShouldStop = true; | |||||
return true; | |||||
#endif | |||||
} | |||||
/* | |||||
* Tell the runner to stop as soon as possible. | |||||
*/ | |||||
void signalRunnerShouldStop() noexcept | |||||
{ | |||||
#ifndef CARLA_OS_WASM | |||||
fRunnerThread.signalThreadShouldExit(); | |||||
#else | |||||
fShouldStop = true; | |||||
#endif | |||||
} | |||||
// --------------------------------------------------------------------------------------------------------------- | |||||
/* | |||||
* Returns the name of the runner. | |||||
* This is the name that gets set in the constructor. | |||||
*/ | |||||
const CarlaString& getRunnerName() const noexcept | |||||
{ | |||||
#ifndef CARLA_OS_WASM | |||||
return fRunnerThread.getThreadName(); | |||||
#else | |||||
return fRunnerName; | |||||
#endif | |||||
} | |||||
// --------------------------------------------------------------------------------------------------------------- | |||||
private: | |||||
#ifndef CARLA_OS_WASM | |||||
class RunnerThread : private Thread | |||||
{ | |||||
Runner* const runner; | |||||
RunnerThread(Runner* const r, const char* const tn, const uint t) | |||||
: Thread(rn), | |||||
runner(r), | |||||
timeInterval(t) {} | |||||
void run() override | |||||
{ | |||||
while (!shouldThreadExit()) | |||||
{ | |||||
bool stillRunning = false; | |||||
try { | |||||
stillRunning = run(); | |||||
} catch(...) {} | |||||
if (stillRunning && !shouldThreadExit()) | |||||
{ | |||||
if (timeInterval != 0) | |||||
d_msleep(timeInterval) | |||||
pthread_yield(); | |||||
continue; | |||||
} | |||||
break; | |||||
} | |||||
} | |||||
} fRunnerThread; | |||||
#else | |||||
const CarlaString fRunnerName; | |||||
volatile bool fShouldStop; | |||||
void _runEntryPoint() noexcept | |||||
{ | |||||
if (fShouldStop) | |||||
return; | |||||
bool stillRunning = false; | |||||
try { | |||||
stillRunning = run(); | |||||
} catch(...) {} | |||||
if (stillRunning && !fShouldStop) | |||||
emscripten_async_call(_entryPoint, this, fTimeInterval); | |||||
} | |||||
static void _entryPoint(void* const userData) noexcept | |||||
{ | |||||
static_cast<CarlaRunner*>(userData)->_runEntryPoint(); | |||||
} | |||||
#endif | |||||
uint fTimeInterval; | |||||
CARLA_DECLARE_NON_COPYABLE(CarlaRunner) | |||||
}; | |||||
// ------------------------------------------------------------------------------------------------------------------- | |||||
#endif // CARLA_RUNNER_HPP_INCLUDED |