Browse Source

Continue work for plugin bridges

tags/1.9.4
falkTX 12 years ago
parent
commit
5e64e56939
12 changed files with 480 additions and 441 deletions
  1. +1
    -0
      source/backend/engine/CarlaEngine.pro
  2. +148
    -86
      source/backend/engine/CarlaEngineBridge.cpp
  3. +1
    -0
      source/backend/engine/CarlaEngineJack.cpp
  4. +1
    -0
      source/backend/engine/distrho/DistrhoPluginInfo.h
  5. +239
    -144
      source/backend/plugin/BridgePlugin.cpp
  6. +2
    -0
      source/backend/plugin/CarlaPlugin.pro
  7. +1
    -1
      source/libs/distrho/DistrhoUIExternal.hpp
  8. +3
    -3
      source/libs/distrho/src/DistrhoPluginVST.cpp
  9. +2
    -0
      source/libs/jackbridge/JackBridge.hpp
  10. +31
    -9
      source/libs/jackbridge/JackBridge2.cpp
  11. +15
    -8
      source/libs/jackbridge/Makefile
  12. +36
    -190
      source/utils/CarlaBridgeUtils.hpp

+ 1
- 0
source/backend/engine/CarlaEngine.pro View File

@@ -78,6 +78,7 @@ HEADERS += \
../../includes/CarlaDefines.hpp \ ../../includes/CarlaDefines.hpp \
../../includes/CarlaMIDI.h \ ../../includes/CarlaMIDI.h \
../../utils/CarlaMutex.hpp \ ../../utils/CarlaMutex.hpp \
../../utils/CarlaRingBuffer.hpp \
../../utils/CarlaString.hpp \ ../../utils/CarlaString.hpp \
../../utils/CarlaThread.hpp \ ../../utils/CarlaThread.hpp \
../../utils/CarlaUtils.hpp \ ../../utils/CarlaUtils.hpp \


+ 148
- 86
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -37,6 +37,111 @@ CARLA_BACKEND_START_NAMESPACE


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


struct BridgeAudioPool {
CarlaString filename;
float* data;
shm_t shm;

BridgeAudioPool()
: data(nullptr)
{
carla_shm_init(shm);
}

~BridgeAudioPool()
{
// should be cleared by now
CARLA_ASSERT(data == nullptr);

clear();
}

bool attach()
{
#ifdef CARLA_OS_WIN
// TESTING!
shm = carla_shm_attach_linux((const char*)filename);
#else
shm = carla_shm_attach((const char*)filename);
#endif

return carla_is_shm_valid(shm);
}

void clear()
{
filename.clear();

data = nullptr;

if (carla_is_shm_valid(shm))
carla_shm_close(shm);
}
};

struct BridgeControl : public RingBufferControl {
CarlaString filename;
BridgeShmControl* data;
shm_t shm;

BridgeControl()
: RingBufferControl(nullptr),
data(nullptr)
{
carla_shm_init(shm);
}

~BridgeControl()
{
// should be cleared by now
CARLA_ASSERT(data == nullptr);

clear();
}

bool attach()
{
#ifdef CARLA_OS_WIN
// TESTING!
shm = carla_shm_attach_linux((const char*)filename);
#else
shm = carla_shm_attach((const char*)filename);
#endif

return carla_is_shm_valid(shm);
}

void clear()
{
filename.clear();

data = nullptr;

if (carla_is_shm_valid(shm))
carla_shm_close(shm);
}

bool mapData()
{
CARLA_ASSERT(data == nullptr);

if (carla_shm_map<BridgeShmControl>(shm, data))
{
setRingBuffer(&data->ringBuffer, false);
return true;
}

return false;
}

PluginBridgeOpcode readOpcode()
{
return static_cast<PluginBridgeOpcode>(readInt());
}
};

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

