@@ -48,32 +48,27 @@ struct CarlaBackendStandalone { | |||
CarlaEngine* engine; | |||
EngineCallbackFunc engineCallback; | |||
void* engineCallbackPtr; | |||
#ifndef BUILD_BRIDGE | |||
EngineOptions engineOptions; | |||
#endif | |||
FileCallbackFunc fileCallback; | |||
void* fileCallbackPtr; | |||
CarlaString lastError; | |||
CarlaBackendStandalone() | |||
CarlaBackendStandalone() noexcept | |||
: engine(nullptr), | |||
engineCallback(nullptr), | |||
engineCallbackPtr(nullptr), | |||
#ifndef BUILD_BRIDGE | |||
engineOptions(), | |||
#endif | |||
fileCallback(nullptr), | |||
fileCallbackPtr(nullptr), | |||
lastError() | |||
{ | |||
#ifdef BUILD_BRIDGE | |||
engineOptions.processMode = CB::ENGINE_PROCESS_MODE_BRIDGE; | |||
engineOptions.transportMode = CB::ENGINE_TRANSPORT_MODE_BRIDGE; | |||
engineOptions.forceStereo = false; | |||
engineOptions.preferPluginBridges = false; | |||
engineOptions.preferUiBridges = false; | |||
#endif | |||
} | |||
lastError() {} | |||
~CarlaBackendStandalone() | |||
~CarlaBackendStandalone() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(engine == nullptr); | |||
} | |||
@@ -192,6 +187,7 @@ protected: | |||
#endif | |||
} | |||
// FIXME | |||
int handleOpen(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(fOscServer != nullptr, 0); | |||
@@ -203,8 +199,10 @@ protected: | |||
if (! carla_is_engine_running()) | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
gStandalone.engineOptions.processMode = CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS; | |||
gStandalone.engineOptions.transportMode = CB::ENGINE_TRANSPORT_MODE_JACK; | |||
#endif | |||
carla_engine_init("JACK", clientId); | |||
} | |||
@@ -414,10 +412,9 @@ static void carla_engine_init_common() | |||
#ifdef BUILD_BRIDGE | |||
using juce::File; | |||
File binaryDir(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()); | |||
gStandalone.engineOptions.binaryDir = carla_strdup_safe(binaryDir.getFullPathName().toRawUTF8()); | |||
gStandalone.engineOptions.resourceDir = carla_strdup_safe(binaryDir.getChildFile("resources").getFullPathName().toRawUTF8()); | |||
File juceBinaryDir(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()); | |||
/* | |||
if (const char* const uisAlwaysOnTop = std::getenv("ENGINE_OPTION_FORCE_STEREO")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_FORCE_STEREO, (std::strcmp(uisAlwaysOnTop, "true") == 0) ? 1 : 0, nullptr); | |||
@@ -426,6 +423,7 @@ static void carla_engine_init_common() | |||
if (const char* const uisAlwaysOnTop = std::getenv("ENGINE_OPTION_PREFER_UI_BRIDGES")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PREFER_UI_BRIDGES, (std::strcmp(uisAlwaysOnTop, "true") == 0) ? 1 : 0, nullptr); | |||
*/ | |||
if (const char* const uisAlwaysOnTop = std::getenv("ENGINE_OPTION_UIS_ALWAYS_ON_TOP")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_UIS_ALWAYS_ON_TOP, (std::strcmp(uisAlwaysOnTop, "true") == 0) ? 1 : 0, nullptr); | |||
@@ -465,9 +463,13 @@ static void carla_engine_init_common() | |||
if (const char* const binaryDir = std::getenv("ENGINE_OPTION_PATH_BINARIES")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, binaryDir); | |||
else | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_BINARIES, 0, juceBinaryDir.getFullPathName().toRawUTF8()); | |||
if (const char* const resourceDir = std::getenv("ENGINE_OPTION_PATH_RESOURCES")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, resourceDir); | |||
else | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PATH_RESOURCES, 0, juceBinaryDir.getChildFile("resources").getFullPathName().toRawUTF8()); | |||
if (const char* const preventBadBehaviour = std::getenv("ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR")) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR, (std::strcmp(preventBadBehaviour, "true") == 0) ? 1 : 0, nullptr); | |||
@@ -568,8 +570,6 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||
return false; | |||
} | |||
carla_engine_init_common(); | |||
#ifdef BUILD_BRIDGE | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_PROCESS_MODE, CB::ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS, nullptr); | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, CB::ENGINE_TRANSPORT_MODE_JACK, nullptr); | |||
@@ -581,6 +581,8 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||
gStandalone.engine->setOption(CB::ENGINE_OPTION_TRANSPORT_MODE, static_cast<int>(gStandalone.engineOptions.transportMode), nullptr); | |||
#endif | |||
carla_engine_init_common(); | |||
if (gStandalone.engine->init(clientName)) | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
@@ -32,6 +32,7 @@ | |||
using juce::File; | |||
using juce::MemoryBlock; | |||
using juce::String; | |||
using juce::Time; | |||
template<typename T> | |||
bool jackbridge_shm_map2(char* shm, T*& value) noexcept | |||
@@ -374,7 +375,7 @@ public: | |||
fShmNonRtServerControl(), | |||
fIsOffline(false), | |||
fFirstIdle(true), | |||
fLastPingCounter(-1), | |||
fLastPingTime(-1), | |||
leakDetector_CarlaEngineBridge() | |||
{ | |||
carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); | |||
@@ -492,6 +493,14 @@ public: | |||
if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) | |||
return false; | |||
// tell backend we're live | |||
{ | |||
const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); | |||
fShmNonRtServerControl.writeOpcode(kPluginBridgeNonRtServerPong); | |||
fShmNonRtServerControl.commitWrite(); | |||
} | |||
startThread(); | |||
return true; | |||
@@ -500,7 +509,7 @@ public: | |||
bool close() override | |||
{ | |||
carla_debug("CarlaEnginePlugin::close()"); | |||
fLastPingCounter = -1; | |||
fLastPingTime = -1; | |||
CarlaEngine::close(); | |||
@@ -535,10 +544,13 @@ public: | |||
CarlaPlugin* const plugin(pData->plugins[0].plugin); | |||
CARLA_SAFE_ASSERT_RETURN(plugin != nullptr,); | |||
const bool wasFirstIdle(fFirstIdle); | |||
if (fFirstIdle) | |||
{ | |||
fFirstIdle = false; | |||
fLastPingCounter = 0; | |||
fLastPingTime = Time::currentTimeMillis(); | |||
CARLA_SAFE_ASSERT(fLastPingTime > 0); | |||
char bufStr[STR_MAX+1]; | |||
uint32_t bufStrSize; | |||
@@ -753,6 +765,7 @@ public: | |||
fShmNonRtServerControl.waitIfDataIsReachingLimit(); | |||
carla_stdout("Carla Client Ready!"); | |||
fLastPingTime = Time::currentTimeMillis(); | |||
} | |||
// send parameter outputs | |||
@@ -781,9 +794,9 @@ public: | |||
handleNonRtData(); | |||
} CARLA_SAFE_EXCEPTION("handleNonRtData"); | |||
if (fLastPingCounter >= 0 && ++fLastPingCounter == 500) | |||
if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 5000 && ! wasFirstIdle) | |||
{ | |||
carla_stderr("Did not receive ping message from server for a long time, closing..."); | |||
carla_stderr("Did not receive ping message from server for 5 secs, closing..."); | |||
callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | |||
} | |||
} | |||
@@ -792,7 +805,7 @@ public: | |||
{ | |||
CarlaEngine::callback(action, pluginId, value1, value2, value3, valueStr); | |||
if (fLastPingCounter < 0) | |||
if (fLastPingTime < 0) | |||
return; | |||
switch (action) | |||
@@ -872,8 +885,8 @@ public: | |||
} | |||
#endif | |||
if (opcode != kPluginBridgeNonRtClientNull && fLastPingCounter > 0) | |||
fLastPingCounter = 0; | |||
if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0) | |||
fLastPingTime = Time::currentTimeMillis(); | |||
switch (opcode) | |||
{ | |||
@@ -887,6 +900,12 @@ public: | |||
fShmNonRtServerControl.commitWrite(); | |||
} break; | |||
case kPluginBridgeNonRtClientPingOnOff: { | |||
const uint32_t onOff(fShmNonRtClientControl.readBool()); | |||
fLastPingTime = onOff ? Time::currentTimeMillis() : -1; | |||
} break; | |||
case kPluginBridgeNonRtClientActivate: | |||
if (plugin != nullptr && plugin->isEnabled()) | |||
plugin->setActive(true, false, false); | |||
@@ -1456,7 +1475,7 @@ private: | |||
bool fIsOffline; | |||
bool fFirstIdle; | |||
int32_t fLastPingCounter; | |||
int64_t fLastPingTime; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge) | |||
}; | |||
@@ -1179,8 +1179,13 @@ public: | |||
handleNonRtData(); | |||
} CARLA_SAFE_EXCEPTION("handleNonRtData"); | |||
} | |||
else | |||
carla_stderr2("TESTING: Bridge has closed!"); | |||
else if (fInitiated) | |||
{ | |||
fTimedOut = true; | |||
fTimedError = true; | |||
fInitiated = false; | |||
pData->engine->callback(ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, pData->id, 0, 0, 0.0f, "plugin bridge has been stopped or crashed"); | |||
} | |||
CarlaPlugin::idle(); | |||
} | |||
@@ -52,6 +52,7 @@ enum PluginBridgeRtClientOpcode { | |||
enum PluginBridgeNonRtClientOpcode { | |||
kPluginBridgeNonRtClientNull = 0, | |||
kPluginBridgeNonRtClientPing, | |||
kPluginBridgeNonRtClientPingOnOff, // bool | |||
kPluginBridgeNonRtClientActivate, | |||
kPluginBridgeNonRtClientDeactivate, | |||
kPluginBridgeNonRtClientSetBufferSize, // uint | |||
@@ -197,6 +198,8 @@ const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcod | |||
return "kPluginBridgeNonRtClientNull"; | |||
case kPluginBridgeNonRtClientPing: | |||
return "kPluginBridgeNonRtClientPing"; | |||
case kPluginBridgeNonRtClientPingOnOff: | |||
return "kPluginBridgeNonRtClientPingOnOff"; | |||
case kPluginBridgeNonRtClientActivate: | |||
return "kPluginBridgeNonRtClientActivate"; | |||
case kPluginBridgeNonRtClientDeactivate: | |||