Browse Source

Continue plugin-bridge rework

tags/1.9.6
falkTX 10 years ago
parent
commit
01935d32ea
9 changed files with 469 additions and 289 deletions
  1. +1
    -1
      source/backend/CarlaEngine.hpp
  2. +2
    -1
      source/backend/CarlaHost.h
  3. +7
    -5
      source/backend/CarlaStandalone.cpp
  4. +223
    -125
      source/backend/engine/CarlaEngineBridge.cpp
  5. +0
    -5
      source/backend/engine/CarlaEngineOsc.cpp
  6. +156
    -118
      source/backend/plugin/CarlaPluginBridge.cpp
  7. +22
    -17
      source/bridges-plugin/CarlaBridgePlugin.cpp
  8. +2
    -2
      source/utils/CarlaBridgeUtils.hpp
  9. +56
    -15
      source/utils/CarlaShmUtils.hpp

+ 1
- 1
source/backend/CarlaEngine.hpp View File

@@ -1167,7 +1167,7 @@ public:

#ifdef BUILD_BRIDGE
// Bridge
static CarlaEngine* newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName);
static CarlaEngine* newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName);
#else
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
// Juce


+ 2
- 1
source/backend/CarlaHost.h View File

@@ -423,7 +423,8 @@ CARLA_EXPORT bool carla_engine_init(const char* driverName, const char* clientNa
/*!
* Initialize the engine in bridged mode.
*/
CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseName[6+1], const char nonRtBaseName[6+1], const char* clientName);
CARLA_EXPORT bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1],
const char nonRtServerBaseName[6+1], const char* clientName);
#endif

/*!


+ 7
- 5
source/backend/CarlaStandalone.cpp View File

@@ -532,13 +532,15 @@ bool carla_engine_init(const char* driverName, const char* clientName)
}

#ifdef BUILD_BRIDGE
bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseName[6+1], const char nonRtBaseName[6+1], const char* clientName)
bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtClientBaseName[6+1], const char nonRtClientBaseName[6+1],
const char nonRtServerBaseName[6+1], const char* clientName)
{
CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(rtBaseName != nullptr && rtBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(nonRtBaseName != nullptr && nonRtBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(rtClientBaseName != nullptr && rtClientBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(nonRtClientBaseName != nullptr && nonRtClientBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(nonRtServerBaseName != nullptr && nonRtServerBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, rtBaseName, nonRtBaseName, clientName);
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\", \"%s\", \"%s\")", audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName);

if (gStandalone.engine != nullptr)
{
@@ -547,7 +549,7 @@ bool carla_engine_init_bridge(const char audioBaseName[6+1], const char rtBaseNa
return false;
}

gStandalone.engine = CarlaEngine::newBridge(audioBaseName, rtBaseName, nonRtBaseName);
gStandalone.engine = CarlaEngine::newBridge(audioBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);

if (gStandalone.engine == nullptr)
{


+ 223
- 125
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -29,15 +29,10 @@

#include "jackbridge/JackBridge.hpp"

#include <cerrno>
#include <ctime>

using juce::File;
using juce::MemoryBlock;
using juce::String;

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

template<typename T>
bool jackbridge_shm_map2(char* shm, T*& value) noexcept
{
@@ -45,8 +40,6 @@ bool jackbridge_shm_map2(char* shm, T*& value) noexcept
return (value != nullptr);
}

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

CARLA_BACKEND_START_NAMESPACE

// -------------------------------------------------------------------
@@ -72,34 +65,128 @@ struct BridgeAudioPool {
clear();
}

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

if (! jackbridge_shm_is_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

data = nullptr;

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

CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
};

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

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

BridgeRtClientControl() noexcept
: filename(),
data(nullptr)
{
carla_zeroChar(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 (! jackbridge_shm_is_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

data = nullptr;

if (jackbridge_shm_is_valid(shm))
jackbridge_shm_close(shm);
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
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);
return true;
}

return false;
}

bool postClient() noexcept
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);

return jackbridge_sem_post(&data->sem.client);
}

bool waitForServer(const uint secs) noexcept
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);

return jackbridge_sem_timedwait(&data->sem.server, secs);
}

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

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
};

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

struct BridgeRtControl : public CarlaRingBufferControl<SmallStackBuffer> {
struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
CarlaString filename;
BridgeRtClientData* data;
BridgeNonRtClientData* data;
char shm[64];

BridgeRtControl() noexcept
BridgeNonRtClientControl() noexcept
: filename(),
data(nullptr)
{
@@ -107,7 +194,7 @@ struct BridgeRtControl : public CarlaRingBufferControl<SmallStackBuffer> {
jackbridge_shm_init(shm);
}

~BridgeRtControl() noexcept override
~BridgeNonRtClientControl() noexcept override
{
// should be cleared by now
CARLA_SAFE_ASSERT(data == nullptr);
@@ -126,19 +213,24 @@ struct BridgeRtControl : public CarlaRingBufferControl<SmallStackBuffer> {
{
filename.clear();

if (! jackbridge_shm_is_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

data = nullptr;

if (jackbridge_shm_is_valid(shm))
jackbridge_shm_close(shm);
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
}

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

if (jackbridge_shm_map2<BridgeRtClientData>(shm, data))
if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
{
CARLA_SAFE_ASSERT(data->midiOut[0] == 0);
setRingBuffer(&data->ringBuffer, false);
return true;
}
@@ -146,22 +238,22 @@ struct BridgeRtControl : public CarlaRingBufferControl<SmallStackBuffer> {
return false;
}

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

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl)
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl)
};

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

struct BridgeNonRtControl : public CarlaRingBufferControl<BigStackBuffer> {
struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> {
CarlaString filename;
BridgeNonRtClientData* data;
BridgeNonRtServerData* data;
char shm[64];

BridgeNonRtControl() noexcept
BridgeNonRtServerControl() noexcept
: filename(),
data(nullptr)
{
@@ -169,7 +261,7 @@ struct BridgeNonRtControl : public CarlaRingBufferControl<BigStackBuffer> {
jackbridge_shm_init(shm);
}

~BridgeNonRtControl() noexcept override
~BridgeNonRtServerControl() noexcept override
{
// should be cleared by now
CARLA_SAFE_ASSERT(data == nullptr);
@@ -188,17 +280,23 @@ struct BridgeNonRtControl : public CarlaRingBufferControl<BigStackBuffer> {
{
filename.clear();

if (! jackbridge_shm_is_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

data = nullptr;

if (jackbridge_shm_is_valid(shm))
jackbridge_shm_close(shm);
jackbridge_shm_close(shm);
jackbridge_shm_init(shm);
}

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

if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data))
{
setRingBuffer(&data->ringBuffer, false);
return true;
@@ -207,12 +305,12 @@ struct BridgeNonRtControl : public CarlaRingBufferControl<BigStackBuffer> {
return false;
}

PluginBridgeNonRtClientOpcode readOpcode() noexcept
void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept
{
return static_cast<PluginBridgeNonRtClientOpcode>(readInt());
writeUInt(static_cast<uint32_t>(opcode));
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl)
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl)
};

// -------------------------------------------------------------------
@@ -221,30 +319,30 @@ class CarlaEngineBridge : public CarlaEngine,
public CarlaThread
{
public:
CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
: CarlaEngine(),
CarlaThread("CarlaEngineBridge"),
fShmAudioPool(),
fShmCVPool(),
fShmRtControl(),
fShmNonRtControl(),
fShmRtClientControl(),
fShmNonRtClientControl(),
fShmNonRtServerControl(),
fIsRunning(false),
fIsOffline(false),
leakDetector_CarlaEngineBridge()
{
carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtBaseName, nonRtBaseName);
carla_stdout("CarlaEngineBridge::CarlaEngineBridge(\"%s\", \"%s\", \"%s\", \"%s\")", audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);

fShmAudioPool.filename = "/carla-bridge_shm_ap_";
fShmAudioPool.filename += audioPoolBaseName;

//fShmCVPool.filename = "/carla-bridge_shm_cvp_";
//fShmCVPool.filename += cvPoolBaseName;
fShmRtClientControl.filename = "/carla-bridge_shm_rtC_";
fShmRtClientControl.filename += rtClientBaseName;

fShmRtControl.filename = "/carla-bridge_shm_rt_";
fShmRtControl.filename += rtBaseName;
fShmNonRtClientControl.filename = "/carla-bridge_shm_nonrtC_";
fShmNonRtClientControl.filename += nonRtClientBaseName;

fShmNonRtControl.filename = "/carla-bridge_shm_nonrt_";
fShmNonRtControl.filename += nonRtBaseName;
fShmNonRtServerControl.filename = "/carla-bridge_shm_nonrtS_";
fShmNonRtServerControl.filename += nonRtServerBaseName;
}

~CarlaEngineBridge() noexcept override
@@ -271,28 +369,28 @@ public:
return false;
}

if (! fShmRtControl.attach())
if (! fShmRtClientControl.attach())
{
clear();
carla_stdout("Failed to attach to rt control shared memory");
return false;
}

if (! fShmRtControl.mapData())
if (! fShmRtClientControl.mapData())
{
clear();
carla_stdout("Failed to map rt control shared memory");
return false;
}

if (! fShmNonRtControl.attach())
if (! fShmNonRtClientControl.attach())
{
clear();
carla_stdout("Failed to attach to non-rt control shared memory");
return false;
}

if (! fShmNonRtControl.mapData())
if (! fShmNonRtClientControl.mapData())
{
clear();
carla_stdout("Failed to map non-rt control shared memory");
@@ -301,22 +399,22 @@ public:

PluginBridgeNonRtClientOpcode opcode;

opcode = fShmNonRtControl.readOpcode();
opcode = fShmNonRtClientControl.readOpcode();
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientNull, opcode);

const uint32_t shmRtDataSize = fShmNonRtControl.readUInt();
const uint32_t shmRtDataSize = fShmNonRtClientControl.readUInt();
CARLA_SAFE_ASSERT_INT2(shmRtDataSize == sizeof(BridgeRtClientData), shmRtDataSize, sizeof(BridgeRtClientData));

const uint32_t shmNonRtDataSize = fShmNonRtControl.readUInt();
const uint32_t shmNonRtDataSize = fShmNonRtClientControl.readUInt();
CARLA_SAFE_ASSERT_INT2(shmNonRtDataSize == sizeof(BridgeNonRtClientData), shmNonRtDataSize, sizeof(BridgeNonRtClientData));

opcode = fShmNonRtControl.readOpcode();
opcode = fShmNonRtClientControl.readOpcode();
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetBufferSize, opcode);
pData->bufferSize = fShmNonRtControl.readUInt();
pData->bufferSize = fShmNonRtClientControl.readUInt();

opcode = fShmNonRtControl.readOpcode();
opcode = fShmNonRtClientControl.readOpcode();
CARLA_SAFE_ASSERT_INT(opcode == kPluginBridgeNonRtClientSetSampleRate, opcode);
pData->sampleRate = fShmNonRtControl.readDouble();
pData->sampleRate = fShmNonRtClientControl.readDouble();

carla_stdout("Carla Client Info:");
carla_stdout(" BufferSize: %i", pData->bufferSize);
@@ -377,15 +475,15 @@ public:
void clear() noexcept
{
fShmAudioPool.clear();
fShmRtControl.clear();
fShmNonRtControl.clear();
fShmRtClientControl.clear();
fShmNonRtClientControl.clear();
}

void handleNonRtData()
{
for (; fShmNonRtControl.isDataAvailableForReading();)
for (; fShmNonRtClientControl.isDataAvailableForReading();)
{
const PluginBridgeNonRtClientOpcode opcode(fShmNonRtControl.readOpcode());
const PluginBridgeNonRtClientOpcode opcode(fShmNonRtClientControl.readOpcode());
CarlaPlugin* const plugin(pData->plugins[0].plugin);

#ifdef DEBUG
@@ -414,14 +512,14 @@ public:
break;

case kPluginBridgeNonRtClientSetBufferSize: {
const uint32_t bufferSize(fShmNonRtControl.readUInt());
const uint32_t bufferSize(fShmNonRtClientControl.readUInt());
pData->bufferSize = bufferSize;
bufferSizeChanged(bufferSize);
break;
}

case kPluginBridgeNonRtClientSetSampleRate: {
const double sampleRate(fShmNonRtControl.readDouble());
const double sampleRate(fShmNonRtClientControl.readDouble());
pData->sampleRate = sampleRate;
sampleRateChanged(sampleRate);
break;
@@ -438,8 +536,8 @@ public:
break;

case kPluginBridgeNonRtClientSetParameterValue: {
const uint32_t index(fShmNonRtControl.readUInt());
const float value(fShmNonRtControl.readFloat());
const uint32_t index(fShmNonRtClientControl.readUInt());
const float value(fShmNonRtClientControl.readFloat());

if (plugin != nullptr && plugin->isEnabled())
plugin->setParameterValue(index, value, false, false, false);
@@ -447,8 +545,8 @@ public:
}

case kPluginBridgeNonRtClientSetParameterMidiChannel: {
const uint32_t index(fShmNonRtControl.readUInt());
const uint8_t channel(fShmNonRtControl.readByte());
const uint32_t index(fShmNonRtClientControl.readUInt());
const uint8_t channel(fShmNonRtClientControl.readByte());

if (plugin != nullptr && plugin->isEnabled())
plugin->setParameterMidiChannel(index, channel, false, false);
@@ -456,8 +554,8 @@ public:
}

case kPluginBridgeNonRtClientSetParameterMidiCC: {
const uint32_t index(fShmNonRtControl.readUInt());
const int16_t cc(fShmNonRtControl.readShort());
const uint32_t index(fShmNonRtClientControl.readUInt());
const int16_t cc(fShmNonRtClientControl.readShort());

if (plugin != nullptr && plugin->isEnabled())
plugin->setParameterMidiCC(index, cc, false, false);
@@ -465,7 +563,7 @@ public:
}

case kPluginBridgeNonRtClientSetProgram: {
const int32_t index(fShmNonRtControl.readInt());
const int32_t index(fShmNonRtClientControl.readInt());

if (plugin != nullptr && plugin->isEnabled())
plugin->setProgram(index, false, false, false);
@@ -473,7 +571,7 @@ public:
}

case kPluginBridgeNonRtClientSetMidiProgram: {
const int32_t index(fShmNonRtControl.readInt());
const int32_t index(fShmNonRtClientControl.readInt());

if (plugin != nullptr && plugin->isEnabled())
plugin->setMidiProgram(index, false, false, false);
@@ -482,22 +580,22 @@ public:

case kPluginBridgeNonRtClientSetCustomData: {
// type
const uint32_t typeSize(fShmNonRtControl.readUInt());
const uint32_t typeSize(fShmNonRtClientControl.readUInt());
char typeStr[typeSize+1];
carla_zeroChar(typeStr, typeSize+1);
fShmNonRtControl.readCustomData(typeStr, typeSize);
fShmNonRtClientControl.readCustomData(typeStr, typeSize);

// key
const uint32_t keySize(fShmNonRtControl.readUInt());
const uint32_t keySize(fShmNonRtClientControl.readUInt());
char keyStr[keySize+1];
carla_zeroChar(keyStr, keySize+1);
fShmNonRtControl.readCustomData(keyStr, keySize);
fShmNonRtClientControl.readCustomData(keyStr, keySize);

// value
const uint32_t valueSize(fShmNonRtControl.readUInt());
const uint32_t valueSize(fShmNonRtClientControl.readUInt());
char valueStr[valueSize+1];
carla_zeroChar(valueStr, valueSize+1);
fShmNonRtControl.readCustomData(valueStr, valueSize);
fShmNonRtClientControl.readCustomData(valueStr, valueSize);

if (plugin != nullptr && plugin->isEnabled())
plugin->setCustomData(typeStr, keyStr, valueStr, true);
@@ -505,12 +603,12 @@ public:
}

case kPluginBridgeNonRtClientSetChunkDataFile: {
const uint32_t size(fShmNonRtControl.readUInt());
const uint32_t size(fShmNonRtClientControl.readUInt());
CARLA_SAFE_ASSERT_BREAK(size > 0);

char chunkFilePathTry[size+1];
carla_zeroChar(chunkFilePathTry, size+1);
fShmNonRtControl.readCustomData(chunkFilePathTry, size);
fShmNonRtClientControl.readCustomData(chunkFilePathTry, size);

CARLA_SAFE_ASSERT_BREAK(chunkFilePathTry[0] != '\0');
if (plugin == nullptr || ! plugin->isEnabled()) break;
@@ -536,7 +634,7 @@ public:
}

case kPluginBridgeNonRtClientSetCtrlChannel: {
const int16_t channel(fShmNonRtControl.readShort());
const int16_t channel(fShmNonRtClientControl.readShort());
CARLA_SAFE_ASSERT_BREAK(channel >= -1 && channel < MAX_MIDI_CHANNELS);

if (plugin != nullptr && plugin->isEnabled())
@@ -545,8 +643,8 @@ public:
}

case kPluginBridgeNonRtClientSetOption: {
const uint32_t option(fShmNonRtControl.readUInt());
const bool yesNo(fShmNonRtControl.readBool());
const uint32_t option(fShmNonRtClientControl.readUInt());
const bool yesNo(fShmNonRtClientControl.readBool());

if (plugin != nullptr && plugin->isEnabled())
plugin->setOption(option, yesNo, false);
@@ -578,7 +676,7 @@ public:

filePath += CARLA_OS_SEP_STR;
filePath += ".CarlaChunk_";
filePath += fShmNonRtControl.filename.buffer() + 24;
filePath += fShmNonRtClientControl.filename.buffer() + 24;

if (File(filePath).replaceWithText(dataBase64.buffer()))
oscSend_bridge_set_chunk_data_file(filePath.toRawUTF8());
@@ -600,8 +698,8 @@ public:
break;

case kPluginBridgeNonRtClientUiParameterChange: {
const uint32_t index(fShmNonRtControl.readUInt());
const float value(fShmNonRtControl.readFloat());
const uint32_t index(fShmNonRtClientControl.readUInt());
const float value(fShmNonRtClientControl.readFloat());

if (plugin != nullptr && plugin->isEnabled())
plugin->uiParameterChange(index, value);
@@ -609,7 +707,7 @@ public:
}

case kPluginBridgeNonRtClientUiProgramChange: {
const uint32_t index(fShmNonRtControl.readUInt());
const uint32_t index(fShmNonRtClientControl.readUInt());

if (plugin != nullptr && plugin->isEnabled())
plugin->uiProgramChange(index);
@@ -617,7 +715,7 @@ public:
}

case kPluginBridgeNonRtClientUiMidiProgramChange: {
const uint32_t index(fShmNonRtControl.readUInt());
const uint32_t index(fShmNonRtClientControl.readUInt());

if (plugin != nullptr && plugin->isEnabled())
plugin->uiMidiProgramChange(index);
@@ -625,9 +723,9 @@ public:
}

case kPluginBridgeNonRtClientUiNoteOn: {
const uint8_t chnl(fShmNonRtControl.readByte());
const uint8_t note(fShmNonRtControl.readByte());
const uint8_t velo(fShmNonRtControl.readByte());
const uint8_t chnl(fShmNonRtClientControl.readByte());
const uint8_t note(fShmNonRtClientControl.readByte());
const uint8_t velo(fShmNonRtClientControl.readByte());

if (plugin != nullptr && plugin->isEnabled())
plugin->uiNoteOn(chnl, note, velo);
@@ -635,8 +733,8 @@ public:
}

case kPluginBridgeNonRtClientUiNoteOff: {
const uint8_t chnl(fShmNonRtControl.readByte());
const uint8_t note(fShmNonRtControl.readByte());
const uint8_t chnl(fShmNonRtClientControl.readByte());
const uint8_t note(fShmNonRtClientControl.readByte());

if (plugin != nullptr && plugin->isEnabled())
plugin->uiNoteOff(chnl, note);
@@ -658,18 +756,18 @@ protected:
{
for (; ! shouldThreadExit();)
{
if (! jackbridge_sem_timedwait(&fShmRtControl.data->sem.server, 5))
if (! fShmRtClientControl.waitForServer(5))
{
if (errno == ETIMEDOUT)
{
signalThreadShouldExit();
break;
}
carla_stderr2("Bridge timed-out, final post...");
fShmRtClientControl.postClient();
carla_stderr2("Bridge timed-out, done.");
signalThreadShouldExit();
break;
}

for (; fShmRtControl.isDataAvailableForReading();)
for (; fShmRtClientControl.isDataAvailableForReading();)
{
const PluginBridgeRtClientOpcode opcode(fShmRtControl.readOpcode());
const PluginBridgeRtClientOpcode opcode(fShmRtClientControl.readOpcode());
CarlaPlugin* const plugin(pData->plugins[0].plugin);

#ifdef DEBUG
@@ -684,24 +782,24 @@ protected:
break;

case kPluginBridgeRtClientSetAudioPool: {
const uint64_t poolSize(fShmRtControl.readULong());
const uint64_t poolSize(fShmRtClientControl.readULong());
CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
fShmAudioPool.data = (float*)jackbridge_shm_map(fShmAudioPool.shm, static_cast<size_t>(poolSize));
break;
}

case kPluginBridgeRtClientSetCVPool: {
const uint64_t poolSize(fShmRtControl.readULong());
const uint64_t poolSize(fShmRtClientControl.readULong());
CARLA_SAFE_ASSERT_BREAK(poolSize > 0);
//fShmCVPool.data = (float*)jackbridge_shm_map(fShmCVPool.shm, static_cast<size_t>(poolSize));
break;
}

case kPluginBridgeRtClientControlEventParameter: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t channel(fShmRtControl.readByte());
const uint16_t param(fShmRtControl.readUShort());
const float value(fShmRtControl.readFloat());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t channel(fShmRtClientControl.readByte());
const uint16_t param(fShmRtClientControl.readUShort());
const float value(fShmRtClientControl.readFloat());

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -716,9 +814,9 @@ protected:
}

case kPluginBridgeRtClientControlEventMidiBank: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t channel(fShmRtControl.readByte());
const uint16_t index(fShmRtControl.readUShort());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t channel(fShmRtClientControl.readByte());
const uint16_t index(fShmRtClientControl.readUShort());

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -733,9 +831,9 @@ protected:
}

case kPluginBridgeRtClientControlEventMidiProgram: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t channel(fShmRtControl.readByte());
const uint16_t index(fShmRtControl.readUShort());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t channel(fShmRtClientControl.readByte());
const uint16_t index(fShmRtClientControl.readUShort());

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -750,8 +848,8 @@ protected:
}

case kPluginBridgeRtClientControlEventAllSoundOff: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t channel(fShmRtControl.readByte());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t channel(fShmRtClientControl.readByte());

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -765,8 +863,8 @@ protected:
}

case kPluginBridgeRtClientControlEventAllNotesOff: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t channel(fShmRtControl.readByte());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t channel(fShmRtClientControl.readByte());

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -780,15 +878,15 @@ protected:
}

case kPluginBridgeRtClientMidiEvent: {
const uint32_t time(fShmRtControl.readUInt());
const uint8_t port(fShmRtControl.readByte());
const uint8_t size(fShmRtControl.readByte());
const uint32_t time(fShmRtClientControl.readUInt());
const uint8_t port(fShmRtClientControl.readByte());
const uint8_t size(fShmRtClientControl.readByte());
CARLA_SAFE_ASSERT_BREAK(size > 0);

uint8_t data[size];

for (uint8_t i=0; i<size; ++i)
data[i] = fShmRtControl.readByte();
data[i] = fShmRtClientControl.readByte();

if (EngineEvent* const event = getNextFreeInputEvent())
{
@@ -825,7 +923,7 @@ protected:

if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(false))
{
const BridgeTimeInfo& bridgeTimeInfo(fShmRtControl.data->timeInfo);
const BridgeTimeInfo& bridgeTimeInfo(fShmRtClientControl.data->timeInfo);

const uint32_t audioInCount(plugin->getAudioInCount());
const uint32_t audioOutCount(plugin->getAudioOutCount());
@@ -888,8 +986,8 @@ protected:
}
}

if (! jackbridge_sem_post(&fShmRtControl.data->sem.client))
carla_stderr2("Could not post to rt semaphore");
if (! fShmRtClientControl.postClient())
carla_stderr2("Could not post to client rt semaphore");
}

fIsRunning = false;
@@ -912,10 +1010,10 @@ protected:
// -------------------------------------------------------------------

private:
BridgeAudioPool fShmAudioPool;
BridgeAudioPool fShmCVPool;
BridgeRtControl fShmRtControl;
BridgeNonRtControl fShmNonRtControl;
BridgeAudioPool fShmAudioPool;
BridgeRtClientControl fShmRtClientControl;
BridgeNonRtClientControl fShmNonRtClientControl;
BridgeNonRtServerControl fShmNonRtServerControl;

bool fIsRunning;
bool fIsOffline;
@@ -925,9 +1023,9 @@ private:

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

CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
{
return new CarlaEngineBridge(audioPoolBaseName, rtBaseName, nonRtBaseName);
return new CarlaEngineBridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);
}

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


+ 0
- 5
source/backend/engine/CarlaEngineOsc.cpp View File

@@ -18,11 +18,6 @@
#include "CarlaEngine.hpp"
#include "CarlaEngineOsc.hpp"
#include "CarlaPlugin.hpp"

#ifndef BUILD_BRIDGE
# include "CarlaBridgeUtils.hpp"
#endif

#include "CarlaMIDI.h"

#include <cctype>


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

@@ -32,29 +32,6 @@
#include <cmath>
#include <ctime>

#define CARLA_BRIDGE_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \
/* check argument count */ \
if (argc != argcToCompare) \
{ \
carla_stderr("BridgePlugin::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \
return 1; \
} \
if (argc > 0) \
{ \
/* check for nullness */ \
if (! (types && typesToCompare)) \
{ \
carla_stderr("BridgePlugin::%s() - argument types are null", __FUNCTION__); \
return 1; \
} \
/* check argument types */ \
if (std::strcmp(types, typesToCompare) != 0) \
{ \
carla_stderr("BridgePlugin::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \
return 1; \
} \
}

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

using juce::File;
@@ -63,56 +40,23 @@ using juce::StringArray;

CARLA_BACKEND_START_NAMESPACE

#if 0
// -------------------------------------------------------------------------------------------------------------------
// call carla_shm_create with for a XXXXXX temp filename

static shm_t shm_mkstemp(char* const fileBase)
{
CARLA_SAFE_ASSERT_RETURN(fileBase != nullptr, gNullCarlaShm);

const size_t fileBaseLen(std::strlen(fileBase));

CARLA_SAFE_ASSERT_RETURN(fileBaseLen > 6, gNullCarlaShm);
CARLA_SAFE_ASSERT_RETURN(std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") == 0, gNullCarlaShm);

static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
static const int charSetLen = static_cast<int>(std::strlen(charSet) - 1); // -1 to avoid trailing '\0'

// try until getting a valid shm or an error occurs
for (;;)
{
for (size_t c = fileBaseLen - 6; c < fileBaseLen; ++c)
fileBase[c] = charSet[std::rand() % charSetLen];

const shm_t shm = carla_shm_create(fileBase);

if (carla_is_shm_valid(shm))
return shm;
if (errno != EEXIST)
return gNullCarlaShm;
}
}

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

struct BridgeAudioPool {
CarlaString filename;
std::size_t size;
float* data;
size_t size;
shm_t shm;

BridgeAudioPool() noexcept
: filename(),
data(nullptr),
size(0)
size(0),
data(nullptr)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, shm(shm_t_INIT) {}
#else
{
carla_shm_init(shm);
shm = shm_t_INIT;
}
#endif

@@ -129,7 +73,10 @@ struct BridgeAudioPool {
filename.clear();

if (! carla_is_shm_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

if (data != nullptr)
{
@@ -139,14 +86,17 @@ struct BridgeAudioPool {

size = 0;
carla_shm_close(shm);
carla_shm_init(shm);
}

void resize(const uint32_t bufferSize, const uint32_t portCount) noexcept
void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept
{
CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm),);

if (data != nullptr)
carla_shm_unmap(shm, data);

size = portCount*bufferSize*sizeof(float);
size = (audioPortCount+cvPortCount)*bufferSize*sizeof(float);

if (size == 0)
size = sizeof(float);
@@ -159,23 +109,23 @@ struct BridgeAudioPool {

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

struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
CarlaString filename;
BridgeRtData* data;
BridgeRtClientData* data;
shm_t shm;

BridgeRtControl()
BridgeRtClientControl()
: filename(),
data(nullptr)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, shm(shm_t_INIT) {}
#else
{
carla_shm_init(shm);
shm = shm_t_INIT;
}
#endif

~BridgeRtControl() noexcept override
~BridgeRtClientControl() noexcept override
{
// should be cleared by now
CARLA_SAFE_ASSERT(data == nullptr);
@@ -188,7 +138,10 @@ struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
filename.clear();

if (! carla_is_shm_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

if (data != nullptr)
{
@@ -197,17 +150,18 @@ struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
}

carla_shm_close(shm);
carla_shm_init(shm);
}

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

if (carla_shm_map<BridgeRtData>(shm, data))
if (carla_shm_map<BridgeRtClientData>(shm, data))
{
carla_zeroStruct(data->sem);
carla_zeroStruct(data->timeInfo);
carla_zeroBytes(data->midiOut, kBridgeRtDataMidiOutSize);
carla_zeroBytes(data->midiOut, kBridgeRtClientDataMidiOutSize);
setRingBuffer(&data->ringBuffer, true);
return true;
}
@@ -225,7 +179,7 @@ struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
setRingBuffer(nullptr, false);
}

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

@@ -234,23 +188,23 @@ struct BridgeRtControl : public CarlaRingBuffer<StackBuffer> {
return jackbridge_sem_timedwait(&data->sem.client, secs);
}

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

CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtControl)
CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
};

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

struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
CarlaMutex mutex;
CarlaString filename;
BridgeNonRtData* data;
BridgeNonRtClientData* data;
shm_t shm;

BridgeNonRtControl() noexcept
BridgeNonRtClientControl() noexcept
: mutex(),
filename(),
data(nullptr)
@@ -258,11 +212,88 @@ struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
, shm(shm_t_INIT) {}
#else
{
shm = shm_t_INIT;
}
#endif

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

clear();
}

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

if (! carla_is_shm_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

if (data != nullptr)
{
carla_shm_unmap(shm, data);
data = nullptr;
}

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

CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl)
};

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

struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> {
CarlaString filename;
BridgeNonRtServerData* data;
shm_t shm;

BridgeNonRtServerControl() noexcept
: filename(),
data(nullptr)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, shm(shm_t_INIT) {}
#else
{
shm = shm_t_INIT;
}
#endif

~BridgeNonRtControl() noexcept override
~BridgeNonRtServerControl() noexcept override
{
// should be cleared by now
CARLA_SAFE_ASSERT(data == nullptr);
@@ -275,7 +306,10 @@ struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
filename.clear();

if (! carla_is_shm_valid(shm))
{
CARLA_SAFE_ASSERT(data == nullptr);
return;
}

if (data != nullptr)
{
@@ -284,13 +318,14 @@ struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
}

carla_shm_close(shm);
carla_shm_init(shm);
}

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

if (carla_shm_map<BridgeNonRtData>(shm, data))
if (carla_shm_map<BridgeNonRtServerData>(shm, data))
{
setRingBuffer(&data->ringBuffer, true);
return true;
@@ -309,12 +344,12 @@ struct BridgeNonRtControl : public CarlaRingBuffer<BigStackBuffer> {
setRingBuffer(nullptr, false);
}

void writeOpcode(const PluginBridgeNonRtOpcode opcode) noexcept
PluginBridgeNonRtClientOpcode readOpcode() noexcept
{
writeInt(static_cast<int32_t>(opcode));
return static_cast<PluginBridgeNonRtClientOpcode>(readUInt());
}

CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtControl)
CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl)
};

// -------------------------------------------------------------------------------------------------------------------
@@ -349,9 +384,9 @@ public:
fLastPongCounter(-1),
fBridgeBinary(),
fShmAudioPool(),
fShmCVPool(),
fShmRtControl(),
fShmNonRtControl(),
fShmRtClientControl(),
fShmNonRtClientControl(),
fShmNonRtServerControl(),
fInfo(),
fParams(nullptr),
leakDetector_BridgePlugin()
@@ -361,6 +396,7 @@ public:
pData->hints |= PLUGIN_IS_BRIDGE;
}

#if 0
~BridgePlugin() override
{
carla_debug("BridgePlugin::~BridgePlugin()");
@@ -410,6 +446,7 @@ public:

fInfo.chunk.clear();
}
#endif

// -------------------------------------------------------------------
// Information (base)
@@ -509,6 +546,7 @@ public:
std::strncpy(strBuf, fParams[parameterId].unit.buffer(), STR_MAX);
}

#if 0
// -------------------------------------------------------------------
// Set data (state)

@@ -750,6 +788,7 @@ public:

CarlaPlugin::idle();
}
#endif

// -------------------------------------------------------------------
// Plugin state
@@ -759,6 +798,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
carla_debug("BridgePlugin::reload() - start");

#if 0
const EngineProcessMode processMode(pData->engine->getProccessMode());

// Safely disable plugin for reload
@@ -881,6 +921,7 @@ public:

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);
#endif

carla_debug("BridgePlugin::reload() - end");
}
@@ -891,16 +932,16 @@ public:
void activate() noexcept override
{
{
const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

fShmNonRtControl.writeOpcode(kPluginBridgeNonRtActivate);
fShmNonRtControl.commitWrite();
fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientActivate);
fShmNonRtClientControl.commitWrite();
}

bool timedOut = true;

try {
timedOut = waitForServer(1);
timedOut = waitForClient(1);
} catch(...) {}

if (! timedOut)
@@ -910,16 +951,16 @@ public:
void deactivate() noexcept override
{
{
const CarlaMutexLocker _cml(fShmNonRtControl.mutex);
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

fShmNonRtControl.writeOpcode(kPluginBridgeNonRtDeactivate);
fShmNonRtControl.commitWrite();
fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientDeactivate);
fShmNonRtClientControl.commitWrite();
}

bool timedOut = true;

try {
timedOut = waitForServer(1);
timedOut = waitForClient(1);
} catch(...) {}

if (! timedOut)
@@ -951,6 +992,8 @@ public:
pData->needsReset = false;
}

(void)audioIn; (void)cvIn;
#if 0
// --------------------------------------------------------------------------------------------------------
// Event Input

@@ -1168,8 +1211,10 @@ public:
} // End of Event Input

processSingle(audioIn, audioOut, cvIn, cvOut, frames);
#endif
}

#if 0
bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames)
{
CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
@@ -1977,7 +2022,7 @@ public:
{
char tmpFileBase[64];

std::sprintf(tmpFileBase, "/carla-bridge_shm_rt_XXXXXX");
std::sprintf(tmpFileBase, "/carla-bridge_shm_rtC_XXXXXX");

fShmRtControl.shm = shm_mkstemp(tmpFileBase);

@@ -2031,7 +2076,7 @@ public:
{
char tmpFileBase[64];

std::sprintf(tmpFileBase, "/carla-bridge_shm_nonrt_XXXXXX");
std::sprintf(tmpFileBase, "/carla-bridge_shm_nonrtC_XXXXXX");

fShmNonRtControl.shm = shm_mkstemp(tmpFileBase);

@@ -2134,6 +2179,7 @@ public:

return true;
}
#endif

private:
const BinaryType fBinaryType;
@@ -2149,10 +2195,10 @@ private:

CarlaString fBridgeBinary;

BridgeAudioPool fShmAudioPool;
BridgeAudioPool fShmCVPool;
BridgeRtControl fShmRtControl;
BridgeNonRtControl fShmNonRtControl;
BridgeAudioPool fShmAudioPool;
BridgeRtClientControl fShmRtClientControl;
BridgeNonRtClientControl fShmNonRtClientControl;
BridgeNonRtServerControl fShmNonRtServerControl;

struct Info {
uint32_t aIns, aOuts;
@@ -2188,27 +2234,23 @@ private:

void resizeAudioAndCVPool(const uint32_t bufferSize)
{
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts);
fShmCVPool.resize(bufferSize, fInfo.cvIns+fInfo.cvOuts);
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);

fShmRtControl.writeOpcode(kPluginBridgeRtSetAudioPool);
fShmRtControl.writeLong(static_cast<int64_t>(fShmAudioPool.size));
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.size));