class CarlaEngineBridge : public CarlaEngine, class CarlaEngineBridge : public CarlaEngine,
public QThread public QThread
{ {
@@ -69,16 +174,8 @@ public:


// SHM Audio Pool // SHM Audio Pool
{ {
#ifdef CARLA_OS_WIN
// TESTING!
fShmAudioPool.shm = carla_shm_attach_linux((const char*)fShmAudioPool.filename);
#else
fShmAudioPool.shm = carla_shm_attach((const char*)fShmAudioPool.filename);
#endif

if (! carla_is_shm_valid(fShmAudioPool.shm))
if (! fShmAudioPool.attach())
{ {
_cleanup();
carla_stdout("Failed to open or create shared memory file #1"); carla_stdout("Failed to open or create shared memory file #1");
return false; return false;
} }
@@ -86,24 +183,20 @@ public:


// SHM Control // SHM Control
{ {
#ifdef CARLA_OS_WIN
// TESTING!
fShmControl.shm = carla_shm_attach_linux((const char*)fShmControl.filename);
#else
fShmControl.shm = carla_shm_attach((const char*)fShmControl.filename);
#endif

if (! carla_is_shm_valid(fShmControl.shm))
if (! fShmControl.attach())
{ {
_cleanup();
carla_stdout("Failed to open or create shared memory file #2"); carla_stdout("Failed to open or create shared memory file #2");
// clear
fShmAudioPool.clear();
return false; return false;
} }


if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
if (! fShmControl.mapData())
{ {
_cleanup();
carla_stdout("Failed to mmap shared memory file"); carla_stdout("Failed to mmap shared memory file");
// clear
fShmControl.clear();
fShmAudioPool.clear();
return false; return false;
} }
} }
@@ -111,14 +204,14 @@ public:
// Read values from memory // Read values from memory
PluginBridgeOpcode opcode; PluginBridgeOpcode opcode;


opcode = rdwr_readOpcode(&fShmControl.data->ringBuffer);
CARLA_ASSERT(opcode == kPluginBridgeOpcodeSetBufferSize);
fBufferSize = rdwr_readInt(&fShmControl.data->ringBuffer);
opcode = fShmControl.readOpcode();
CARLA_ASSERT_INT(opcode == kPluginBridgeOpcodeSetBufferSize, opcode);
fBufferSize = fShmControl.readInt();
carla_stderr("BufferSize: %i", fBufferSize); carla_stderr("BufferSize: %i", fBufferSize);


opcode = rdwr_readOpcode(&fShmControl.data->ringBuffer);
CARLA_ASSERT(opcode == kPluginBridgeOpcodeSetSampleRate);
fSampleRate = rdwr_readFloat(&fShmControl.data->ringBuffer);
opcode = fShmControl.readOpcode();
CARLA_ASSERT_INT(opcode == kPluginBridgeOpcodeSetSampleRate, opcode);
fSampleRate = fShmControl.readFloat();
carla_stderr("SampleRate: %f", fSampleRate); carla_stderr("SampleRate: %f", fSampleRate);


fQuitNow = false; fQuitNow = false;
@@ -137,7 +230,8 @@ public:
fQuitNow = true; fQuitNow = true;
QThread::wait(); QThread::wait();


_cleanup();
fShmControl.clear();
fShmAudioPool.clear();


return true; return true;
} }
@@ -163,21 +257,29 @@ public:
void run() void run()
{ {
// TODO - set RT permissions // TODO - set RT permissions
carla_debug("CarlaEngineBridge::run()");


while (! fQuitNow) while (! fQuitNow)
{ {
carla_debug("CarlaEngineBridge::run() - try wait");

if (! jackbridge_sem_timedwait(&fShmControl.data->runServer, 5)) if (! jackbridge_sem_timedwait(&fShmControl.data->runServer, 5))
{ {
if (errno != ETIMEDOUT)
continue;

fQuitNow = true;
return;
if (errno == ETIMEDOUT)
{
fIsRunning = false;
fQuitNow = true;
return;
}
} }


while (rdwr_dataAvailable(&fShmControl.data->ringBuffer))
carla_debug("CarlaEngineBridge::run() - connected");

while (fShmControl.dataAvailable())
{ {
const PluginBridgeOpcode opcode(rdwr_readOpcode(&fShmControl.data->ringBuffer));
const PluginBridgeOpcode opcode(fShmControl.readOpcode());

carla_debug("CarlaEngineBridge::run() - got opcode: %s", PluginBridgeOpcode2str(opcode));


switch (opcode) switch (opcode)
{ {
@@ -186,29 +288,29 @@ public:


case kPluginBridgeOpcodeSetAudioPool: case kPluginBridgeOpcodeSetAudioPool:
{ {
const int poolSize(rdwr_readInt(&fShmControl.data->ringBuffer));
const long poolSize(fShmControl.readLong());
fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, poolSize); fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, poolSize);
break; break;
} }


case kPluginBridgeOpcodeSetBufferSize: case kPluginBridgeOpcodeSetBufferSize:
{ {
const int bufferSize(rdwr_readInt(&fShmControl.data->ringBuffer));
const int bufferSize(fShmControl.readInt());
bufferSizeChanged(bufferSize); bufferSizeChanged(bufferSize);
break; break;
} }


case kPluginBridgeOpcodeSetSampleRate: case kPluginBridgeOpcodeSetSampleRate:
{ {
const float sampleRate(rdwr_readFloat(&fShmControl.data->ringBuffer));
const float sampleRate(fShmControl.readFloat());
sampleRateChanged(sampleRate); sampleRateChanged(sampleRate);
break; break;
} }


case kPluginBridgeOpcodeSetParameter: case kPluginBridgeOpcodeSetParameter:
{ {
const int index(rdwr_readInt(&fShmControl.data->ringBuffer));
const float value(rdwr_readFloat(&fShmControl.data->ringBuffer));
const int index(fShmControl.readInt());
const float value(fShmControl.readFloat());


CarlaPlugin* const plugin(getPluginUnchecked(0)); CarlaPlugin* const plugin(getPluginUnchecked(0));


@@ -223,7 +325,7 @@ public:


case kPluginBridgeOpcodeSetProgram: case kPluginBridgeOpcodeSetProgram:
{ {
const int index(rdwr_readInt(&fShmControl.data->ringBuffer));
const int index(fShmControl.readInt());


CarlaPlugin* const plugin(getPluginUnchecked(0)); CarlaPlugin* const plugin(getPluginUnchecked(0));


@@ -238,7 +340,7 @@ public:


case kPluginBridgeOpcodeSetMidiProgram: case kPluginBridgeOpcodeSetMidiProgram:
{ {
const int index(rdwr_readInt(&fShmControl.data->ringBuffer));
const int index(fShmControl.readInt());


CarlaPlugin* const plugin(getPluginUnchecked(0)); CarlaPlugin* const plugin(getPluginUnchecked(0));


@@ -254,13 +356,13 @@ public:
case kPluginBridgeOpcodeMidiEvent: case kPluginBridgeOpcodeMidiEvent:
{ {
uint8_t data[4] = { 0 }; uint8_t data[4] = { 0 };
const long time(rdwr_readLong(&fShmControl.data->ringBuffer));
const int dataSize(rdwr_readInt(&fShmControl.data->ringBuffer));
const long time(fShmControl.readLong());
const int dataSize(fShmControl.readInt());


CARLA_ASSERT_INT(dataSize >= 1 && dataSize <= 4, dataSize); CARLA_ASSERT_INT(dataSize >= 1 && dataSize <= 4, dataSize);


for (int i=0; i < dataSize && i < 4; ++i) for (int i=0; i < dataSize && i < 4; ++i)
data[i] = rdwr_readChar(&fShmControl.data->ringBuffer);
data[i] = fShmControl.readChar();


CARLA_ASSERT(kData->bufEvents.in != nullptr); CARLA_ASSERT(kData->bufEvents.in != nullptr);


@@ -311,52 +413,12 @@ public:
} }


private: private:
struct BridgeAudioPool {
CarlaString filename;
float* data;
shm_t shm;

BridgeAudioPool()
: data(nullptr)
{
carla_shm_init(shm);
}
} fShmAudioPool;

struct BridgeControl {
CarlaString filename;
BridgeShmControl* data;
shm_t shm;

BridgeControl()
: data(nullptr)
{
carla_shm_init(shm);
}

} fShmControl;
BridgeAudioPool fShmAudioPool;
BridgeControl fShmControl;


bool fIsRunning; bool fIsRunning;
bool fQuitNow; bool fQuitNow;


void _cleanup()
{
if (fShmAudioPool.filename.isNotEmpty())
fShmAudioPool.filename.clear();

if (fShmControl.filename.isNotEmpty())
fShmControl.filename.clear();

fShmAudioPool.data = nullptr;
fShmControl.data = nullptr;

if (carla_is_shm_valid(fShmAudioPool.shm))
carla_shm_close(fShmAudioPool.shm);

if (carla_is_shm_valid(fShmControl.shm))
carla_shm_close(fShmControl.shm);
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineBridge)
}; };




+ 1
- 0
source/backend/engine/CarlaEngineJack.cpp View File

@@ -2231,6 +2231,7 @@ private:


CarlaEngine* CarlaEngine::newJack() CarlaEngine* CarlaEngine::newJack()
{ {
carla_debug("CarlaEngine::newJack()");
return new CarlaEngineJack(); return new CarlaEngineJack();
} }




+ 1
- 0
source/backend/engine/distrho/DistrhoPluginInfo.h View File

@@ -29,6 +29,7 @@
#define DISTRHO_PLUGIN_WANT_LATENCY 0 #define DISTRHO_PLUGIN_WANT_LATENCY 0
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 #define DISTRHO_PLUGIN_WANT_PROGRAMS 1
#define DISTRHO_PLUGIN_WANT_STATE 1 #define DISTRHO_PLUGIN_WANT_STATE 1
#define DISTRHO_PLUGIN_WANT_TIMEPOS 1


#define DISTRHO_PLUGIN_URI "http://kxstudio.sf.net/carla" #define DISTRHO_PLUGIN_URI "http://kxstudio.sf.net/carla"




+ 239
- 144
source/backend/plugin/BridgePlugin.cpp View File

@@ -71,26 +71,26 @@ shm_t shm_mkstemp(char* const fileBase)
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789"; "0123456789";


const int size = (fileBase != nullptr) ? std::strlen(fileBase) : 0;
const size_t fileBaseLen((fileBase != nullptr) ? std::strlen(fileBase) : 0);


shm_t shm;
carla_shm_init(shm);
shm_t fakeShm;
carla_shm_init(fakeShm);


if (size < 6)
if (fileBaseLen < 6)
{ {
errno = EINVAL; errno = EINVAL;
return shm;
return fakeShm;
} }


if (std::strcmp(fileBase + size - 6, "XXXXXX") != 0)
if (std::strcmp(fileBase + fileBaseLen - 6, "XXXXXX") != 0)
{ {
errno = EINVAL; errno = EINVAL;
return shm;
return fakeShm;
} }


while (true)
for (;;)
{ {
for (int c = size - 6; c < size; ++c)
for (size_t c = fileBaseLen - 6; c < fileBaseLen; ++c)
{ {
// Note the -1 to avoid the trailing '\0' in charSet. // Note the -1 to avoid the trailing '\0' in charSet.
fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)]; fileBase[c] = charSet[std::rand() % (sizeof(charSet) - 1)];
@@ -105,6 +105,139 @@ shm_t shm_mkstemp(char* const fileBase)


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


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

BridgeAudioPool()
: data(nullptr),
size(0)
{
carla_shm_init(shm);
}

~BridgeAudioPool()
{
// should be cleared by now
CARLA_ASSERT(data == nullptr);

clear();
}

void clear()
{
filename.clear();

if (! carla_is_shm_valid(shm))
return;

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

size = 0;

carla_shm_close(shm);
}

void resize(const uint32_t bufferSize, const uint32_t portCount)
{
if (data != nullptr)
carla_shm_unmap(shm, data, size);

size = portCount*bufferSize*sizeof(float);

if (size == 0)
size = sizeof(float);

data = (float*)carla_shm_map(shm, size);
}
};

struct BridgeControl : public RingBufferControl {
CarlaString filename;
BridgeShmControl* data;
shm_t shm;

BridgeControl()
: RingBufferControl(nullptr),
data(nullptr)
{
carla_shm_init(shm);
}

~BridgeControl()
{
// should be cleared by now
CARLA_ASSERT(data == nullptr);

clear();
}

void clear()
{
filename.clear();

if (! carla_is_shm_valid(shm))
return;

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

carla_shm_close(shm);
}

bool mapData()
{
CARLA_ASSERT(data == nullptr);

if (carla_shm_map<BridgeShmControl>(shm, data))
{
setRingBuffer(&data->ringBuffer, true);
return true;
}

return false;
}

void unmapData()
{
CARLA_ASSERT(data != nullptr);

if (data == nullptr)
return;

carla_shm_unmap(shm, data, sizeof(BridgeShmControl));
data = nullptr;

setRingBuffer(nullptr, false);
}

bool waitForServer()
{
CARLA_ASSERT(data != nullptr);

if (data == nullptr)
return false;

jackbridge_sem_post(&data->runServer);

return jackbridge_sem_timedwait(&data->runClient, 5);
}

void writeOpcode(const PluginBridgeOpcode opcode)
{
writeInt(static_cast<int>(opcode));
}
};

struct BridgeParamInfo { struct BridgeParamInfo {
float value; float value;
CarlaString name; CarlaString name;
@@ -116,6 +249,8 @@ struct BridgeParamInfo {
CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(BridgeParamInfo) CARLA_DECLARE_NON_COPY_STRUCT_WITH_LEAK_DETECTOR(BridgeParamInfo)
}; };


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

class BridgePlugin : public CarlaPlugin class BridgePlugin : public CarlaPlugin
{ {
public: public:
@@ -126,6 +261,7 @@ public:
fInitiated(false), fInitiated(false),
fInitError(false), fInitError(false),
fSaved(false), fSaved(false),
fNeedsSemDestroy(false),
fParams(nullptr) fParams(nullptr)
{ {
carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype)); carla_debug("BridgePlugin::BridgePlugin(%p, %i, %s, %s)", engine, id, BinaryType2Str(btype), PluginType2Str(ptype));
@@ -153,9 +289,9 @@ public:


if (kData->osc.thread.isRunning()) if (kData->osc.thread.isRunning())
{ {
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeQuit);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
waitForServer();
fShmControl.writeOpcode(kPluginBridgeOpcodeQuit);
fShmControl.commitWrite();
fShmControl.waitForServer();
} }


if (kData->osc.data.target != nullptr) if (kData->osc.data.target != nullptr)
@@ -173,7 +309,15 @@ public:
kData->osc.thread.terminate(); kData->osc.thread.terminate();
} }


cleanup();
if (fNeedsSemDestroy)
{
jackbridge_sem_destroy(&fShmControl.data->runServer);
jackbridge_sem_destroy(&fShmControl.data->runClient);
}

fShmAudioPool.clear();
fShmControl.clear();

clearBuffers(); clearBuffers();


//info.chunk.clear(); //info.chunk.clear();
@@ -336,13 +480,13 @@ public:
if (doLock) if (doLock)
kData->singleMutex.lock(); kData->singleMutex.lock();


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetParameter);
rdwr_writeInt(&fShmControl.data->ringBuffer, parameterId);
rdwr_writeFloat(&fShmControl.data->ringBuffer, value);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
fShmControl.writeInt(parameterId);
fShmControl.writeFloat(value);


if (doLock) if (doLock)
{ {
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.commitWrite();
kData->singleMutex.unlock(); kData->singleMutex.unlock();
} }


@@ -363,12 +507,12 @@ public:
if (doLock) if (doLock)
kData->singleMutex.lock(); kData->singleMutex.lock();


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetProgram);
rdwr_writeInt(&fShmControl.data->ringBuffer, index);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetProgram);
fShmControl.writeInt(index);


if (doLock) if (doLock)
{ {
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.commitWrite();
kData->singleMutex.unlock(); kData->singleMutex.unlock();
} }


@@ -389,12 +533,12 @@ public:
if (doLock) if (doLock)
kData->singleMutex.lock(); kData->singleMutex.lock();


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetMidiProgram);
rdwr_writeInt(&fShmControl.data->ringBuffer, index);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetMidiProgram);
fShmControl.writeInt(index);


if (doLock) if (doLock)
{ {
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.commitWrite();
kData->singleMutex.unlock(); kData->singleMutex.unlock();
} }


@@ -597,20 +741,20 @@ public:
void activate() override void activate() override
{ {
// already locked before // already locked before
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetParameter);
rdwr_writeInt(&fShmControl.data->ringBuffer, PARAMETER_ACTIVE);
rdwr_writeFloat(&fShmControl.data->ringBuffer, 1.0f);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
fShmControl.writeInt(PARAMETER_ACTIVE);
fShmControl.writeFloat(1.0f);
fShmControl.commitWrite();
waitForServer(); waitForServer();
} }


void deactivate() override void deactivate() override
{ {
// already locked before // already locked before
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetParameter);
rdwr_writeInt(&fShmControl.data->ringBuffer, PARAMETER_ACTIVE);
rdwr_writeFloat(&fShmControl.data->ringBuffer, 0.0f);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetParameter);
fShmControl.writeInt(PARAMETER_ACTIVE);
fShmControl.writeFloat(0.0f);
fShmControl.commitWrite();
waitForServer(); waitForServer();
} }


@@ -662,12 +806,12 @@ public:
data2 = note.note; data2 = note.note;
data3 = note.velo; data3 = note.velo;


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeMidiEvent);
rdwr_writeLong(&fShmControl.data->ringBuffer, 0);
rdwr_writeInt(&fShmControl.data->ringBuffer, 3);
rdwr_writeChar(&fShmControl.data->ringBuffer, data1);
rdwr_writeChar(&fShmControl.data->ringBuffer, data2);
rdwr_writeChar(&fShmControl.data->ringBuffer, data3);
fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
fShmControl.writeLong(0);
fShmControl.writeInt(3);
fShmControl.writeChar(data1);
fShmControl.writeChar(data2);
fShmControl.writeChar(data3);
} }


kData->extNotes.mutex.unlock(); kData->extNotes.mutex.unlock();
@@ -785,12 +929,12 @@ public:


if ((fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F) if ((fOptions & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param <= 0x5F)
{ {
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeMidiEvent);
rdwr_writeLong(&fShmControl.data->ringBuffer, event.time);
rdwr_writeInt(&fShmControl.data->ringBuffer, 3);
rdwr_writeChar(&fShmControl.data->ringBuffer, MIDI_STATUS_CONTROL_CHANGE + event.channel);
rdwr_writeChar(&fShmControl.data->ringBuffer, ctrlEvent.param);
rdwr_writeChar(&fShmControl.data->ringBuffer, ctrlEvent.value*127.0f);
fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
fShmControl.writeLong(event.time);
fShmControl.writeInt(3);
fShmControl.writeChar(MIDI_STATUS_CONTROL_CHANGE + event.channel);
fShmControl.writeChar(ctrlEvent.param);
fShmControl.writeChar(ctrlEvent.value*127.0f);
} }


break; break;
@@ -874,12 +1018,12 @@ public:
data[2] = midiEvent.data[2]; data[2] = midiEvent.data[2];
data[3] = midiEvent.data[3]; data[3] = midiEvent.data[3];


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeMidiEvent);
rdwr_writeLong(&fShmControl.data->ringBuffer, event.time);
rdwr_writeInt(&fShmControl.data->ringBuffer, midiEvent.size);
fShmControl.writeOpcode(kPluginBridgeOpcodeMidiEvent);
fShmControl.writeLong(event.time);
fShmControl.writeInt(midiEvent.size);


for (uint8_t j=0; j < midiEvent.size && j < 4; ++j) for (uint8_t j=0; j < midiEvent.size && j < 4; ++j)
rdwr_writeChar(&fShmControl.data->ringBuffer, data[j]);
fShmControl.writeChar(data[j]);


if (status == MIDI_STATUS_NOTE_ON) if (status == MIDI_STATUS_NOTE_ON)
postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]); postponeRtEvent(kPluginPostRtEventNoteOn, channel, midiEvent.data[1], midiEvent.data[2]);
@@ -944,8 +1088,8 @@ public:
// -------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------
// Run plugin // Run plugin


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeProcess);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeProcess);
fShmControl.commitWrite();


