Browse Source

Move more bridge stuff into common code

tags/1.9.8
falkTX 7 years ago
parent
commit
918c049663
4 changed files with 237 additions and 235 deletions
  1. +6
    -103
      source/backend/engine/CarlaEngineBridge.cpp
  2. +1
    -132
      source/backend/plugin/CarlaPluginBridge.cpp
  3. +191
    -0
      source/utils/CarlaBridgeUtils.cpp
  4. +39
    -0
      source/utils/CarlaBridgeUtils.hpp

+ 6
- 103
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -41,7 +41,7 @@ using juce::Time;
using juce::Thread;

template<typename T>
bool jackbridge_shm_map2(void* shm, T*& value) noexcept
bool jackbridge_shm_map3(void* shm, T*& value) noexcept
{
value = (T*)jackbridge_shm_map(shm, sizeof(T));
return (value != nullptr);
@@ -51,102 +51,6 @@ CARLA_BACKEND_START_NAMESPACE

// -------------------------------------------------------------------

struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
CarlaString filename;
BridgeRtClientData* data;
char shm[64];

BridgeRtClientControl() noexcept
: filename(),
data(nullptr)
{
carla_zeroChars(shm, 64);
jackbridge_shm_init(shm);
}

~BridgeRtClientControl() 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))
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_map2<BridgeRtClientData>(shm, data))
{
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);
return true;
}

return false;
}

void unmapData() noexcept
{
data = nullptr;
setRingBuffer(nullptr, false);
}

PluginBridgeRtClientOpcode readOpcode() noexcept
{
return static_cast<PluginBridgeRtClientOpcode>(readUInt());
}

// helper class that automatically posts semaphore on destructor
struct WaitHelper {
BridgeRtClientData* const data;
const bool ok;

WaitHelper(BridgeRtClientControl& c) noexcept
: data(c.data),
ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {}

~WaitHelper() noexcept
{
if (ok)
jackbridge_sem_post(&data->sem.client, false);
}

CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper)
};

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
};

// -------------------------------------------------------------------

struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
CarlaString filename;
BridgeNonRtClientData* data;
@@ -199,7 +103,7 @@ struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer>
{
CARLA_SAFE_ASSERT(data == nullptr);

if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
if (jackbridge_shm_map3<BridgeNonRtClientData>(shm, data))
{
setRingBuffer(&data->ringBuffer, false);
return true;
@@ -278,7 +182,7 @@ struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer>
{
CARLA_SAFE_ASSERT(data == nullptr);

if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data))
if (jackbridge_shm_map3<BridgeNonRtServerData>(shm, data))
{
setRingBuffer(&data->ringBuffer, false);
return true;
@@ -366,15 +270,13 @@ public:
fShmNonRtClientControl(),
fShmNonRtServerControl(),
fBaseNameAudioPool(audioPoolBaseName),
fBaseNameRtClientControl(rtClientBaseName),
fIsOffline(false),
fFirstIdle(true),
fLastPingTime(-1)
{
carla_debug("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);

fShmRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT;
fShmRtClientControl.filename += rtClientBaseName;

fShmNonRtClientControl.filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT;
fShmNonRtClientControl.filename += nonRtClientBaseName;

@@ -408,7 +310,7 @@ public:
return false;
}

if (! fShmRtClientControl.attach())
if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
{
clear();
carla_stderr("Failed to attach to rt client control shared memory");
@@ -1588,6 +1490,7 @@ private:
BridgeNonRtServerControl fShmNonRtServerControl;

CarlaString fBaseNameAudioPool;
CarlaString fBaseNameRtClientControl;

bool fIsOffline;
bool fFirstIdle;


+ 1
- 132
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -51,137 +51,6 @@ static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };

// -------------------------------------------------------------------------------------------------------------------

struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
BridgeRtClientData* data;
CarlaString filename;
bool needsSemDestroy;
carla_shm_t shm;

BridgeRtClientControl()
: data(nullptr),
filename(),
needsSemDestroy(false)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, shm(carla_shm_t_INIT) {}
#else
{
carla_shm_init(shm);
}
#endif

~BridgeRtClientControl() 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_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);

if (! jackbridge_sem_init(&data->sem.server))
{
unmapData();
carla_shm_close(shm);
carla_shm_init(shm);
return false;
}

if (! jackbridge_sem_init(&data->sem.client))
{
jackbridge_sem_destroy(&data->sem.server);
unmapData();
carla_shm_close(shm);
carla_shm_init(shm);
return false;
}

filename = tmpFileBase;
needsSemDestroy = true;
return true;
}

void clear() noexcept
{
filename.clear();

if (needsSemDestroy)
{
jackbridge_sem_destroy(&data->sem.client);
jackbridge_sem_destroy(&data->sem.server);
needsSemDestroy = false;
}

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<BridgeRtClientData>(shm, data))
{
std::memset(data, 0, sizeof(BridgeRtClientData));
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);
}

bool waitForClient(const uint msecs) noexcept
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);

jackbridge_sem_post(&data->sem.server, true);

return jackbridge_sem_timedwait(&data->sem.client, msecs, true);
}

void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
{
writeUInt(static_cast<uint32_t>(opcode));
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
};

// -------------------------------------------------------------------------------------------------------------------

struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
BridgeNonRtClientData* data;
CarlaString filename;
@@ -2483,7 +2352,7 @@ public:
return false;
}

if (! fShmRtClientControl.initialize())
if (! fShmRtClientControl.initializeServer())
{
carla_stderr("Failed to initialize RT client control");
fShmAudioPool.clear();


+ 191
- 0
source/utils/CarlaBridgeUtils.cpp View File

@@ -38,6 +38,15 @@

// -------------------------------------------------------------------------------------------------------------------

template<typename T>
bool jackbridge_shm_map2(void* shm, T*& value) noexcept
{
value = (T*)jackbridge_shm_map(shm, sizeof(T));
return (value != nullptr);
}

// -------------------------------------------------------------------------------------------------------------------

BridgeAudioPool::BridgeAudioPool() noexcept
: data(nullptr),
dataSize(0),
@@ -136,3 +145,185 @@ void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPort
}

// -------------------------------------------------------------------------------------------------------------------

BridgeRtClientControl::BridgeRtClientControl() noexcept
: data(nullptr),
filename(),
needsSemDestroy(false)
{
carla_zeroChars(shm, 64);
jackbridge_shm_init(shm);
}

BridgeRtClientControl::~BridgeRtClientControl() noexcept
{
// should be cleared by now
CARLA_SAFE_ASSERT(data == nullptr);

clear();
}

bool BridgeRtClientControl::initializeServer() noexcept
{
#ifndef BUILD_BRIDGE
char tmpFileBase[64];
std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_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);

// NEW
if (! mapData())
{
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
return false;
}

CARLA_SAFE_ASSERT(data != nullptr);

if (! jackbridge_sem_init(&data->sem.server))
{
unmapData();
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
return false;
}

if (! jackbridge_sem_init(&data->sem.client))
{
jackbridge_sem_destroy(&data->sem.server);
unmapData();
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
return false;
}
// NEW

filename = tmpFileBase;
needsSemDestroy = true;
return true;
#else
return false;
#endif
}

bool BridgeRtClientControl::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_RT_CLIENT;
filename += basename;

jackbridge_shm_attach(shm, filename);

return jackbridge_shm_is_valid(shm);
#else
return false;
#endif
}

void BridgeRtClientControl::clear() noexcept
{
filename.clear();

if (needsSemDestroy)
{
jackbridge_sem_destroy(&data->sem.client);
jackbridge_sem_destroy(&data->sem.server);
needsSemDestroy = false;
}

if (data != nullptr)
unmapData();

if (! jackbridge_shm_is_valid(shm))
return;

jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
}

bool BridgeRtClientControl::mapData() noexcept
{
CARLA_SAFE_ASSERT(data == nullptr);

if (jackbridge_shm_map2<BridgeRtClientData>(shm, data))
{
#ifndef BUILD_BRIDGE
std::memset(data, 0, sizeof(BridgeRtClientData));
setRingBuffer(&data->ringBuffer, true);
#else
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);
#endif
return true;
}

return false;
}

void BridgeRtClientControl::unmapData() noexcept
{
#ifndef BUILD_BRIDGE
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);

jackbridge_shm_unmap(shm, data);
#endif

data = nullptr;
setRingBuffer(nullptr, false);
}

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);
#else
return false;
#endif
}

PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept
{
#ifdef BUILD_BRIDGE
return static_cast<PluginBridgeRtClientOpcode>(readUInt());
#else
return kPluginBridgeRtClientNull;
#endif
}

void BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
{
#ifndef BUILD_BRIDGE
writeUInt(static_cast<uint32_t>(opcode));
#endif
}

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);
}

// -------------------------------------------------------------------------------------------------------------------

+ 39
- 0
source/utils/CarlaBridgeUtils.hpp View File

@@ -218,4 +218,43 @@ struct BridgeAudioPool {

// -------------------------------------------------------------------------------------------------------------------

struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
BridgeRtClientData* data;
CarlaString filename;
bool needsSemDestroy; // client only
char shm[64];

BridgeRtClientControl() noexcept;
~BridgeRtClientControl() noexcept override;

bool initializeServer() noexcept;
bool attachClient(const char* const basename) noexcept;
void clear() noexcept;

bool mapData() noexcept;
void unmapData() noexcept;

// Client calls
bool waitForClient(const uint msecs) noexcept;
void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept;

// Servers calls
PluginBridgeRtClientOpcode readOpcode() noexcept;

// helper class that automatically posts semaphore on destructor
struct WaitHelper {
BridgeRtClientData* const data;
const bool ok;

WaitHelper(BridgeRtClientControl& c) noexcept;
~WaitHelper() noexcept;

CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper)
};

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
};

// -------------------------------------------------------------------------------------------------------------------

#endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED

Loading…
Cancel
Save