@@ -40,190 +40,8 @@ using juce::String; | |||
using juce::Time; | |||
using juce::Thread; | |||
template<typename T> | |||
bool jackbridge_shm_map3(void* shm, T*& value) noexcept | |||
{ | |||
value = (T*)jackbridge_shm_map(shm, sizeof(T)); | |||
return (value != nullptr); | |||
} | |||
CARLA_BACKEND_START_NAMESPACE | |||
// ------------------------------------------------------------------- | |||
struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> { | |||
CarlaString filename; | |||
BridgeNonRtClientData* data; | |||
char shm[64]; | |||
BridgeNonRtClientControl() noexcept | |||
: filename(), | |||
data(nullptr) | |||
{ | |||
carla_zeroChars(shm, 64); | |||
jackbridge_shm_init(shm); | |||
} | |||
~BridgeNonRtClientControl() noexcept override | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
clear(); | |||
} | |||
void clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! jackbridge_shm_is_valid(shm)) | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
return; | |||
} | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
} | |||
bool attach() noexcept | |||
{ | |||
// must be invalid right now | |||
CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); | |||
jackbridge_shm_attach(shm, filename); | |||
return jackbridge_shm_is_valid(shm); | |||
} | |||
bool mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (jackbridge_shm_map3<BridgeNonRtClientData>(shm, data)) | |||
{ | |||
setRingBuffer(&data->ringBuffer, false); | |||
return true; | |||
} | |||
return false; | |||
} | |||
void unmapData() noexcept | |||
{ | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
PluginBridgeNonRtClientOpcode readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeNonRtClientOpcode>(readUInt()); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl) | |||
}; | |||
// ------------------------------------------------------------------- | |||
struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> { | |||
CarlaMutex mutex; | |||
CarlaString filename; | |||
BridgeNonRtServerData* data; | |||
char shm[64]; | |||
BridgeNonRtServerControl() noexcept | |||
: mutex(), | |||
filename(), | |||
data(nullptr) | |||
{ | |||
carla_zeroChars(shm, 64); | |||
jackbridge_shm_init(shm); | |||
} | |||
~BridgeNonRtServerControl() noexcept override | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
clear(); | |||
} | |||
void clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! jackbridge_shm_is_valid(shm)) | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
return; | |||
} | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
} | |||
bool attach() noexcept | |||
{ | |||
// must be invalid right now | |||
CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); | |||
jackbridge_shm_attach(shm, filename); | |||
return jackbridge_shm_is_valid(shm); | |||
} | |||
bool mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (jackbridge_shm_map3<BridgeNonRtServerData>(shm, data)) | |||
{ | |||
setRingBuffer(&data->ringBuffer, false); | |||
return true; | |||
} | |||
return false; | |||
} | |||
void unmapData() noexcept | |||
{ | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept | |||
{ | |||
writeUInt(static_cast<uint32_t>(opcode)); | |||
} | |||
void waitIfDataIsReachingLimit() noexcept | |||
{ | |||
if (getAvailableDataSize() < HugeStackBuffer::size/4) | |||
return; | |||
for (int i=50; --i >= 0;) | |||
{ | |||
if (getAvailableDataSize() >= HugeStackBuffer::size*3/4) | |||
{ | |||
writeOpcode(kPluginBridgeNonRtServerPong); | |||
commitWrite(); | |||
return; | |||
} | |||
carla_msleep(20); | |||
} | |||
carla_stderr("Client waitIfDataIsReachingLimit() reached and failed"); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
// Bridge Engine client | |||
@@ -271,17 +89,13 @@ public: | |||
fShmNonRtServerControl(), | |||
fBaseNameAudioPool(audioPoolBaseName), | |||
fBaseNameRtClientControl(rtClientBaseName), | |||
fBaseNameNonRtClientControl(nonRtClientBaseName), | |||
fBaseNameNonRtServerControl(nonRtServerBaseName), | |||
fIsOffline(false), | |||
fFirstIdle(true), | |||
fLastPingTime(-1) | |||
{ | |||
carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); | |||
fShmNonRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT; | |||
fShmNonRtClientControl.filename += nonRtClientBaseName; | |||
fShmNonRtServerControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER; | |||
fShmNonRtServerControl.filename += nonRtServerBaseName; | |||
} | |||
~CarlaEngineBridge() noexcept override | |||
@@ -324,7 +138,7 @@ public: | |||
return false; | |||
} | |||
if (! fShmNonRtClientControl.attach()) | |||
if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) | |||
{ | |||
clear(); | |||
carla_stderr("Failed to attach to non-rt client control shared memory"); | |||
@@ -338,7 +152,7 @@ public: | |||
return false; | |||
} | |||
if (! fShmNonRtServerControl.attach()) | |||
if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) | |||
{ | |||
clear(); | |||
carla_stderr("Failed to attach to non-rt server control shared memory"); | |||
@@ -1491,6 +1305,8 @@ private: | |||
CarlaString fBaseNameAudioPool; | |||
CarlaString fBaseNameRtClientControl; | |||
CarlaString fBaseNameNonRtClientControl; | |||
CarlaString fBaseNameNonRtServerControl; | |||
bool fIsOffline; | |||
bool fFirstIdle; | |||
@@ -51,216 +51,6 @@ static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 }; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> { | |||
BridgeNonRtClientData* data; | |||
CarlaString filename; | |||
CarlaMutex mutex; | |||
carla_shm_t shm; | |||
BridgeNonRtClientControl() noexcept | |||
: data(nullptr), | |||
filename(), | |||
mutex() | |||
#ifdef CARLA_PROPER_CPP11_SUPPORT | |||
, shm(carla_shm_t_INIT) {} | |||
#else | |||
{ | |||
carla_shm_init(shm); | |||
} | |||
#endif | |||
~BridgeNonRtClientControl() noexcept override | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
clear(); | |||
} | |||
bool initialize() noexcept | |||
{ | |||
char tmpFileBase[64]; | |||
std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "XXXXXX"); | |||
shm = carla_shm_create_temp(tmpFileBase); | |||
CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm), false); | |||
if (! mapData()) | |||
{ | |||
carla_shm_close(shm); | |||
carla_shm_init(shm); | |||
return false; | |||
} | |||
CARLA_SAFE_ASSERT(data != nullptr); | |||
filename = tmpFileBase; | |||
return true; | |||
} | |||
void clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! carla_is_shm_valid(shm)) | |||
return; | |||
carla_shm_close(shm); | |||
carla_shm_init(shm); | |||
} | |||
bool mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (carla_shm_map<BridgeNonRtClientData>(shm, data)) | |||
{ | |||
setRingBuffer(&data->ringBuffer, true); | |||
return true; | |||
} | |||
return false; | |||
} | |||
void unmapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
carla_shm_unmap(shm, data); | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
void writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept | |||
{ | |||
writeUInt(static_cast<uint32_t>(opcode)); | |||
} | |||
void waitIfDataIsReachingLimit() noexcept | |||
{ | |||
if (getAvailableDataSize() < BigStackBuffer::size/4) | |||
return; | |||
for (int i=50; --i >= 0;) | |||
{ | |||
if (getAvailableDataSize() >= BigStackBuffer::size*3/4) | |||
{ | |||
writeOpcode(kPluginBridgeNonRtClientPing); | |||
commitWrite(); | |||
return; | |||
} | |||
carla_msleep(20); | |||
} | |||
carla_stderr("Server waitIfDataIsReachingLimit() reached and failed"); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> { | |||
BridgeNonRtServerData* data; | |||
CarlaString filename; | |||
carla_shm_t shm; | |||
BridgeNonRtServerControl() noexcept | |||
: data(nullptr), | |||
filename() | |||
#ifdef CARLA_PROPER_CPP11_SUPPORT | |||
, shm(carla_shm_t_INIT) {} | |||
#else | |||
{ | |||
carla_shm_init(shm); | |||
} | |||
#endif | |||
~BridgeNonRtServerControl() noexcept override | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
clear(); | |||
} | |||
bool initialize() noexcept | |||
{ | |||
char tmpFileBase[64]; | |||
std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "XXXXXX"); | |||
shm = carla_shm_create_temp(tmpFileBase); | |||
if (! carla_is_shm_valid(shm)) | |||
return false; | |||
if (! mapData()) | |||
{ | |||
carla_shm_close(shm); | |||
carla_shm_init(shm); | |||
return false; | |||
} | |||
CARLA_SAFE_ASSERT(data != nullptr); | |||
filename = tmpFileBase; | |||
return true; | |||
} | |||
void clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! carla_is_shm_valid(shm)) | |||
return; | |||
carla_shm_close(shm); | |||
carla_shm_init(shm); | |||
} | |||
bool mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (carla_shm_map<BridgeNonRtServerData>(shm, data)) | |||
{ | |||
setRingBuffer(&data->ringBuffer, true); | |||
return true; | |||
} | |||
return false; | |||
} | |||
void unmapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
carla_shm_unmap(shm, data); | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
PluginBridgeNonRtServerOpcode readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeNonRtServerOpcode>(readUInt()); | |||
} | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
struct BridgeParamInfo { | |||
float value; | |||
CarlaString name; | |||
@@ -2359,7 +2149,7 @@ public: | |||
return false; | |||
} | |||
if (! fShmNonRtClientControl.initialize()) | |||
if (! fShmNonRtClientControl.initializeServer()) | |||
{ | |||
carla_stderr("Failed to initialize Non-RT client control"); | |||
fShmRtClientControl.clear(); | |||
@@ -2367,7 +2157,7 @@ public: | |||
return false; | |||
} | |||
if (! fShmNonRtServerControl.initialize()) | |||
if (! fShmNonRtServerControl.initializeServer()) | |||
{ | |||
carla_stderr("Failed to initialize Non-RT server control"); | |||
fShmNonRtClientControl.clear(); | |||
@@ -126,6 +126,7 @@ void BridgeAudioPool::clear() noexcept | |||
jackbridge_shm_init(shm); | |||
} | |||
#ifndef BUILD_BRIDGE | |||
void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(jackbridge_shm_is_valid(shm),); | |||
@@ -143,6 +144,7 @@ void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPort | |||
std::memset(data, 0, dataSize); | |||
} | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
@@ -258,15 +260,15 @@ bool BridgeRtClientControl::mapData() noexcept | |||
if (jackbridge_shm_map2<BridgeRtClientData>(shm, data)) | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
std::memset(data, 0, sizeof(BridgeRtClientData)); | |||
setRingBuffer(&data->ringBuffer, true); | |||
#else | |||
#ifdef BUILD_BRIDGE | |||
CARLA_SAFE_ASSERT(data->midiOut[0] == 0); | |||
setRingBuffer(&data->ringBuffer, false); | |||
CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false); | |||
CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false); | |||
#else | |||
std::memset(data, 0, sizeof(BridgeRtClientData)); | |||
setRingBuffer(&data->ringBuffer, true); | |||
#endif | |||
return true; | |||
} | |||
@@ -286,44 +288,328 @@ void BridgeRtClientControl::unmapData() noexcept | |||
setRingBuffer(nullptr, false); | |||
} | |||
#ifndef BUILD_BRIDGE | |||
bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(msecs > 0, false); | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | |||
#ifndef BUILD_BRIDGE | |||
jackbridge_sem_post(&data->sem.server, true); | |||
return jackbridge_sem_timedwait(&data->sem.client, msecs, true); | |||
return false; | |||
} | |||
void BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept | |||
{ | |||
writeUInt(static_cast<uint32_t>(opcode)); | |||
} | |||
#else | |||
PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeRtClientOpcode>(readUInt()); | |||
} | |||
BridgeRtClientControl::WaitHelper::WaitHelper(BridgeRtClientControl& c) noexcept | |||
: data(c.data), | |||
ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {} | |||
BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept | |||
{ | |||
if (ok) | |||
jackbridge_sem_post(&data->sem.client, false); | |||
} | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
BridgeNonRtClientControl::BridgeNonRtClientControl() noexcept | |||
: data(nullptr), | |||
filename(), | |||
mutex() | |||
{ | |||
carla_zeroChars(shm, 64); | |||
jackbridge_shm_init(shm); | |||
} | |||
BridgeNonRtClientControl::~BridgeNonRtClientControl() noexcept | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
clear(); | |||
} | |||
bool BridgeNonRtClientControl::initializeServer() noexcept | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
char tmpFileBase[64]; | |||
std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "XXXXXX"); | |||
const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase); | |||
CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false); | |||
void* const shmptr = shm; | |||
carla_shm_t& shm1 = *(carla_shm_t*)shmptr; | |||
carla_copyStruct(shm1, shm2); | |||
if (! mapData()) | |||
{ | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
return false; | |||
} | |||
CARLA_SAFE_ASSERT(data != nullptr); | |||
filename = tmpFileBase; | |||
return true; | |||
#else | |||
return false; | |||
#endif | |||
} | |||
PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept | |||
bool BridgeNonRtClientControl::attachClient(const char* const basename) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false); | |||
#ifdef BUILD_BRIDGE | |||
return static_cast<PluginBridgeRtClientOpcode>(readUInt()); | |||
// must be invalid right now | |||
CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); | |||
filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT; | |||
filename += basename; | |||
jackbridge_shm_attach(shm, filename); | |||
return jackbridge_shm_is_valid(shm); | |||
#else | |||
return kPluginBridgeRtClientNull; | |||
return false; | |||
#endif | |||
} | |||
void BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept | |||
void BridgeNonRtClientControl::clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! jackbridge_shm_is_valid(shm)) | |||
{ | |||
#ifdef BUILD_BRIDGE | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
#endif | |||
return; | |||
} | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
} | |||
bool BridgeNonRtClientControl::mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data)) | |||
{ | |||
#ifdef BUILD_BRIDGE | |||
setRingBuffer(&data->ringBuffer, false); | |||
#else | |||
setRingBuffer(&data->ringBuffer, true); | |||
#endif | |||
return true; | |||
} | |||
return false; | |||
} | |||
void BridgeNonRtClientControl::unmapData() noexcept | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
jackbridge_shm_unmap(shm, data); | |||
#endif | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
#ifndef BUILD_BRIDGE | |||
void BridgeNonRtClientControl::waitIfDataIsReachingLimit() noexcept | |||
{ | |||
if (getAvailableDataSize() < BigStackBuffer::size/4) | |||
return; | |||
for (int i=50; --i >= 0;) | |||
{ | |||
if (getAvailableDataSize() >= BigStackBuffer::size*3/4) | |||
{ | |||
writeOpcode(kPluginBridgeNonRtClientPing); | |||
commitWrite(); | |||
return; | |||
} | |||
carla_msleep(20); | |||
} | |||
carla_stderr("Server waitIfDataIsReachingLimit() reached and failed"); | |||
} | |||
void BridgeNonRtClientControl::writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept | |||
{ | |||
writeUInt(static_cast<uint32_t>(opcode)); | |||
} | |||
#else | |||
PluginBridgeNonRtClientOpcode BridgeNonRtClientControl::readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeNonRtClientOpcode>(readUInt()); | |||
return kPluginBridgeNonRtClientNull; | |||
} | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
BridgeNonRtServerControl::BridgeNonRtServerControl() noexcept | |||
: data(nullptr), | |||
filename(), | |||
mutex() | |||
{ | |||
carla_zeroChars(shm, 64); | |||
jackbridge_shm_init(shm); | |||
} | |||
BridgeRtClientControl::WaitHelper::WaitHelper(BridgeRtClientControl& c) noexcept | |||
: data(c.data), | |||
ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {} | |||
BridgeNonRtServerControl::~BridgeNonRtServerControl() noexcept | |||
{ | |||
// should be cleared by now | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept | |||
clear(); | |||
} | |||
bool BridgeNonRtServerControl::initializeServer() noexcept | |||
{ | |||
if (ok) | |||
jackbridge_sem_post(&data->sem.client, false); | |||
#ifndef BUILD_BRIDGE | |||
char tmpFileBase[64]; | |||
std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "XXXXXX"); | |||
const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase); | |||
CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false); | |||
void* const shmptr = shm; | |||
carla_shm_t& shm1 = *(carla_shm_t*)shmptr; | |||
carla_copyStruct(shm1, shm2); | |||
if (! mapData()) | |||
{ | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
return false; | |||
} | |||
CARLA_SAFE_ASSERT(data != nullptr); | |||
filename = tmpFileBase; | |||
return true; | |||
#else | |||
return false; | |||
#endif | |||
} | |||
bool BridgeNonRtServerControl::attachClient(const char* const basename) noexcept | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false); | |||
#ifdef BUILD_BRIDGE | |||
// must be invalid right now | |||
CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false); | |||
filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER; | |||
filename += basename; | |||
jackbridge_shm_attach(shm, filename); | |||
return jackbridge_shm_is_valid(shm); | |||
#else | |||
return false; | |||
#endif | |||
} | |||
void BridgeNonRtServerControl::clear() noexcept | |||
{ | |||
filename.clear(); | |||
if (data != nullptr) | |||
unmapData(); | |||
if (! jackbridge_shm_is_valid(shm)) | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
return; | |||
} | |||
jackbridge_shm_close(shm); | |||
jackbridge_shm_init(shm); | |||
} | |||
bool BridgeNonRtServerControl::mapData() noexcept | |||
{ | |||
CARLA_SAFE_ASSERT(data == nullptr); | |||
if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data)) | |||
{ | |||
#ifdef BUILD_BRIDGE | |||
setRingBuffer(&data->ringBuffer, false); | |||
#else | |||
setRingBuffer(&data->ringBuffer, true); | |||
#endif | |||
return true; | |||
} | |||
return false; | |||
} | |||
void BridgeNonRtServerControl::unmapData() noexcept | |||
{ | |||
#ifndef BUILD_BRIDGE | |||
CARLA_SAFE_ASSERT_RETURN(data != nullptr,); | |||
jackbridge_shm_unmap(shm, data); | |||
#endif | |||
data = nullptr; | |||
setRingBuffer(nullptr, false); | |||
} | |||
#ifndef BUILD_BRIDGE | |||
PluginBridgeNonRtServerOpcode BridgeNonRtServerControl::readOpcode() noexcept | |||
{ | |||
return static_cast<PluginBridgeNonRtServerOpcode>(readUInt()); | |||
} | |||
#else | |||
void BridgeNonRtServerControl::waitIfDataIsReachingLimit() noexcept | |||
{ | |||
if (getAvailableDataSize() < HugeStackBuffer::size/4) | |||
return; | |||
for (int i=50; --i >= 0;) | |||
{ | |||
if (getAvailableDataSize() >= HugeStackBuffer::size*3/4) | |||
{ | |||
writeOpcode(kPluginBridgeNonRtServerPong); | |||
commitWrite(); | |||
return; | |||
} | |||
carla_msleep(20); | |||
} | |||
carla_stderr("Client waitIfDataIsReachingLimit() reached and failed"); | |||
} | |||
void BridgeNonRtServerControl::writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept | |||
{ | |||
writeUInt(static_cast<uint32_t>(opcode)); | |||
} | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- |
@@ -19,6 +19,7 @@ | |||
#define CARLA_BRIDGE_UTILS_HPP_INCLUDED | |||
#include "CarlaBridgeDefines.hpp" | |||
#include "CarlaMutex.hpp" | |||
#include "CarlaString.hpp" | |||
#if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS) | |||
@@ -211,7 +212,9 @@ struct BridgeAudioPool { | |||
bool attachClient(const char* const fname) noexcept; | |||
void clear() noexcept; | |||
#ifndef BUILD_BRIDGE | |||
void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept; | |||
#endif | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) | |||
}; | |||
@@ -234,11 +237,12 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||
bool mapData() noexcept; | |||
void unmapData() noexcept; | |||
// Client calls | |||
#ifndef BUILD_BRIDGE | |||
// non-bridge, server | |||
bool waitForClient(const uint msecs) noexcept; | |||
void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept; | |||
// Servers calls | |||
#else | |||
// bridge, client | |||
PluginBridgeRtClientOpcode readOpcode() noexcept; | |||
// helper class that automatically posts semaphore on destructor | |||
@@ -251,10 +255,71 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||
CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper) | |||
}; | |||
#endif | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> { | |||
BridgeNonRtClientData* data; | |||
CarlaString filename; | |||
CarlaMutex mutex; | |||
char shm[64]; | |||
BridgeNonRtClientControl() noexcept; | |||
~BridgeNonRtClientControl() noexcept override; | |||
bool initializeServer() noexcept; | |||
bool attachClient(const char* const basename) noexcept; | |||
void clear() noexcept; | |||
bool mapData() noexcept; | |||
void unmapData() noexcept; | |||
#ifndef BUILD_BRIDGE | |||
// non-bridge, server | |||
void waitIfDataIsReachingLimit() noexcept; | |||
void writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept; | |||
#else | |||
// bridge, client | |||
PluginBridgeNonRtClientOpcode readOpcode() noexcept; | |||
#endif | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> { | |||
BridgeNonRtServerData* data; | |||
CarlaString filename; | |||
CarlaMutex mutex; | |||
char shm[64]; | |||
BridgeNonRtServerControl() noexcept; | |||
~BridgeNonRtServerControl() noexcept override; | |||
bool initializeServer() noexcept; | |||
bool attachClient(const char* const basename) noexcept; | |||
void clear() noexcept; | |||
bool mapData() noexcept; | |||
void unmapData() noexcept; | |||
#ifndef BUILD_BRIDGE | |||
// non-bridge, server | |||
PluginBridgeNonRtServerOpcode readOpcode() noexcept; | |||
#else | |||
// bridge, client | |||
void waitIfDataIsReachingLimit() noexcept; | |||
void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept; | |||
#endif | |||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
#endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED |