| @@ -151,13 +151,13 @@ struct BridgeAudioPool { | |||||
| } | } | ||||
| }; | }; | ||||
| struct BridgeControl : public RingBufferControl { | |||||
| struct BridgeControl : public RingBufferControlTemplate<StackRingBuffer> { | |||||
| CarlaString filename; | CarlaString filename; | ||||
| BridgeShmControl* data; | BridgeShmControl* data; | ||||
| shm_t shm; | shm_t shm; | ||||
| BridgeControl() | BridgeControl() | ||||
| : RingBufferControl(nullptr), | |||||
| : RingBufferControlTemplate(nullptr), | |||||
| data(nullptr) | data(nullptr) | ||||
| { | { | ||||
| carla_shm_init(shm); | carla_shm_init(shm); | ||||
| @@ -1204,36 +1204,39 @@ public: | |||||
| void idle() override | void idle() override | ||||
| { | { | ||||
| #if 0 | |||||
| if (fUi.type == UI::TYPE_NULL) | |||||
| return CarlaPlugin::idle(); | |||||
| if (! fAtomQueueOut.isEmpty()) | if (! fAtomQueueOut.isEmpty()) | ||||
| { | { | ||||
| char dumpBuf[fAtomQueueOut.getSize()]; | |||||
| Lv2AtomQueue tmpQueue; | Lv2AtomQueue tmpQueue; | ||||
| tmpQueue.copyDataFrom(&fAtomQueueOut); | |||||
| tmpQueue.copyAndDumpDataFromQueue(fAtomQueueOut, dumpBuf); | |||||
| uint32_t portIndex; | uint32_t portIndex; | ||||
| const LV2_Atom* atom; | const LV2_Atom* atom; | ||||
| const bool hasPortEvent(fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->port_event != nullptr); | const bool hasPortEvent(fUi.handle != nullptr && fUi.descriptor != nullptr && fUi.descriptor->port_event != nullptr); | ||||
| while (tmpQueue.get(&portIndex, &atom)) | |||||
| for (; tmpQueue.get(&atom, &portIndex);) | |||||
| { | { | ||||
| //carla_stdout("OUTPUT message IN GUI REMOVED FROM BUFFER"); | |||||
| carla_stdout("OUTPUT message IN GUI REMOVED FROM BUFFER"); | |||||
| if (fUi.type == PLUGIN_UI_OSC) | |||||
| if (fUi.type == UI::TYPE_OSC) | |||||
| { | { | ||||
| if (pData->osc.data.target != nullptr) | if (pData->osc.data.target != nullptr) | ||||
| { | { | ||||
| QByteArray chunk((const char*)atom, lv2_atom_total_size(atom)); | |||||
| osc_send_lv2_atom_transfer(&pData->osc.data, portIndex, chunk.toBase64().constData()); | |||||
| QByteArray chunk((const char*)atom, static_cast<int>(lv2_atom_total_size(atom))); | |||||
| osc_send_lv2_atom_transfer(pData->osc.data, portIndex, chunk.toBase64().constData()); | |||||
| } | } | ||||
| } | } | ||||
| else if (fUi.type != PLUGIN_UI_NULL) | |||||
| else | |||||
| { | { | ||||
| if (hasPortEvent) | if (hasPortEvent) | ||||
| fUi.descriptor->port_event(fUi.handle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); | fUi.descriptor->port_event(fUi.handle, portIndex, lv2_atom_total_size(atom), CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT, atom); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| if (fUi.handle != nullptr && fUi.descriptor != nullptr) | if (fUi.handle != nullptr && fUi.descriptor != nullptr) | ||||
| { | { | ||||
| @@ -2507,26 +2510,24 @@ public: | |||||
| // ---------------------------------------------------------------------------------------------------- | // ---------------------------------------------------------------------------------------------------- | ||||
| // Message Input | // Message Input | ||||
| #if 0 | |||||
| if (fAtomQueueIn.tryLock()) | if (fAtomQueueIn.tryLock()) | ||||
| { | { | ||||
| if (! fAtomQueueIn.isEmpty()) | if (! fAtomQueueIn.isEmpty()) | ||||
| { | { | ||||
| uint32_t portIndex; | |||||
| const LV2_Atom* atom; | const LV2_Atom* atom; | ||||
| uint32_t portIndex; | |||||
| k = fEventsIn.ctrlIndex; | |||||
| const uint32_t j = fEventsIn.ctrlIndex; | |||||
| while (fAtomQueueIn.get(&portIndex, &atom)) | |||||
| for (; fAtomQueueIn.get(&atom, &portIndex);) | |||||
| { | { | ||||
| carla_debug("Event input message sent to plugin DSP, type %i:\"%s\", size:%i/%i", | carla_debug("Event input message sent to plugin DSP, type %i:\"%s\", size:%i/%i", | ||||
| atom->type, carla_lv2_urid_unmap(this, atom->type), | atom->type, carla_lv2_urid_unmap(this, atom->type), | ||||
| atom->size, lv2_atom_total_size(atom) | |||||
| ); | |||||
| atom->size, lv2_atom_total_size(atom)); | |||||
| if (! lv2_atom_buffer_write(&evInAtomIters[k], 0, 0, atom->type, atom->size, LV2NV_ATOM_BODY_CONST(atom))) | |||||
| if (! lv2_atom_buffer_write(&evInAtomIters[j], 0, 0, atom->type, atom->size, LV2_ATOM_BODY_CONST(atom))) | |||||
| { | { | ||||
| carla_stdout("Event input buffer full, 1 message lost"); | |||||
| carla_stdout("Event input buffer full, at least 1 message lost"); | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -2534,7 +2535,6 @@ public: | |||||
| fAtomQueueIn.unlock(); | fAtomQueueIn.unlock(); | ||||
| } | } | ||||
| #endif | |||||
| // ---------------------------------------------------------------------------------------------------- | // ---------------------------------------------------------------------------------------------------- | ||||
| // MIDI Input (External) | // MIDI Input (External) | ||||
| @@ -2912,7 +2912,6 @@ public: | |||||
| { | { | ||||
| if (fEventsOut.ctrl->type & CARLA_EVENT_DATA_ATOM) | if (fEventsOut.ctrl->type & CARLA_EVENT_DATA_ATOM) | ||||
| { | { | ||||
| //const uint32_t rindex(fEventsOut.ctrl->rindex); | |||||
| const LV2_Atom_Event* ev; | const LV2_Atom_Event* ev; | ||||
| LV2_Atom_Buffer_Iterator iter; | LV2_Atom_Buffer_Iterator iter; | ||||
| @@ -2932,12 +2931,11 @@ public: | |||||
| if (fEventsOut.ctrl->port != nullptr && ev->time.frames >= 0 && ev->body.size <= 0xFF) | if (fEventsOut.ctrl->port != nullptr && ev->time.frames >= 0 && ev->body.size <= 0xFF) | ||||
| fEventsOut.ctrl->port->writeMidiEvent(static_cast<uint32_t>(ev->time.frames), static_cast<uint8_t>(ev->body.size), data); | fEventsOut.ctrl->port->writeMidiEvent(static_cast<uint32_t>(ev->time.frames), static_cast<uint8_t>(ev->body.size), data); | ||||
| } | } | ||||
| #if 0 | |||||
| else if (ev->body.type == CARLA_URI_MAP_ID_ATOM_BLANK) | else if (ev->body.type == CARLA_URI_MAP_ID_ATOM_BLANK) | ||||
| { | { | ||||
| fAtomQueueOut.put(rindex, &ev->body); | |||||
| fAtomQueueOut.put(&ev->body, fEventsOut.ctrl->rindex); | |||||
| } | } | ||||
| #endif | |||||
| lv2_atom_buffer_increment(&iter); | lv2_atom_buffer_increment(&iter); | ||||
| } | } | ||||
| } | } | ||||
| @@ -3938,9 +3936,9 @@ public: | |||||
| case CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM: | case CARLA_URI_MAP_ID_ATOM_TRANSFER_ATOM: | ||||
| case CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT: | case CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT: | ||||
| #if 0 | |||||
| fAtomQueueIn.put(rindex, (const LV2_Atom*)buffer); | |||||
| #endif | |||||
| CARLA_SAFE_ASSERT_RETURN(((const LV2_Atom*)buffer)->size == bufferSize,); | |||||
| fAtomQueueIn.put((const LV2_Atom*)buffer, rindex); | |||||
| break; | break; | ||||
| default: | default: | ||||
| @@ -4633,10 +4631,7 @@ public: | |||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | ||||
| carla_debug("Lv2Plugin::handleTransferAtom(%i, %p)", portIndex, atom); | carla_debug("Lv2Plugin::handleTransferAtom(%i, %p)", portIndex, atom); | ||||
| #if 0 | |||||
| fAtomQueueIn.put(portIndex, atom); | |||||
| #endif | |||||
| return; (void)portIndex; | |||||
| fAtomQueueIn.put(atom, portIndex); | |||||
| } | } | ||||
| void handleUridMap(const LV2_URID urid, const char* const uri) | void handleUridMap(const LV2_URID urid, const char* const uri) | ||||
| @@ -4662,10 +4657,8 @@ private: | |||||
| float** fAudioOutBuffers; | float** fAudioOutBuffers; | ||||
| float* fParamBuffers; | float* fParamBuffers; | ||||
| #if 0 | |||||
| Lv2AtomQueue fAtomQueueIn; | Lv2AtomQueue fAtomQueueIn; | ||||
| Lv2AtomQueue fAtomQueueOut; | Lv2AtomQueue fAtomQueueOut; | ||||
| #endif | |||||
| LV2_Atom_Forge fAtomForge; | LV2_Atom_Forge fAtomForge; | ||||
| Lv2PluginEventData fEventsIn; | Lv2PluginEventData fEventsIn; | ||||
| @@ -79,7 +79,7 @@ struct BridgeShmControl { | |||||
| void* runClient; | void* runClient; | ||||
| char _padClient[32]; | char _padClient[32]; | ||||
| }; | }; | ||||
| RingBuffer ringBuffer; | |||||
| StackRingBuffer ringBuffer; | |||||
| } POST_PACKED_STRUCTURE; | } POST_PACKED_STRUCTURE; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -1,6 +1,5 @@ | |||||
| /* | /* | ||||
| * Carla Ring Buffer based on dssi-vst code | |||||
| * Copyright (C) 2004-2010 Chris Cannam <cannam@all-day-breakfast.com> | |||||
| * Carla Ring Buffer | |||||
| * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | * Copyright (C) 2013-2014 Filipe Coelho <falktx@falktx.com> | ||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| @@ -21,26 +20,45 @@ | |||||
| #include "CarlaUtils.hpp" | #include "CarlaUtils.hpp" | ||||
| //#ifndef RING_BUFFER_SIZE | |||||
| #define RING_BUFFER_SIZE 2048 | |||||
| //#endif | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // RingBuffer struct | |||||
| // RingBuffer structs | |||||
| struct HeapRingBuffer { | |||||
| uint32_t size; | |||||
| int32_t head, tail, written; | |||||
| bool invalidateCommit; | |||||
| char* buf; | |||||
| HeapRingBuffer& operator=(const HeapRingBuffer& rb) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(size == rb.size, *this); | |||||
| size = rb.size; | |||||
| head = rb.head; | |||||
| tail = rb.tail; | |||||
| written = rb.written; | |||||
| invalidateCommit = rb.invalidateCommit; | |||||
| std::memcpy(buf, rb.buf, size); | |||||
| struct RingBuffer { | |||||
| return *this; | |||||
| } | |||||
| }; | |||||
| struct StackRingBuffer { | |||||
| static const uint32_t size = 2048; | |||||
| int32_t head, tail, written; | int32_t head, tail, written; | ||||
| bool invalidateCommit; | bool invalidateCommit; | ||||
| char buf[RING_BUFFER_SIZE]; | |||||
| char buf[size]; | |||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // RingBufferControl class | |||||
| // RingBufferControl templated class | |||||
| class RingBufferControl | |||||
| template <class RingBufferStruct> | |||||
| class RingBufferControlTemplate | |||||
| { | { | ||||
| public: | public: | ||||
| RingBufferControl(RingBuffer* const ringBuf) noexcept | |||||
| RingBufferControlTemplate(RingBufferStruct* const ringBuf) noexcept | |||||
| : fRingBuf(ringBuf) | : fRingBuf(ringBuf) | ||||
| { | { | ||||
| if (ringBuf != nullptr) | if (ringBuf != nullptr) | ||||
| @@ -55,10 +73,12 @@ public: | |||||
| fRingBuf->tail = 0; | fRingBuf->tail = 0; | ||||
| fRingBuf->written = 0; | fRingBuf->written = 0; | ||||
| fRingBuf->invalidateCommit = false; | fRingBuf->invalidateCommit = false; | ||||
| carla_zeroChar(fRingBuf->buf, RING_BUFFER_SIZE); | |||||
| if (fRingBuf->size > 0) | |||||
| carla_zeroChar(fRingBuf->buf, fRingBuf->size); | |||||
| } | } | ||||
| void setRingBuffer(RingBuffer* const ringBuf, const bool reset) noexcept | |||||
| void setRingBuffer(RingBufferStruct* const ringBuf, const bool reset) noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(ringBuf != nullptr,); | CARLA_SAFE_ASSERT_RETURN(ringBuf != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(ringBuf != fRingBuf,); | CARLA_SAFE_ASSERT_RETURN(ringBuf != fRingBuf,); | ||||
| @@ -155,6 +175,7 @@ protected: | |||||
| CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(buf != nullptr,); | CARLA_SAFE_ASSERT_RETURN(buf != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(size != 0,); | CARLA_SAFE_ASSERT_RETURN(size != 0,); | ||||
| CARLA_SAFE_ASSERT_RETURN(size < fRingBuf->size,); | |||||
| // this should not happen | // this should not happen | ||||
| CARLA_ASSERT(fRingBuf->head >= 0); | CARLA_ASSERT(fRingBuf->head >= 0); | ||||
| @@ -169,7 +190,7 @@ protected: | |||||
| const size_t head(static_cast<size_t>(fRingBuf->head)); | const size_t head(static_cast<size_t>(fRingBuf->head)); | ||||
| const size_t tail(static_cast<size_t>(fRingBuf->tail)); | const size_t tail(static_cast<size_t>(fRingBuf->tail)); | ||||
| const size_t wrap((head < tail) ? RING_BUFFER_SIZE : 0); | |||||
| const size_t wrap((head < tail) ? fRingBuf->size : 0); | |||||
| if (head - tail + wrap < size) | if (head - tail + wrap < size) | ||||
| { | { | ||||
| @@ -179,10 +200,10 @@ protected: | |||||
| size_t readto = tail + size; | size_t readto = tail + size; | ||||
| if (readto >= RING_BUFFER_SIZE) | |||||
| if (readto >= fRingBuf->size) | |||||
| { | { | ||||
| readto -= RING_BUFFER_SIZE; | |||||
| const size_t firstpart(RING_BUFFER_SIZE - tail); | |||||
| readto -= fRingBuf->size; | |||||
| const size_t firstpart(fRingBuf->size - tail); | |||||
| std::memcpy(charbuf, fRingBuf->buf + tail, firstpart); | std::memcpy(charbuf, fRingBuf->buf + tail, firstpart); | ||||
| std::memcpy(charbuf + firstpart, fRingBuf->buf, readto); | std::memcpy(charbuf + firstpart, fRingBuf->buf, readto); | ||||
| } | } | ||||
| @@ -199,6 +220,7 @@ protected: | |||||
| CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,); | CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(buf != nullptr,); | CARLA_SAFE_ASSERT_RETURN(buf != nullptr,); | ||||
| CARLA_SAFE_ASSERT_RETURN(size != 0,); | CARLA_SAFE_ASSERT_RETURN(size != 0,); | ||||
| CARLA_SAFE_ASSERT_RETURN(size < fRingBuf->size,); | |||||
| // this should not happen | // this should not happen | ||||
| CARLA_ASSERT(fRingBuf->head >= 0); | CARLA_ASSERT(fRingBuf->head >= 0); | ||||
| @@ -209,7 +231,7 @@ protected: | |||||
| const size_t tail(static_cast<size_t>(fRingBuf->tail)); | const size_t tail(static_cast<size_t>(fRingBuf->tail)); | ||||
| const size_t wrtn(static_cast<size_t>(fRingBuf->written)); | const size_t wrtn(static_cast<size_t>(fRingBuf->written)); | ||||
| const size_t wrap((tail <= wrtn) ? RING_BUFFER_SIZE : 0); | |||||
| const size_t wrap((tail <= wrtn) ? fRingBuf->size : 0); | |||||
| if (tail - wrtn + wrap <= size) | if (tail - wrtn + wrap <= size) | ||||
| { | { | ||||
| @@ -220,10 +242,10 @@ protected: | |||||
| size_t writeto = wrtn + size; | size_t writeto = wrtn + size; | ||||
| if (writeto >= RING_BUFFER_SIZE) | |||||
| if (writeto >= fRingBuf->size) | |||||
| { | { | ||||
| writeto -= RING_BUFFER_SIZE; | |||||
| const size_t firstpart(RING_BUFFER_SIZE - wrtn); | |||||
| writeto -= fRingBuf->size; | |||||
| const size_t firstpart(fRingBuf->size - wrtn); | |||||
| std::memcpy(fRingBuf->buf + wrtn, charbuf, firstpart); | std::memcpy(fRingBuf->buf + wrtn, charbuf, firstpart); | ||||
| std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto); | std::memcpy(fRingBuf->buf, charbuf + firstpart, writeto); | ||||
| } | } | ||||
| @@ -236,10 +258,10 @@ protected: | |||||
| } | } | ||||
| private: | private: | ||||
| RingBuffer* fRingBuf; | |||||
| RingBufferStruct* fRingBuf; | |||||
| CARLA_PREVENT_HEAP_ALLOCATION | CARLA_PREVENT_HEAP_ALLOCATION | ||||
| CARLA_DECLARE_NON_COPY_CLASS(RingBufferControl) | |||||
| CARLA_DECLARE_NON_COPY_CLASS(RingBufferControlTemplate) | |||||
| }; | }; | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -1,6 +1,6 @@ | |||||
| /* | /* | ||||
| * Simple Queue, specially developed for Atom types | * Simple Queue, specially developed for Atom types | ||||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||||
| * | * | ||||
| * This program is free software; you can redistribute it and/or | * This program is free software; you can redistribute it and/or | ||||
| * modify it under the terms of the GNU General Public License as | * modify it under the terms of the GNU General Public License as | ||||
| @@ -25,17 +25,47 @@ | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| class Lv2AtomRingBufferControl : public RingBufferControl | |||||
| class Lv2AtomRingBufferControl : public RingBufferControlTemplate<HeapRingBuffer> | |||||
| { | { | ||||
| public: | public: | ||||
| Lv2AtomRingBufferControl() | Lv2AtomRingBufferControl() | ||||
| : RingBufferControl(&fBuffer) | |||||
| : RingBufferControlTemplate(nullptr) | |||||
| { | { | ||||
| fBuffer.size = 0; | |||||
| fBuffer.buf = nullptr; | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| const LV2_Atom* readAtom(uint32_t* const portIndex) | |||||
| void createBuffer(const uint32_t size) | |||||
| { | |||||
| if (fBuffer.buf != nullptr) | |||||
| delete[] fBuffer.buf; | |||||
| fBuffer.size = size; | |||||
| fBuffer.buf = new char[size]; | |||||
| setRingBuffer(&fBuffer, true); | |||||
| } | |||||
| // used for tmp buffers only | |||||
| void copyDump(HeapRingBuffer& rb, char dumpBuf[]) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(fBuffer.size == 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(fBuffer.buf == nullptr,); | |||||
| fBuffer.buf = dumpBuf; | |||||
| fBuffer.size = rb.size; | |||||
| fBuffer.head = rb.head; | |||||
| fBuffer.tail = rb.tail; | |||||
| fBuffer.written = rb.written; | |||||
| fBuffer.invalidateCommit = rb.invalidateCommit; | |||||
| std::memcpy(dumpBuf, rb.buf, rb.size); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| const LV2_Atom* readAtom(uint32_t* const portIndex) noexcept | |||||
| { | { | ||||
| fRetAtom.atom.size = 0; | fRetAtom.atom.size = 0; | ||||
| fRetAtom.atom.type = 0; | fRetAtom.atom.type = 0; | ||||
| @@ -44,12 +74,12 @@ public: | |||||
| if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0) | if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0) | ||||
| return nullptr; | return nullptr; | ||||
| CARLA_SAFE_ASSERT_RETURN(fRetAtom.atom.size < RING_BUFFER_SIZE, nullptr); | |||||
| CARLA_SAFE_ASSERT_RETURN(fRetAtom.atom.size < kMaxDataSize, nullptr); | |||||
| int32_t index = -1; | int32_t index = -1; | ||||
| tryRead(&index, sizeof(int32_t)); | tryRead(&index, sizeof(int32_t)); | ||||
| if (index == -1) | |||||
| if (index < 0) | |||||
| return nullptr; | return nullptr; | ||||
| if (portIndex != nullptr) | if (portIndex != nullptr) | ||||
| @@ -63,7 +93,7 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) | |||||
| bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) noexcept | |||||
| { | { | ||||
| tryWrite(atom, sizeof(LV2_Atom)); | tryWrite(atom, sizeof(LV2_Atom)); | ||||
| tryWrite(&portIndex, sizeof(int32_t)); | tryWrite(&portIndex, sizeof(int32_t)); | ||||
| @@ -74,11 +104,13 @@ public: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| private: | private: | ||||
| RingBuffer fBuffer; | |||||
| HeapRingBuffer fBuffer; | |||||
| static const size_t kMaxDataSize = 2048; | |||||
| struct RetAtom { | struct RetAtom { | ||||
| LV2_Atom atom; | LV2_Atom atom; | ||||
| char data[RING_BUFFER_SIZE]; | |||||
| char data[kMaxDataSize]; | |||||
| } fRetAtom; | } fRetAtom; | ||||
| friend class Lv2AtomQueue; | friend class Lv2AtomQueue; | ||||
| @@ -96,21 +128,54 @@ public: | |||||
| { | { | ||||
| } | } | ||||
| void copyDataFromQueue(Lv2AtomQueue& queue) | |||||
| // ------------------------------------------------------------------- | |||||
| void createBuffer(const uint32_t size) | |||||
| { | { | ||||
| // lock queue | |||||
| const CarlaMutex::ScopedLocker qsl(queue.fMutex); | |||||
| fRingBufferCtrl.createBuffer(size); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| uint32_t getSize() const noexcept | |||||
| { | |||||
| return fRingBufferCtrl.fBuffer.size; | |||||
| } | |||||
| bool isEmpty() const noexcept | |||||
| { | |||||
| return !fRingBufferCtrl.isDataAvailable(); | |||||
| } | |||||
| // must have been locked before | |||||
| bool get(const LV2_Atom** const atom, uint32_t* const portIndex) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false); | |||||
| if (! fRingBufferCtrl.isDataAvailable()) | |||||
| return false; | |||||
| if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex)) | |||||
| { | { | ||||
| // copy data from queue | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| carla_copyStruct<RingBuffer>(fRingBufferCtrl.fBuffer, queue.fRingBufferCtrl.fBuffer); | |||||
| *atom = retAtom; | |||||
| return true; | |||||
| } | } | ||||
| // reset queque - FIXME? no queue.? | |||||
| queue.fRingBufferCtrl.clear(); | |||||
| return false; | |||||
| } | } | ||||
| // must NOT been locked, we do that here | |||||
| bool put(const LV2_Atom* const atom, const uint32_t portIndex) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false); | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex)); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| void lock() const noexcept | void lock() const noexcept | ||||
| { | { | ||||
| fMutex.lock(); | fMutex.lock(); | ||||
| @@ -126,33 +191,40 @@ public: | |||||
| fMutex.unlock(); | fMutex.unlock(); | ||||
| } | } | ||||
| bool put(const LV2_Atom* const atom, const uint32_t portIndex) | |||||
| // ------------------------------------------------------------------- | |||||
| void copyDataFromQueue(Lv2AtomQueue& queue) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false); | |||||
| // lock source | |||||
| const CarlaMutex::ScopedLocker qsl(queue.fMutex); | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| { | |||||
| // copy data from source | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| fRingBufferCtrl.fBuffer = queue.fRingBufferCtrl.fBuffer; | |||||
| } | |||||
| return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex)); | |||||
| // clear source | |||||
| queue.fRingBufferCtrl.clear(); | |||||
| } | } | ||||
| bool get(const LV2_Atom** const atom, uint32_t* const portIndex) | |||||
| void copyAndDumpDataFromQueue(Lv2AtomQueue& queue, char dumpBuf[]) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false); | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| if (! fRingBufferCtrl.isDataAvailable()) | |||||
| return false; | |||||
| // lock source | |||||
| const CarlaMutex::ScopedLocker qsl(queue.fMutex); | |||||
| if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex)) | |||||
| { | { | ||||
| *atom = retAtom; | |||||
| return true; | |||||
| // copy data from source | |||||
| const CarlaMutex::ScopedLocker sl(fMutex); | |||||
| fRingBufferCtrl.copyDump(queue.fRingBufferCtrl.fBuffer, dumpBuf); | |||||
| } | } | ||||
| return false; | |||||
| // clear source | |||||
| queue.fRingBufferCtrl.clear(); | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | |||||
| private: | private: | ||||
| CarlaMutex fMutex; | CarlaMutex fMutex; | ||||
| Lv2AtomRingBufferControl fRingBufferCtrl; | Lv2AtomRingBufferControl fRingBufferCtrl; | ||||