Browse Source

Allow to receive LV2 atoms of any size up to max-length

Previous design with a stack var was so wrong

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.5.3
falkTX 2 years ago
parent
commit
ec3d7a3657
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
2 changed files with 58 additions and 45 deletions
  1. +39
    -14
      source/backend/plugin/CarlaPluginLV2.cpp
  2. +19
    -31
      source/utils/Lv2AtomRingBuffer.hpp

+ 39
- 14
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -657,6 +657,8 @@ public:
fAtomBufferWorkerResp(), fAtomBufferWorkerResp(),
fAtomBufferUiOutTmpData(nullptr), fAtomBufferUiOutTmpData(nullptr),
fAtomBufferWorkerInTmpData(nullptr), fAtomBufferWorkerInTmpData(nullptr),
fAtomBufferRealtime(nullptr),
fAtomBufferRealtimeSize(0),
fEventsIn(), fEventsIn(),
fEventsOut(), fEventsOut(),
fLv2Options(), fLv2Options(),
@@ -858,6 +860,12 @@ public:
fAtomBufferWorkerInTmpData = nullptr; fAtomBufferWorkerInTmpData = nullptr;
} }


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

clearBuffers(); clearBuffers();
} }


@@ -2131,14 +2139,19 @@ public:
CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),); CARLA_SAFE_ASSERT_RETURN(tmpRingBuffer.isDataAvailableForReading(),);
CARLA_SAFE_ASSERT_RETURN(fExt.worker != nullptr && fExt.worker->work != nullptr,); 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; 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) if (fInlineDisplayNeedsRedraw)
@@ -2200,29 +2213,35 @@ public:
Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData); Lv2AtomRingBuffer tmpRingBuffer(fAtomBufferUiOut, fAtomBufferUiOutTmpData);
CARLA_SAFE_ASSERT(tmpRingBuffer.isDataAvailableForReading()); 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; uint32_t portIndex;
const LV2_Atom* atom;
const bool hasPortEvent(fUI.handle != nullptr && const bool hasPortEvent(fUI.handle != nullptr &&
fUI.descriptor != nullptr && fUI.descriptor != nullptr &&
fUI.descriptor->port_event != nullptr); fUI.descriptor->port_event != nullptr);


for (; tmpRingBuffer.get(atom, portIndex);)
for (; tmpRingBuffer.get(portIndex, localAtom); localAtom->size = localSize)
{ {
#ifndef LV2_UIS_ONLY_INPROCESS #ifndef LV2_UIS_ONLY_INPROCESS
if (fUI.type == UI::TYPE_BRIDGE) if (fUI.type == UI::TYPE_BRIDGE)
{ {
if (fPipeServer.isPipeRunning()) if (fPipeServer.isPipeRunning())
fPipeServer.writeLv2AtomMessage(portIndex, atom);
fPipeServer.writeLv2AtomMessage(portIndex, localAtom);
} }
else else
#endif #endif
{ {
if (hasPortEvent && ! fNeedsUiClose) 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 #ifndef LV2_UIS_ONLY_INPROCESS
@@ -3221,7 +3240,9 @@ public:
{ {
fAtomBufferWorkerIn.createBuffer(eventBufferSize); fAtomBufferWorkerIn.createBuffer(eventBufferSize);
fAtomBufferWorkerResp.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 || if (fRdfDescriptor->ParameterCount > 0 ||
@@ -3869,10 +3890,11 @@ public:
{ {
if (fAtomBufferEvIn.isDataAvailableForReading()) if (fAtomBufferEvIn.isDataAvailableForReading())
{ {
const LV2_Atom* atom;
uint32_t j, portIndex; 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; j = (portIndex < fEventsIn.count) ? portIndex : fEventsIn.ctrlIndex;


@@ -4331,10 +4353,11 @@ public:
{ {
if (fAtomBufferWorkerResp.isDataAvailableForReading()) if (fAtomBufferWorkerResp.isDataAvailableForReading())
{ {
const LV2_Atom* atom;
uint32_t portIndex; 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); CARLA_SAFE_ASSERT_CONTINUE(atom->type == kUridCarlaAtomWorkerResp);
fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom)); fExt.worker->work_response(fHandle, atom->size, LV2_ATOM_BODY_CONST(atom));
@@ -7472,6 +7495,8 @@ private:
Lv2AtomRingBuffer fAtomBufferWorkerResp; Lv2AtomRingBuffer fAtomBufferWorkerResp;
uint8_t* fAtomBufferUiOutTmpData; uint8_t* fAtomBufferUiOutTmpData;
uint8_t* fAtomBufferWorkerInTmpData; uint8_t* fAtomBufferWorkerInTmpData;
LV2_Atom* fAtomBufferRealtime;
uint32_t fAtomBufferRealtimeSize;


CarlaPluginLV2EventData fEventsIn; CarlaPluginLV2EventData fEventsIn;
CarlaPluginLV2EventData fEventsOut; CarlaPluginLV2EventData fEventsOut;


+ 19
- 31
source/utils/Lv2AtomRingBuffer.hpp View File

@@ -32,9 +32,6 @@ public:
: fMutex(), : fMutex(),
fHeapBuffer(HeapBuffer_INIT), fHeapBuffer(HeapBuffer_INIT),
fNeedsDataDelete(true) fNeedsDataDelete(true)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, fRetAtom{{0,0}, {0}}
#endif
{ {
carla_zeroStruct(fHeapBuffer); carla_zeroStruct(fHeapBuffer);
} }
@@ -43,9 +40,6 @@ public:
: fMutex(), : fMutex(),
fHeapBuffer(HeapBuffer_INIT), fHeapBuffer(HeapBuffer_INIT),
fNeedsDataDelete(false) fNeedsDataDelete(false)
#ifdef CARLA_PROPER_CPP11_SUPPORT
, fRetAtom{{0,0}, {0}}
#endif
{ {
carla_zeroStruct(fHeapBuffer); carla_zeroStruct(fHeapBuffer);


@@ -120,14 +114,12 @@ public:
// ------------------------------------------------------------------- // -------------------------------------------------------------------


// NOTE: must have been locked before // 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; return true;
}


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


@@ -155,29 +147,32 @@ public:
protected: 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; int32_t index = -1;
if (! tryRead(&index, sizeof(int32_t))) if (! tryRead(&index, sizeof(int32_t)))
return nullptr;
return false;
if (index < 0) 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); portIndex = static_cast<uint32_t>(index);
return &fRetAtom.atom;
retAtom->size = atom.size;
retAtom->type = atom.type;
return true;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -203,13 +198,6 @@ private:
HeapBuffer fHeapBuffer; HeapBuffer fHeapBuffer;
const bool fNeedsDataDelete; 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; friend class Lv2AtomQueue;


CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION


Loading…
Cancel
Save