Skip to content

Commit

Permalink
Allow to receive LV2 atoms of any size up to max-length
Browse files Browse the repository at this point in the history
Previous design with a stack var was so wrong

Signed-off-by: falkTX <falktx@falktx.com>
  • Loading branch information
falkTX committed Jan 13, 2023
1 parent 1d537e9 commit ec3d7a3
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 45 deletions.
53 changes: 39 additions & 14 deletions source/backend/plugin/CarlaPluginLV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,8 @@ class CarlaPluginLV2 : public CarlaPlugin,
fAtomBufferWorkerResp(),
fAtomBufferUiOutTmpData(nullptr),
fAtomBufferWorkerInTmpData(nullptr),
fAtomBufferRealtime(nullptr),
fAtomBufferRealtimeSize(0),
fEventsIn(),
fEventsOut(),
fLv2Options(),
Expand Down Expand Up @@ -858,6 +860,12 @@ class CarlaPluginLV2 : public CarlaPlugin,
fAtomBufferWorkerInTmpData = nullptr;
}

if (fAtomBufferRealtime != nullptr)
{
std::free(fAtomBufferRealtime);
fAtomBufferRealtime = nullptr;
}

clearBuffers();
}

Expand Down Expand Up @@ -2131,14 +2139,19 @@ class CarlaPluginLV2 : public CarlaPlugin,
CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),);
CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr,);

const size_t localSize = fAtomBufferWorkerIn.getSize();
uint8_t* const localData = new uint8_t[localSize];
LV2_Atom* const localAtom = static_cast<LV2_Atom*>(static_cast<void*>(localData));
localAtom->size = localSize;
uint32_t portIndex;
const LV2_Atom* atom;

for (; tmpRingBuffer.get(atom, portIndex);)
for (; tmpRingBuffer.get(portIndex, localAtom); localAtom->size = localSize)
{
CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerIn);
fExt.worker->work(fHandle, carla_lv2_worker_respond, this, atom->size, LV2_ATOM_BODY_CONST(atom));
CARLA_SAFE_ASSERT_CONTINUE(localAtom->type == kUridCarlaAtomWorkerIn);
fExt.worker->work(fHandle, carla_lv2_worker_respond, this, localAtom->size, LV2_ATOM_BODY_CONST(localAtom));
}

delete[] localData;
}

if (fInlineDisplayNeedsRedraw)
Expand Down Expand Up @@ -2200,29 +2213,35 @@ class CarlaPluginLV2 : public CarlaPlugin,
Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData);
CARLA_SAFE_ASSERT(tmpRingBuffer.isDataAvailableForReading());

const size_t localSize = fAtomBufferUiOut.getSize();
uint8_t* const localData = new uint8_t[localSize];
LV2_Atom* const localAtom = static_cast<LV2_Atom*>(static_cast<void*>(localData));
localAtom->size = localSize;

uint32_t portIndex;
const LV2_Atom* atom;
const bool hasPortEvent(fUI.handle != nullptr &&
fUI.descriptor != nullptr &&
fUI.descriptor->port_event != nullptr);

for (; tmpRingBuffer.get(atom, portIndex);)
for (; tmpRingBuffer.get(portIndex, localAtom); localAtom->size = localSize)
{
#ifndef LV2_UIS_ONLY_INPROCESS
if (fUI.type == UI::TYPE_BRIDGE)
{
if (fPipeServer.isPipeRunning())
fPipeServer.writeLv2AtomMessage(portIndex, atom);
fPipeServer.writeLv2AtomMessage(portIndex, localAtom);
}
else
#endif
{
if (hasPortEvent && ! fNeedsUiClose)
fUI.descriptor->port_event(fUI.handle, portIndex, lv2_atom_total_size(atom), kUridAtomTransferEvent, atom);
fUI.descriptor->port_event(fUI.handle, portIndex, lv2_atom_total_size(localAtom), kUridAtomTransferEvent, localAtom);
}

inspectAtomForParameterChange(atom);
inspectAtomForParameterChange(localAtom);
}

delete[] localData;
}

#ifndef LV2_UIS_ONLY_INPROCESS
Expand Down Expand Up @@ -3221,7 +3240,9 @@ class CarlaPluginLV2 : public CarlaPlugin,
{
fAtomBufferWorkerIn.createBuffer(eventBufferSize);
fAtomBufferWorkerResp.createBuffer(eventBufferSize);
fAtomBufferWorkerInTmpData = new uint8_t[fAtomBufferWorkerIn.getSize()];
fAtomBufferRealtimeSize = fAtomBufferWorkerIn.getSize(); // actual buffer size will be next power of 2
fAtomBufferRealtime = static_cast<LV2_Atom*>(std::malloc(fAtomBufferRealtimeSize));
fAtomBufferWorkerInTmpData = new uint8_t[fAtomBufferRealtimeSize];
}

if (fRdfDescriptor->ParameterCount > 0 ||
Expand Down Expand Up @@ -3869,10 +3890,11 @@ class CarlaPluginLV2 : public CarlaPlugin,
{
if (fAtomBufferEvIn.isDataAvailableForReading())
{
const LV2_Atom* atom;
uint32_t j, portIndex;
LV2_Atom* const atom = fAtomBufferRealtime;
atom->size = fAtomBufferRealtimeSize;

for (; fAtomBufferEvIn.get(atom, portIndex);)
for (; fAtomBufferEvIn.get(portIndex, atom); atom->size = fAtomBufferRealtimeSize)
{
j = (portIndex < fEventsIn.count) ? portIndex : fEventsIn.ctrlIndex;

Expand Down Expand Up @@ -4331,10 +4353,11 @@ class CarlaPluginLV2 : public CarlaPlugin,
{
if (fAtomBufferWorkerResp.isDataAvailableForReading())
{
const LV2_Atom* atom;
uint32_t portIndex;
LV2_Atom* const atom = fAtomBufferRealtime;
atom->size = fAtomBufferRealtimeSize;

for (; fAtomBufferWorkerResp.get(atom, portIndex);)
for (; fAtomBufferWorkerResp.get(portIndex, atom); atom->size = fAtomBufferRealtimeSize)
{
CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerResp);
fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom));
Expand Down Expand Up @@ -7472,6 +7495,8 @@ class CarlaPluginLV2 : public CarlaPlugin,
Lv2AtomRingBuffer fAtomBufferWorkerResp;
uint8_t* fAtomBufferUiOutTmpData;
uint8_t* fAtomBufferWorkerInTmpData;
LV2_Atom* fAtomBufferRealtime;
uint32_t fAtomBufferRealtimeSize;

CarlaPluginLV2EventData fEventsIn;
CarlaPluginLV2EventData fEventsOut;
Expand Down
50 changes: 19 additions & 31 deletions source/utils/Lv2AtomRingBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
: fMutex(),
fHeapBuffer(HeapBuffer_INIT),
fNeedsDataDelete(true)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, fRetAtom{{0,0}, {0}}
#endif
{
carla_zeroStruct(fHeapBuffer);
}
Expand All @@ -43,9 +40,6 @@ class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
: fMutex(),
fHeapBuffer(HeapBuffer_INIT),
fNeedsDataDelete(false)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, fRetAtom{{0,0}, {0}}
#endif
{
carla_zeroStruct(fHeapBuffer);

Expand Down Expand Up @@ -120,14 +114,12 @@ class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
// -------------------------------------------------------------------

// NOTE: must have been locked before
bool get(const LV2_Atom*& atom, uint32_t& portIndex) noexcept
bool get(uint32_t& portIndex, LV2_Atom* const retAtom) noexcept
{
if (const LV2_Atom* const retAtom = readAtom(portIndex))
{
atom = retAtom;
if (readAtom(portIndex, retAtom))
return true;
}

retAtom->size = retAtom->type = 0;
return false;
}

Expand Down Expand Up @@ -155,29 +147,32 @@ class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
protected:
// -------------------------------------------------------------------

const LV2_Atom* readAtom(uint32_t& portIndex) noexcept
bool readAtom(uint32_t& portIndex, LV2_Atom* const retAtom) noexcept
{
fRetAtom.atom.size = 0;
fRetAtom.atom.type = 0;
const uint32_t maxAtomSize = retAtom->size - sizeof(LV2_Atom);

LV2_Atom atom = {};

if (! tryRead(&fRetAtom.atom, sizeof(LV2_Atom)))
return nullptr;
if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0)
return nullptr;
if (! tryRead(&atom, sizeof(LV2_Atom)))
return false;
if (atom.size == 0 || atom.type == 0)
return false;

CARLA_SAFE_ASSERT_UINT2_RETURN(fRetAtom.atom.size < kMaxAtomDataSize, fRetAtom.atom.size, kMaxAtomDataSize, nullptr);
CARLA_SAFE_ASSERT_UINT2_RETURN(atom.size < maxAtomSize, atom.size, maxAtomSize, false);

int32_t index = -1;
if (! tryRead(&index, sizeof(int32_t)))
return nullptr;
return false;
if (index < 0)
return nullptr;
return false;

if (! tryRead(fRetAtom.data, fRetAtom.atom.size))
return nullptr;
if (! tryRead(retAtom + 1, atom.size))
return false;

portIndex = static_cast<uint32_t>(index);
return &fRetAtom.atom;
retAtom->size = atom.size;
retAtom->type = atom.type;
return true;
}

// -------------------------------------------------------------------
Expand All @@ -203,13 +198,6 @@ class Lv2AtomRingBuffer : public CarlaRingBufferControl<HeapBuffer>
HeapBuffer fHeapBuffer;
const bool fNeedsDataDelete;

static const std::size_t kMaxAtomDataSize = 32768 - sizeof(LV2_Atom);

struct RetAtom {
LV2_Atom atom;
char data[kMaxAtomDataSize];
} fRetAtom;

friend class Lv2AtomQueue;

CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
Expand Down

0 comments on commit ec3d7a3

Please sign in to comment.