fShmRtControl.writeOpcode(kPluginBridgeRtSetCVPool);
fShmRtControl.writeLong(static_cast<int64_t>(fShmCVPool.size));
fShmRtClientControl.commitWrite();

fShmRtControl.commitWrite();

waitForServer();
waitForClient();
}

bool waitForServer(const uint secs = 5)
bool waitForClient(const uint secs = 5)
{
CARLA_SAFE_ASSERT_RETURN(! fTimedOut, false);

if (! fShmRtControl.waitForServer(secs))
if (! fShmRtClientControl.waitForClient(secs))
{
carla_stderr("waitForServer() timeout here");
carla_stderr("waitForClient() timeout here");
fTimedOut = true;
return false;
}
@@ -2218,7 +2260,6 @@ private:

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(BridgePlugin)
};
#endif

CARLA_BACKEND_END_NAMESPACE

@@ -2233,7 +2274,6 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P
carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")", init.engine, init.filename, init.name, init.label, BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);

#ifndef BUILD_BRIDGE
# if 0
if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
{
init.engine->setLastError("Bridge not possible, bridge-binary not found");
@@ -2242,6 +2282,7 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P

BridgePlugin* const plugin(new BridgePlugin(init.engine, init.id, btype, ptype));

# if 0
if (! plugin->init(init.filename, init.name, init.label, bridgeBinary))
{
init.engine->registerEnginePlugin(init.id, nullptr);
@@ -2252,6 +2293,9 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P
plugin->reload();

bool canRun = true;
# else
bool canRun = false;
# endif

if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
@@ -2279,12 +2323,6 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P
}

return plugin;
# else
init.engine->setLastError("Bridged plugins not working due to pending code rewrite.");
return nullptr;
// unused
(void)bridgeBinary; (void)btype; (void)ptype;
# endif
#else
init.engine->setLastError("Plugin bridge support not available");
return nullptr;


+ 22
- 17
source/bridges-plugin/CarlaBridgePlugin.cpp View File

@@ -169,7 +169,8 @@ static JUCEApplicationBase* juce_CreateApplication() { return new CarlaJuceApp()
class CarlaBridgePlugin
{
public:
CarlaBridgePlugin(const bool useBridge, const char* const clientName, const char* const audioPoolBaseName, const char* const rtBaseName, const char* const nonRtBaseName)
CarlaBridgePlugin(const bool useBridge, const char* const clientName, const char* const audioPoolBaseName,
const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName)
: fEngine(nullptr),
fProjFilename(),
fOscControlData(),
@@ -178,12 +179,12 @@ public:
leakDetector_CarlaBridgePlugin()
{
CARLA_ASSERT(clientName != nullptr && clientName[0] != '\0');
carla_debug("CarlaBridgePlugin::CarlaBridgePlugin(%s, \"%s\", %s, %s, %s)", bool2str(useBridge), clientName, audioPoolBaseName, rtBaseName, nonRtBaseName);
carla_debug("CarlaBridgePlugin::CarlaBridgePlugin(%s, \"%s\", %s, %s, %s, %s)", bool2str(useBridge), clientName, audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);

carla_set_engine_callback(callback, this);

if (useBridge)
carla_engine_init_bridge(audioPoolBaseName, rtBaseName, nonRtBaseName, clientName);
carla_engine_init_bridge(audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName, clientName);
else
carla_engine_init("JACK", clientName);

@@ -420,25 +421,29 @@ int main(int argc, char* argv[])
// ---------------------------------------------------------------------
// Setup bridge ids

char bridgeBaseAudioName[6+1];
char bridgeBaseControlName[6+1];
char bridgeBaseTimeName[6+1];
char audioPoolBaseName[6+1];
char rtClientBaseName[6+1];
char nonRtClientBaseName[6+1];
char nonRtServerBaseName[6+1];

if (useBridge)
{
CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*3, 1);
std::strncpy(bridgeBaseAudioName, shmIds, 6);
std::strncpy(bridgeBaseControlName, shmIds+6, 6);
std::strncpy(bridgeBaseTimeName, shmIds+12, 6);
bridgeBaseAudioName[6] = '\0';
bridgeBaseControlName[6] = '\0';
bridgeBaseTimeName[6] = '\0';
CARLA_SAFE_ASSERT_RETURN(std::strlen(shmIds) == 6*4, 1);
std::strncpy(audioPoolBaseName, shmIds+6*0, 6);
std::strncpy(rtClientBaseName, shmIds+6*1, 6);
std::strncpy(nonRtClientBaseName, shmIds+6*2, 6);
std::strncpy(nonRtServerBaseName, shmIds+6*3, 6);
audioPoolBaseName[6] = '\0';
rtClientBaseName[6] = '\0';
nonRtClientBaseName[6] = '\0';
nonRtServerBaseName[6] = '\0';
}
else
{
bridgeBaseAudioName[0] = '\0';
bridgeBaseControlName[0] = '\0';
bridgeBaseTimeName[0] = '\0';
audioPoolBaseName[0] = '\0';
rtClientBaseName[0] = '\0';
nonRtClientBaseName[0] = '\0';
nonRtServerBaseName[0] = '\0';
}

// ---------------------------------------------------------------------
@@ -466,7 +471,7 @@ int main(int argc, char* argv[])
// ---------------------------------------------------------------------
// Init plugin bridge

CarlaBridgePlugin bridge(useBridge, clientName, bridgeBaseAudioName, bridgeBaseControlName, bridgeBaseTimeName);
CarlaBridgePlugin bridge(useBridge, clientName, audioPoolBaseName, rtClientBaseName, nonRtClientBaseName, nonRtServerBaseName);

if (! bridge.isOk())
{


+ 2
- 2
source/utils/CarlaBridgeUtils.hpp View File

@@ -125,14 +125,14 @@ struct BridgeTimeInfo {

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

static const std::size_t kBridgeRtDataMidiOutSize = 512*4;
static const std::size_t kBridgeRtClientDataMidiOutSize = 512*4;

// Server => Client RT
struct BridgeRtClientData {
BridgeSemaphore sem;
BridgeTimeInfo timeInfo;
SmallStackBuffer ringBuffer;
uint8_t midiOut[kBridgeRtDataMidiOutSize];
uint8_t midiOut[kBridgeRtClientDataMidiOutSize];
};

// Server => Client Non-RT


+ 56
- 15
source/utils/CarlaShmUtils.hpp View File

@@ -22,12 +22,13 @@

#ifdef CARLA_OS_WIN
struct shm_t { HANDLE shm; HANDLE map; };
# define shm_t_INIT {nullptr, nullptr}
# define shm_t_INIT { nullptr, nullptr }
#else
# include <cerrno>
# include <fcntl.h>
# include <sys/mman.h>
struct shm_t { int fd; const char* filename; std::size_t size; };
# define shm_t_INIT {-1, nullptr}
# define shm_t_INIT { -1, nullptr, 0 }
#endif

// -----------------------------------------------------------------------
@@ -36,11 +37,7 @@ struct shm_t { int fd; const char* filename; std::size_t size; };
/*
* Null object returned when a shared memory operation fails.
*/
#ifdef CARLA_OS_WIN
static const shm_t gNullCarlaShm = { nullptr, nullptr };
#else
static const shm_t gNullCarlaShm = { -1, nullptr, 0 };
#endif
static const shm_t gNullCarlaShm = shm_t_INIT;

/*
* Check if a shared memory object is valid.
@@ -61,14 +58,7 @@ bool carla_is_shm_valid(const shm_t& shm) noexcept
static inline
void carla_shm_init(shm_t& shm) noexcept
{
#ifdef CARLA_OS_WIN
shm.shm = nullptr;
shm.map = nullptr;
#else
shm.fd = -1;
shm.filename = nullptr;
shm.size = 0;
#endif
shm = gNullCarlaShm;
}

/*
@@ -246,6 +236,57 @@ void carla_shm_unmap(shm_t& shm, void* const ptr) noexcept
} CARLA_SAFE_EXCEPTION("carla_shm_unmap");
}

// -----------------------------------------------------------------------
// advanced calls

/*
* Create and open a new shared memory object for a XXXXXX temp filename.
* Will keep trying until a free random filename is obtained.
*/
static inline
shm_t carla_shm_create_temp(char* const fileBase)
{
// check if the fileBase name is valid
CARLA_SAFE_ASSERT_RETURN(fileBase != nullptr, gNullCarlaShm);

const std::size_t fileBaseLen(std::strlen(fileBase));

CARLA_SAFE_ASSERT_RETURN(fileBaseLen > 6, gNullCarlaShm);
CARLA_SAFE_ASSERT_RETURN(std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") == 0, gNullCarlaShm);

// character set to use randomly
static const char charSet[] = "abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
static const int charSetLen = static_cast<int>(std::strlen(charSet) - 1); // -1 to avoid trailing '\0'

// try until getting a valid shm is obtained or an error occurs
for (;;)
{
// fill the XXXXXX characters randomly
for (std::size_t c = fileBaseLen - 6; c < fileBaseLen; ++c)
fileBase[c] = charSet[std::rand() % charSetLen];

// (try to) create new shm for this filename
const shm_t shm = carla_shm_create(fileBase);

// all ok!
if (carla_is_shm_valid(shm))
return shm;

// file already exists, keep trying
#ifdef CARLA_OS_WIN
// TODO
#else
if (errno == EEXIST)
continue;
#endif

// some unknown error occurred, return null
return gNullCarlaShm;
}
}

// -----------------------------------------------------------------------
// shared memory, templated calls



Loading…
Cancel
Save