if (! waitForServer()) if (! waitForServer())
{ {
@@ -1030,17 +1174,17 @@ public:
{ {
resizeAudioPool(newBufferSize); resizeAudioPool(newBufferSize);


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetBufferSize);
rdwr_writeInt(&fShmControl.data->ringBuffer, newBufferSize);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetBufferSize);
fShmControl.writeInt(newBufferSize);
fShmControl.commitWrite();


} }


void sampleRateChanged(const double newSampleRate) override void sampleRateChanged(const double newSampleRate) override
{ {
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetSampleRate);
rdwr_writeFloat(&fShmControl.data->ringBuffer, newSampleRate);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetSampleRate);
fShmControl.writeFloat(newSampleRate);
fShmControl.commitWrite();
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -1569,7 +1713,6 @@ public:


if (! carla_is_shm_valid(fShmAudioPool.shm)) if (! carla_is_shm_valid(fShmAudioPool.shm))
{ {
//_cleanup();
carla_stdout("Failed to open or create shared memory file #1"); carla_stdout("Failed to open or create shared memory file #1");
return false; return false;
} }
@@ -1588,48 +1731,57 @@ public:


if (! carla_is_shm_valid(fShmControl.shm)) if (! carla_is_shm_valid(fShmControl.shm))
{ {
//_cleanup();
carla_stdout("Failed to open or create shared memory file #2"); carla_stdout("Failed to open or create shared memory file #2");
// clear
carla_shm_close(fShmAudioPool.shm);
return false; return false;
} }


