@@ -40,190 +40,8 @@ using juce::String; | |||||
using juce::Time; | using juce::Time; | ||||
using juce::Thread; | 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 | 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 | // Bridge Engine client | ||||
@@ -271,17 +89,13 @@ public: | |||||
fShmNonRtServerControl(), | fShmNonRtServerControl(), | ||||
fBaseNameAudioPool(audioPoolBaseName), | fBaseNameAudioPool(audioPoolBaseName), | ||||
fBaseNameRtClientControl(rtClientBaseName), | fBaseNameRtClientControl(rtClientBaseName), | ||||
fBaseNameNonRtClientControl(nonRtClientBaseName), | |||||
fBaseNameNonRtServerControl(nonRtServerBaseName), | |||||
fIsOffline(false), | fIsOffline(false), | ||||
fFirstIdle(true), | fFirstIdle(true), | ||||
fLastPingTime(-1) | fLastPingTime(-1) | ||||
{ | { | ||||
carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName); | 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 | ~CarlaEngineBridge() noexcept override | ||||
@@ -324,7 +138,7 @@ public: | |||||
return false; | return false; | ||||
} | } | ||||
if (! fShmNonRtClientControl.attach()) | |||||
if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) | |||||
{ | { | ||||
clear(); | clear(); | ||||
carla_stderr("Failed to attach to non-rt client control shared memory"); | carla_stderr("Failed to attach to non-rt client control shared memory"); | ||||
@@ -338,7 +152,7 @@ public: | |||||
return false; | return false; | ||||
} | } | ||||
if (! fShmNonRtServerControl.attach()) | |||||
if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) | |||||
{ | { | ||||
clear(); | clear(); | ||||
carla_stderr("Failed to attach to non-rt server control shared memory"); | carla_stderr("Failed to attach to non-rt server control shared memory"); | ||||
@@ -1491,6 +1305,8 @@ private: | |||||
CarlaString fBaseNameAudioPool; | CarlaString fBaseNameAudioPool; | ||||
CarlaString fBaseNameRtClientControl; | CarlaString fBaseNameRtClientControl; | ||||
CarlaString fBaseNameNonRtClientControl; | |||||
CarlaString fBaseNameNonRtServerControl; | |||||
bool fIsOffline; | bool fIsOffline; | ||||
bool fFirstIdle; | 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 { | struct BridgeParamInfo { | ||||
float value; | float value; | ||||
CarlaString name; | CarlaString name; | ||||
@@ -2359,7 +2149,7 @@ public: | |||||
return false; | return false; | ||||
} | } | ||||
if (! fShmNonRtClientControl.initialize()) | |||||
if (! fShmNonRtClientControl.initializeServer()) | |||||
{ | { | ||||
carla_stderr("Failed to initialize Non-RT client control"); | carla_stderr("Failed to initialize Non-RT client control"); | ||||
fShmRtClientControl.clear(); | fShmRtClientControl.clear(); | ||||
@@ -2367,7 +2157,7 @@ public: | |||||
return false; | return false; | ||||
} | } | ||||
if (! fShmNonRtServerControl.initialize()) | |||||
if (! fShmNonRtServerControl.initializeServer()) | |||||
{ | { | ||||
carla_stderr("Failed to initialize Non-RT server control"); | carla_stderr("Failed to initialize Non-RT server control"); | ||||
fShmNonRtClientControl.clear(); | fShmNonRtClientControl.clear(); | ||||
@@ -126,6 +126,7 @@ void BridgeAudioPool::clear() noexcept | |||||
jackbridge_shm_init(shm); | jackbridge_shm_init(shm); | ||||
} | } | ||||
#ifndef BUILD_BRIDGE | |||||
void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept | 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),); | 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); | std::memset(data, 0, dataSize); | ||||
} | } | ||||
#endif | |||||
// ------------------------------------------------------------------------------------------------------------------- | // ------------------------------------------------------------------------------------------------------------------- | ||||
@@ -258,15 +260,15 @@ bool BridgeRtClientControl::mapData() noexcept | |||||
if (jackbridge_shm_map2<BridgeRtClientData>(shm, data)) | 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); | CARLA_SAFE_ASSERT(data->midiOut[0] == 0); | ||||
setRingBuffer(&data->ringBuffer, false); | setRingBuffer(&data->ringBuffer, false); | ||||
CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false); | CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false); | ||||
CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false); | CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false); | ||||
#else | |||||
std::memset(data, 0, sizeof(BridgeRtClientData)); | |||||
setRingBuffer(&data->ringBuffer, true); | |||||
#endif | #endif | ||||
return true; | return true; | ||||
} | } | ||||
@@ -286,44 +288,328 @@ void BridgeRtClientControl::unmapData() noexcept | |||||
setRingBuffer(nullptr, false); | setRingBuffer(nullptr, false); | ||||
} | } | ||||
#ifndef BUILD_BRIDGE | |||||
bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept | bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept | ||||
{ | { | ||||
CARLA_SAFE_ASSERT_RETURN(msecs > 0, false); | CARLA_SAFE_ASSERT_RETURN(msecs > 0, false); | ||||
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); | ||||
#ifndef BUILD_BRIDGE | |||||
jackbridge_sem_post(&data->sem.server, true); | jackbridge_sem_post(&data->sem.server, true); | ||||
return jackbridge_sem_timedwait(&data->sem.client, msecs, 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 | #else | ||||
return false; | return false; | ||||
#endif | #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 | #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 | #else | ||||
return kPluginBridgeRtClientNull; | |||||
return false; | |||||
#endif | #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 | #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)); | writeUInt(static_cast<uint32_t>(opcode)); | ||||
} | |||||
#else | |||||
PluginBridgeNonRtClientOpcode BridgeNonRtClientControl::readOpcode() noexcept | |||||
{ | |||||
return static_cast<PluginBridgeNonRtClientOpcode>(readUInt()); | |||||
return kPluginBridgeNonRtClientNull; | |||||
} | |||||
#endif | #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 | #define CARLA_BRIDGE_UTILS_HPP_INCLUDED | ||||
#include "CarlaBridgeDefines.hpp" | #include "CarlaBridgeDefines.hpp" | ||||
#include "CarlaMutex.hpp" | |||||
#include "CarlaString.hpp" | #include "CarlaString.hpp" | ||||
#if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS) | #if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS) | ||||
@@ -211,7 +212,9 @@ struct BridgeAudioPool { | |||||
bool attachClient(const char* const fname) noexcept; | bool attachClient(const char* const fname) noexcept; | ||||
void clear() noexcept; | void clear() noexcept; | ||||
#ifndef BUILD_BRIDGE | |||||
void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept; | void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept; | ||||
#endif | |||||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) | CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool) | ||||
}; | }; | ||||
@@ -234,11 +237,12 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||||
bool mapData() noexcept; | bool mapData() noexcept; | ||||
void unmapData() noexcept; | void unmapData() noexcept; | ||||
// Client calls | |||||
#ifndef BUILD_BRIDGE | |||||
// non-bridge, server | |||||
bool waitForClient(const uint msecs) noexcept; | bool waitForClient(const uint msecs) noexcept; | ||||
void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept; | void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept; | ||||
// Servers calls | |||||
#else | |||||
// bridge, client | |||||
PluginBridgeRtClientOpcode readOpcode() noexcept; | PluginBridgeRtClientOpcode readOpcode() noexcept; | ||||
// helper class that automatically posts semaphore on destructor | // helper class that automatically posts semaphore on destructor | ||||
@@ -251,10 +255,71 @@ struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> { | |||||
CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper) | CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper) | ||||
}; | }; | ||||
#endif | |||||
CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl) | 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 | #endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED |