Browse Source

Restart plugin bridges when re-activated, using last saved state

tags/v1.9.11
falkTX 6 years ago
parent
commit
d21c37ee64
1 changed files with 156 additions and 74 deletions
  1. +156
    -74
      source/backend/plugin/CarlaPluginBridge.cpp

+ 156
- 74
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -912,8 +912,7 @@ public:
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");
handleProcessStopped();
}

CarlaPlugin::idle();
@@ -1086,7 +1085,10 @@ public:

void activate() noexcept override
{
CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
if (! fBridgeThread.isThreadRunning())
{
CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),);
}

{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
@@ -1832,8 +1834,17 @@ public:
fInfo.aIns = fShmNonRtServerControl.readUInt();
fInfo.aOuts = fShmNonRtServerControl.readUInt();

CARLA_SAFE_ASSERT(fInfo.aInNames == nullptr);
CARLA_SAFE_ASSERT(fInfo.aOutNames == nullptr);
if (fInfo.aInNames != nullptr)
{
delete[] fInfo.aInNames;
fInfo.aInNames = nullptr;
}

if (fInfo.aOutNames != nullptr)
{
delete[] fInfo.aOutNames;
fInfo.aOutNames = nullptr;
}

if (fInfo.aIns > 0)
{
@@ -2326,26 +2337,6 @@ public:
return false;
}

// ---------------------------------------------------------------
// initial values

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION);

fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());

fShmNonRtClientControl.commitWrite();

// testing dummy message
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
fShmRtClientControl.commitWrite();

#ifndef CARLA_OS_WIN
// ---------------------------------------------------------------
// set wine prefix
@@ -2388,58 +2379,10 @@ public:
fWinePrefix.toRawUTF8(),
#endif
bridgeBinary, label, shmIdsStr);
fBridgeThread.startThread();
}

// ---------------------------------------------------------------
// wait for bridge to start

fInitiated = false;
fLastPongTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPongTime > 0);

static bool sFirstInit = true;

int64_t timeoutEnd = 5000;

if (sFirstInit)
timeoutEnd *= 2;
#ifndef CARLA_OS_WIN
if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
timeoutEnd *= 2;
#endif
sFirstInit = false;

const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;

for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
{
pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (needsEngineIdle)
pData->engine->idle();

idle();

if (fInitiated)
break;
if (pData->engine->isAboutToClose())
break;

carla_msleep(20);
}

fLastPongTime = -1;

if (fInitError || ! fInitiated)
{
fBridgeThread.stopThread(6000);

if (! fInitError)
pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");

if (! restartBridgeThread())
return false;
}

// ---------------------------------------------------------------
// register client
@@ -2586,6 +2529,24 @@ private:

BridgeParamInfo* fParams;

void handleProcessStopped() noexcept
{
const bool wasActive = pData->active;
pData->active = false;

if (wasActive)
{
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
if (pData->engine->isOscControlRegistered())
pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, 0.0f);
pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0.0f, nullptr);
#endif
}

if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
}

void resizeAudioPool(const uint32_t bufferSize)
{
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
@@ -2609,6 +2570,127 @@ private:
carla_stderr2("waitForClient(%s) timed out", action);
}

bool restartBridgeThread()
{
fInitiated = false;
fInitError = false;
fTimedError = false;

// reset memory
fShmRtClientControl.data->procFlags = 0;
carla_zeroStruct(fShmRtClientControl.data->timeInfo);
carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);

fShmRtClientControl.clearData();
fShmNonRtClientControl.clearData();
fShmNonRtServerControl.clearData();

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION);

fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());

fShmNonRtClientControl.commitWrite();

if (fShmAudioPool.dataSize != 0)
{
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
fShmRtClientControl.commitWrite();
}
else
{
// testing dummy message
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
fShmRtClientControl.commitWrite();
}

fBridgeThread.startThread();

fLastPongTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPongTime > 0);

static bool sFirstInit = true;

int64_t timeoutEnd = 5000;

if (sFirstInit)
timeoutEnd *= 2;
#ifndef CARLA_OS_WIN
if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
timeoutEnd *= 2;
#endif
sFirstInit = false;

const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;

for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
{
pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (needsEngineIdle)
pData->engine->idle();

idle();

if (fInitiated)
break;
if (pData->engine->isAboutToClose())
break;

carla_msleep(20);
}

fLastPongTime = -1;

if (fInitError || ! fInitiated)
{
fBridgeThread.stopThread(6000);

if (! fInitError)
pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n"
"(or the plugin crashed on initialization?)");

return false;
}

if (const size_t dataSize = fInfo.chunk.size())
{
#ifdef CARLA_PROPER_CPP11_SUPPORT
void* data = fInfo.chunk.data();
#else
void* data = &fInfo.chunk.front();
#endif
CarlaString dataBase64(CarlaString::asBase64(data, dataSize));
CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0, true);

String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());

filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
filePath += fShmAudioPool.getFilenameSuffix();

if (File(filePath).replaceWithText(dataBase64.buffer()))
{
const uint32_t ulength(static_cast<uint32_t>(filePath.length()));

const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
fShmNonRtClientControl.writeUInt(ulength);
fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
fShmNonRtClientControl.commitWrite();
}
}

return true;
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)
};



Loading…
Cancel
Save