fShmControl.filename = tmpFileBase; fShmControl.filename = tmpFileBase;


if (! carla_shm_map<BridgeShmControl>(fShmControl.shm, fShmControl.data))
if (! fShmControl.mapData())
{ {
//_cleanup();
carla_stdout("Failed to mmap shared memory file"); carla_stdout("Failed to mmap shared memory file");
// clear
carla_shm_close(fShmControl.shm);
carla_shm_close(fShmAudioPool.shm);
return false; return false;
} }


CARLA_ASSERT(fShmControl.data != nullptr); CARLA_ASSERT(fShmControl.data != nullptr);


std::memset(fShmControl.data, 0, sizeof(BridgeShmControl));
std::strcpy(fShmControl.data->ringBuffer.buf, "This thing is actually working!!!!");

if (sem_init(&fShmControl.data->runServer, 1, 0) != 0)
if (! jackbridge_sem_init(&fShmControl.data->runServer))
{ {
//_cleanup();
carla_stdout("Failed to initialize shared memory semaphore #1"); carla_stdout("Failed to initialize shared memory semaphore #1");
// clear
fShmControl.unmapData();
carla_shm_close(fShmControl.shm);
carla_shm_close(fShmAudioPool.shm);
return false; return false;
} }


if (sem_init(&fShmControl.data->runClient, 1, 0) != 0)
if (! jackbridge_sem_init(&fShmControl.data->runClient))
{ {
//_cleanup();
carla_stdout("Failed to initialize shared memory semaphore #2"); carla_stdout("Failed to initialize shared memory semaphore #2");
// clear
jackbridge_sem_destroy(&fShmControl.data->runServer);
fShmControl.unmapData();
carla_shm_close(fShmControl.shm);
carla_shm_close(fShmAudioPool.shm);
return false; return false;
} }

fNeedsSemDestroy = true;
} }


// initial values // initial values
rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetBufferSize);
rdwr_writeInt(&fShmControl.data->ringBuffer, kData->engine->getBufferSize());
fShmControl.writeOpcode(kPluginBridgeOpcodeSetBufferSize);
fShmControl.writeInt(kData->engine->getBufferSize());


rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetSampleRate);
rdwr_writeFloat(&fShmControl.data->ringBuffer, kData->engine->getSampleRate());
fShmControl.writeOpcode(kPluginBridgeOpcodeSetSampleRate);
fShmControl.writeFloat(kData->engine->getSampleRate());


rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.commitWrite();


// register plugin now so we can receive OSC (and wait for it) // register plugin now so we can receive OSC (and wait for it)
fHints |= PLUGIN_IS_BRIDGE; fHints |= PLUGIN_IS_BRIDGE;
@@ -1689,35 +1841,12 @@ private:
bool fInitiated; bool fInitiated;
bool fInitError; bool fInitError;
bool fSaved; bool fSaved;
bool fNeedsSemDestroy;


CarlaString fBridgeBinary; CarlaString fBridgeBinary;


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

BridgeAudioPool()
: data(nullptr),
size(0)
{
carla_shm_init(shm);
}
} fShmAudioPool;

struct BridgeControl {
CarlaString filename;
BridgeShmControl* data;
shm_t shm;

BridgeControl()
: data(nullptr)
{
carla_shm_init(shm);
}

} fShmControl;
BridgeAudioPool fShmAudioPool;
BridgeControl fShmControl;


struct Info { struct Info {
uint32_t aIns, aOuts; uint32_t aIns, aOuts;
@@ -1741,59 +1870,20 @@ private:


BridgeParamInfo* fParams; BridgeParamInfo* fParams;


void cleanup()
void resizeAudioPool(const uint32_t bufferSize)
{ {
if (fShmAudioPool.filename.isNotEmpty())
fShmAudioPool.filename.clear();
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts);


if (fShmControl.filename.isNotEmpty())
fShmControl.filename.clear();

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

fShmAudioPool.size = 0;

if (fShmControl.data != nullptr)
{
carla_shm_unmap(fShmControl.shm, fShmControl.data, sizeof(BridgeShmControl));
fShmControl.data = nullptr;
}

if (carla_is_shm_valid(fShmAudioPool.shm))
carla_shm_close(fShmAudioPool.shm);

if (carla_is_shm_valid(fShmControl.shm))
carla_shm_close(fShmControl.shm);
}

void resizeAudioPool(uint32_t bufferSize)
{
if (fShmAudioPool.data != nullptr)
carla_shm_unmap(fShmAudioPool.shm, fShmAudioPool.data, fShmAudioPool.size);

fShmAudioPool.size = (fInfo.aIns+fInfo.aOuts)*bufferSize*sizeof(float);

if (fShmAudioPool.size == 0)
fShmAudioPool.size = sizeof(float);

fShmAudioPool.data = (float*)carla_shm_map(fShmAudioPool.shm, fShmAudioPool.size);

rdwr_writeOpcode(&fShmControl.data->ringBuffer, kPluginBridgeOpcodeSetAudioPool);
rdwr_writeInt(&fShmControl.data->ringBuffer, fShmAudioPool.size);
rdwr_commitWrite(&fShmControl.data->ringBuffer);
fShmControl.writeOpcode(kPluginBridgeOpcodeSetAudioPool);
fShmControl.writeLong(fShmAudioPool.size);
fShmControl.commitWrite();


waitForServer(); waitForServer();
} }


bool waitForServer() bool waitForServer()
{ {
sem_post(&fShmControl.data->runServer);

if (! jackbridge_sem_timedwait(&fShmControl.data->runClient, 5))
if (! fShmControl.waitForServer())
{ {
carla_stderr("waitForServer() timeout"); carla_stderr("waitForServer() timeout");
kData->active = false; // TODO kData->active = false; // TODO
@@ -1854,18 +1944,23 @@ CarlaPlugin* CarlaPlugin::newBridge(const Initializer& init, BinaryType btype, P
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Bridge Helper // Bridge Helper


#define bridgePlugin ((BridgePlugin*)plugin)

int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type, int CarlaPluginSetOscBridgeInfo(CarlaPlugin* const plugin, const PluginBridgeInfoType type,
const int argc, const lo_arg* const* const argv, const char* const types) const int argc, const lo_arg* const* const argv, const char* const types)
{ {
CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0); CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
return ((BridgePlugin*)plugin)->setOscPluginBridgeInfo(type, argc, argv, types);
return bridgePlugin->setOscPluginBridgeInfo(type, argc, argv, types);
} }


BinaryType CarlaPluginGetBridgeBinaryType(CarlaPlugin* const plugin) BinaryType CarlaPluginGetBridgeBinaryType(CarlaPlugin* const plugin)
{ {
CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0); CARLA_ASSERT(plugin != nullptr && (plugin->hints() & PLUGIN_IS_BRIDGE) != 0);
return ((BridgePlugin*)plugin)->binaryType();
return bridgePlugin->binaryType();
} }

#undef bridgePlugin

#endif #endif


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE

+ 2
- 0
source/backend/plugin/CarlaPlugin.pro View File

@@ -68,11 +68,13 @@ HEADERS += \


HEADERS += \ HEADERS += \
../../utils/CarlaUtils.hpp \ ../../utils/CarlaUtils.hpp \
../../utils/CarlaBridgeUtils.hpp \
../../utils/CarlaJuceUtils.hpp \ ../../utils/CarlaJuceUtils.hpp \
../../utils/CarlaLibUtils.hpp \ ../../utils/CarlaLibUtils.hpp \
../../utils/CarlaOscUtils.hpp \ ../../utils/CarlaOscUtils.hpp \
../../utils/CarlaStateUtils.hpp \ ../../utils/CarlaStateUtils.hpp \
../../utils/CarlaMutex.hpp \ ../../utils/CarlaMutex.hpp \
../../utils/CarlaRingBuffer.hpp \
../../utils/CarlaString.hpp ../../utils/CarlaString.hpp


INCLUDEPATH = . .. \ INCLUDEPATH = . .. \


+ 1
- 1
source/libs/distrho/DistrhoUIExternal.hpp View File

@@ -33,7 +33,7 @@ public:
virtual ~ExternalUI() override; virtual ~ExternalUI() override;


protected: protected:
const char* d_externalFilename() const = 0;
virtual const char* d_externalFilename() const = 0;


private: private:
friend class UIInternal; friend class UIInternal;


+ 3
- 3
source/libs/distrho/src/DistrhoPluginVST.cpp View File

@@ -211,7 +211,7 @@ protected:
void setParameterValue(uint32_t index, float realValue) void setParameterValue(uint32_t index, float realValue)
{ {
const ParameterRanges& ranges(kPlugin->parameterRanges(index)); const ParameterRanges& ranges(kPlugin->parameterRanges(index));
const float perValue(ranges.normalizeValue(realValue));
const float perValue(ranges.normalizedValue(realValue));


kPlugin->setParameterValue(index, realValue); kPlugin->setParameterValue(index, realValue);
hostCallback(audioMasterAutomate, index, 0, nullptr, perValue); hostCallback(audioMasterAutomate, index, 0, nullptr, perValue);
@@ -472,13 +472,13 @@ public:
float vst_getParameter(int32_t index) float vst_getParameter(int32_t index)
{ {
const ParameterRanges& ranges(fPlugin.parameterRanges(index)); const ParameterRanges& ranges(fPlugin.parameterRanges(index));
return ranges.normalizeValue(fPlugin.parameterValue(index));
return ranges.normalizedValue(fPlugin.parameterValue(index));
} }


void vst_setParameter(int32_t index, float value) void vst_setParameter(int32_t index, float value)
{ {
const ParameterRanges& ranges(fPlugin.parameterRanges(index)); const ParameterRanges& ranges(fPlugin.parameterRanges(index));
const float realValue(ranges.unnormalizeValue(value));
const float realValue(ranges.unnormalizedValue(value));
fPlugin.setParameterValue(index, realValue); fPlugin.setParameterValue(index, realValue);


#if DISTRHO_PLUGIN_HAS_UI #if DISTRHO_PLUGIN_HAS_UI


+ 2
- 0
source/libs/jackbridge/JackBridge.hpp View File

@@ -335,6 +335,8 @@ CARLA_EXPORT bool jackbridge_custom_unpublish_data(jack_client_t* client, const
CARLA_EXPORT bool jackbridge_custom_set_data_appearance_callback(jack_client_t* client, JackCustomDataAppearanceCallback callback, void* arg); CARLA_EXPORT bool jackbridge_custom_set_data_appearance_callback(jack_client_t* client, JackCustomDataAppearanceCallback callback, void* arg);
CARLA_EXPORT const char** jackbridge_custom_get_keys(jack_client_t* client, const char* client_name); CARLA_EXPORT const char** jackbridge_custom_get_keys(jack_client_t* client, const char* client_name);


CARLA_EXPORT bool jackbridge_sem_init(void* sem);
CARLA_EXPORT bool jackbridge_sem_destroy(void* sem);
CARLA_EXPORT bool jackbridge_sem_post(void* sem); CARLA_EXPORT bool jackbridge_sem_post(void* sem);
CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs); CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs);




+ 31
- 9
source/libs/jackbridge/JackBridge2.cpp View File

@@ -18,6 +18,8 @@


#ifndef __JACKBRIDGE_HPP__ #ifndef __JACKBRIDGE_HPP__
// don't include the whole JACK API in this file // don't include the whole JACK API in this file
CARLA_EXPORT bool jackbridge_sem_init(void* sem);
CARLA_EXPORT bool jackbridge_sem_destroy(void* sem);
CARLA_EXPORT bool jackbridge_sem_post(void* sem); CARLA_EXPORT bool jackbridge_sem_post(void* sem);
CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs); CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs);
#endif #endif
@@ -25,6 +27,16 @@ CARLA_EXPORT bool jackbridge_sem_timedwait(void* sem, int secs);
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------


#if JACKBRIDGE_DUMMY #if JACKBRIDGE_DUMMY
bool jackbridge_sem_init(void*)
{
return false;
}

bool jackbridge_sem_destroy(void*)
{
return false;
}

bool jackbridge_sem_post(void*) bool jackbridge_sem_post(void*)
{ {
return false; return false;
@@ -38,15 +50,15 @@ bool jackbridge_sem_timedwait(void*, int)


#include <semaphore.h> #include <semaphore.h>


#ifdef __WINE__
# define _STRUCT_TIMEVAL 1
# define _SYS_SELECT_H 1
# include <bits/types.h>
struct timespec {
__time_t tv_sec; /* Seconds. */
long int tv_nsec; /* Nanoseconds. */
};
#endif
//#ifdef __WINE__
//# define _STRUCT_TIMEVAL 1
//# define _SYS_SELECT_H 1
//# include <bits/types.h>
//struct timespec {
// __time_t tv_sec; /* Seconds. */
// long int tv_nsec; /* Nanoseconds. */
//};
//#endif


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
# include <sys/time.h> # include <sys/time.h>
@@ -54,6 +66,16 @@ struct timespec {
# include <time.h> # include <time.h>
#endif #endif


bool jackbridge_sem_init(void* sem)
{
return (sem_init((sem_t*)sem, 1, 0) == 0);
}

bool jackbridge_sem_destroy(void* sem)
{
return (sem_destroy((sem_t*)sem) == 0);
}

bool jackbridge_sem_post(void* sem) bool jackbridge_sem_post(void* sem)
{ {
return (sem_post((sem_t*)sem) == 0); return (sem_post((sem_t*)sem) == 0);


+ 15
- 8
source/libs/jackbridge/Makefile View File

@@ -29,11 +29,13 @@ WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wi
WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine
WINE_LINK_FLAGS = $(LINK_FLAGS) -ldl -lrt -lpthread -ljack WINE_LINK_FLAGS = $(LINK_FLAGS) -ldl -lrt -lpthread -ljack


OBJS = JackBridge1.cpp JackBridge2.cpp
OBJS = JackBridge1.cpp JackBridge2.cpp
OBJSw32 = JackBridge1.w32.o JackBridge2.w32.o
OBJSw64 = JackBridge1.w64.o JackBridge2.w64.o


# -------------------------------------------------------------- # --------------------------------------------------------------


all: test
all:


win32: ../jackbridge-win32.dll win32: ../jackbridge-win32.dll
win64: ../jackbridge-win64.dll win64: ../jackbridge-win64.dll
@@ -42,8 +44,13 @@ wine64: ../jackbridge-win64.dll.so


# -------------------------------------------------------------- # --------------------------------------------------------------


test: $(OBJS)
$(CXX) $^ $(WINE_BUILD_FLAGS) $(WINE_LINK_FLAGS) -o $@
JackBridge%.w32.o: JackBridge%.cpp
$(CXX) $^ $(WINE_BUILD_FLAGS) $(WINE_32BIT_FLAGS) -c -o $@

JackBridge%.w64.o: JackBridge%.cpp
$(CXX) $^ $(WINE_BUILD_FLAGS) $(WINE_64BIT_FLAGS) -c -o $@

# --------------------------------------------------------------


../jackbridge-win32.dll: $(OBJS) ../jackbridge-win32.dll: $(OBJS)
$(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@ $(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_32BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@
@@ -51,10 +58,10 @@ test: $(OBJS)
../jackbridge-win64.dll: $(OBJS) ../jackbridge-win64.dll: $(OBJS)
$(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@ $(CXX) $^ $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -Wl,--output-def,$@.def,--out-implib,$@.a -o $@ $(CMD_STRIP) $@


../jackbridge-win32.dll.so: $(OBJS) ../jackbridge-win32.dll.def
$(WINECXX) $^ $(WINE_BUILD_FLAGS) $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) -mno-cygwin -o $@ $(CMD_STRIP) $@
../jackbridge-win32.dll.so: JackBridge1.cpp JackBridge2.cpp ../jackbridge-win32.dll.def
$(WINECXX) $^ $(WIN_BUILD_FLAGS) $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) -mno-cygwin -o $@ $(CMD_STRIP) $@


../jackbridge-win64.dll.so: $(OBJS) ../jackbridge-win64.dll.def
$(WINECXX) $^ $(WINE_BUILD_FLAGS) $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) -mno-cygwin -o $@ $(CMD_STRIP) $@
../jackbridge-win64.dll.so: JackBridge1.cpp JackBridge2.cpp ../jackbridge-win64.dll.def
$(WINECXX) $^ $(WIN_BUILD_FLAGS) $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) -mno-cygwin -o $@ $(CMD_STRIP) $@


# -------------------------------------------------------------- # --------------------------------------------------------------

+ 36
- 190
source/utils/CarlaBridgeUtils.hpp View File

@@ -19,16 +19,12 @@
#ifndef __CARLA_BRIDGE_UTILS_HPP__ #ifndef __CARLA_BRIDGE_UTILS_HPP__
#define __CARLA_BRIDGE_UTILS_HPP__ #define __CARLA_BRIDGE_UTILS_HPP__


#include "CarlaUtils.hpp"
#include "CarlaRingBuffer.hpp"


#include <semaphore.h>

#define BRIDGE_SHM_RING_BUFFER_SIZE 2048

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


enum PluginBridgeInfoType { enum PluginBridgeInfoType {
kPluginBridgeAudioCount,
kPluginBridgeAudioCount = 0,
kPluginBridgeMidiCount, kPluginBridgeMidiCount,
kPluginBridgeParameterCount, kPluginBridgeParameterCount,
kPluginBridgeProgramCount, kPluginBridgeProgramCount,
@@ -52,7 +48,7 @@ enum PluginBridgeInfoType {


enum PluginBridgeOpcode { enum PluginBridgeOpcode {
kPluginBridgeOpcodeNull = 0, kPluginBridgeOpcodeNull = 0,
kPluginBridgeOpcodeSetAudioPool = 1, // int
kPluginBridgeOpcodeSetAudioPool = 1, // long
kPluginBridgeOpcodeSetBufferSize = 2, // int kPluginBridgeOpcodeSetBufferSize = 2, // int
kPluginBridgeOpcodeSetSampleRate = 3, // float kPluginBridgeOpcodeSetSampleRate = 3, // float
kPluginBridgeOpcodeSetParameter = 4, // int, float kPluginBridgeOpcodeSetParameter = 4, // int, float
@@ -72,29 +68,25 @@ const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Hos
//If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file. //If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file.
#endif #endif


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

struct BridgeRingBuffer {
int head, tail, written;
bool invalidateCommit;
char buf[BRIDGE_SHM_RING_BUFFER_SIZE];
};
// -------------------------------------------------


struct BridgeShmControl { struct BridgeShmControl {
// 32 and 64-bit binaries align semaphores differently. // 32 and 64-bit binaries align semaphores differently.
// Let's make sure there's plenty of room for either one. // Let's make sure there's plenty of room for either one.
union { union {
sem_t runServer;
void* runServer;
char _alignServer[128]; char _alignServer[128];
}; };
union { union {
sem_t runClient;
void* runClient;
char _alignClient[128]; char _alignClient[128];
}; };
BridgeRingBuffer ringBuffer;
RingBuffer ringBuffer;

CARLA_DECLARE_NON_COPY_STRUCT(BridgeShmControl)
}; };


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


static inline static inline
const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type) const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type)
@@ -147,183 +139,37 @@ const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type)
return nullptr; return nullptr;
} }


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

static inline static inline
void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size)
const char* PluginBridgeOpcode2str(const PluginBridgeOpcode opcode)
{ {
CARLA_ASSERT(buf != nullptr);

if (buf == nullptr)
return;

char* const charbuf(static_cast<char*>(buf));

size_t tail = ringbuf->tail;
size_t head = ringbuf->head;
size_t wrap = 0;

if (head <= tail) {
wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
}
if (head - tail + wrap < size) {
return;
}

size_t readto = tail + size;

if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE)
{
readto -= BRIDGE_SHM_RING_BUFFER_SIZE;
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail;
std::memcpy(charbuf, ringbuf->buf + tail, firstpart);
std::memcpy(charbuf + firstpart, ringbuf->buf, readto);
}
else
switch (opcode)
{ {
std::memcpy(charbuf, ringbuf->buf + tail, size);
case kPluginBridgeOpcodeNull:
return "kPluginBridgeOpcodeNull";
case kPluginBridgeOpcodeSetAudioPool:
return "kPluginBridgeOpcodeSetAudioPool";
case kPluginBridgeOpcodeSetBufferSize:
return "kPluginBridgeOpcodeSetBufferSize";
case kPluginBridgeOpcodeSetSampleRate:
return "kPluginBridgeOpcodeSetSampleRate";
case kPluginBridgeOpcodeSetParameter:
return "kPluginBridgeOpcodeSetParameter";
case kPluginBridgeOpcodeSetProgram:
return "kPluginBridgeOpcodeSetProgram";
case kPluginBridgeOpcodeSetMidiProgram:
return "kPluginBridgeOpcodeSetMidiProgram";
case kPluginBridgeOpcodeMidiEvent:
return "kPluginBridgeOpcodeMidiEvent";
case kPluginBridgeOpcodeProcess:
return "kPluginBridgeOpcodeProcess";
case kPluginBridgeOpcodeQuit:
return "kPluginBridgeOpcodeQuit";
} }


ringbuf->tail = readto;
}

static inline
void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size)
{
CARLA_ASSERT(buf != nullptr);

if (buf == nullptr)
return;

const char* const charbuf(static_cast<const char*>(buf));

size_t written = ringbuf->written;
size_t tail = ringbuf->tail;
size_t wrap = 0;

if (tail <= written)
{
wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
}
if (tail - written + wrap < size)
{
carla_stderr2("Ring buffer full! Dropping events.");
ringbuf->invalidateCommit = true;
return;
}

size_t writeto = written + size;

if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE)
{
writeto -= BRIDGE_SHM_RING_BUFFER_SIZE;
size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written;
std::memcpy(ringbuf->buf + written, charbuf, firstpart);
std::memcpy(ringbuf->buf, charbuf + firstpart, writeto);
}
else
{
std::memcpy(ringbuf->buf + written, charbuf, size);
}

ringbuf->written = writeto;
}

static inline
void rdwr_commitWrite(BridgeRingBuffer* const ringbuf)
{
if (ringbuf->invalidateCommit)
{
ringbuf->written = ringbuf->head;
ringbuf->invalidateCommit = false;
}
else
{
ringbuf->head = ringbuf->written;
}
}

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

static inline
bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf)
{
return (ringbuf->tail != ringbuf->head);
}

static inline
PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf)
{
int i = static_cast<int>(kPluginBridgeOpcodeNull);
rdwr_tryRead(ringbuf, &i, sizeof(int));
return static_cast<PluginBridgeOpcode>(i);
}

static inline
char rdwr_readChar(BridgeRingBuffer* const ringbuf)
{
char c = 0;
rdwr_tryRead(ringbuf, &c, sizeof(char));
return c;
}

static inline
int rdwr_readInt(BridgeRingBuffer* const ringbuf)
{
int i = 0;
rdwr_tryRead(ringbuf, &i, sizeof(int));
return i;
}

static inline
long rdwr_readLong(BridgeRingBuffer* const ringbuf)
{
long l = 0;
rdwr_tryRead(ringbuf, &l, sizeof(long));
return l;
}

static inline
float rdwr_readFloat(BridgeRingBuffer* const ringbuf)
{
float f = 0.0f;
rdwr_tryRead(ringbuf, &f, sizeof(float));
return f;
}

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

static inline
void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode)
{
const int intcode(static_cast<int>(opcode));
rdwr_tryWrite(ringbuf, &intcode, sizeof(int));
}

static inline
void rdwr_writeChar(BridgeRingBuffer* const ringbuf, const char value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(char));
}

static inline
void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(int));
}

static inline
void rdwr_writeLong(BridgeRingBuffer* const ringbuf, const long value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(long));
}

static inline
void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value)
{
rdwr_tryWrite(ringbuf, &value, sizeof(float));
carla_stderr("CarlaBackend::PluginBridgeOpcode2str(%i) - invalid opcode", opcode);
return nullptr;
} }


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


#endif // __CARLA_BRIDGE_UTILS_HPP__ #endif // __CARLA_BRIDGE_UTILS_HPP__

Loading…
Cancel
Save