Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
6.0KB

  1. /*
  2. * LV2 Atom Ring Buffer
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef LV2_ATOM_RING_BUFFER_HPP_INCLUDED
  18. #define LV2_ATOM_RING_BUFFER_HPP_INCLUDED
  19. #include "CarlaMutex.hpp"
  20. #include "CarlaRingBuffer.hpp"
  21. #include "lv2/atom.h"
  22. // -----------------------------------------------------------------------
  23. class Lv2AtomRingBuffer : public CarlaRingBuffer<HeapBuffer>
  24. {
  25. public:
  26. Lv2AtomRingBuffer() noexcept
  27. : CarlaRingBuffer<HeapBuffer>(),
  28. fNeedsDataDelete(true)
  29. {
  30. carla_zeroStruct(fHeapBuffer);
  31. }
  32. Lv2AtomRingBuffer(Lv2AtomRingBuffer& ringBuf, uint8_t buf[]) noexcept
  33. : CarlaRingBuffer<HeapBuffer>(),
  34. fNeedsDataDelete(false)
  35. {
  36. fHeapBuffer.buf = buf;
  37. fHeapBuffer.size = ringBuf.fHeapBuffer.size;
  38. {
  39. const CarlaMutexLocker cml(ringBuf.fMutex);
  40. fHeapBuffer.copyDataFrom(ringBuf.fHeapBuffer);
  41. ringBuf.clear();
  42. }
  43. setRingBuffer(&fHeapBuffer, false);
  44. }
  45. ~Lv2AtomRingBuffer() noexcept
  46. {
  47. if (fHeapBuffer.buf == nullptr || ! fNeedsDataDelete)
  48. return;
  49. delete[] fHeapBuffer.buf;
  50. fHeapBuffer.buf = nullptr;
  51. }
  52. // -------------------------------------------------------------------
  53. void createBuffer(const uint32_t size) noexcept
  54. {
  55. CARLA_SAFE_ASSERT_RETURN(fHeapBuffer.buf == nullptr,);
  56. CARLA_SAFE_ASSERT_RETURN(fNeedsDataDelete,);
  57. CARLA_SAFE_ASSERT_RETURN(size > 0,);
  58. const uint32_t p2size(carla_nextPowerOf2(size));
  59. try {
  60. fHeapBuffer.buf = new uint8_t[p2size];
  61. } CARLA_SAFE_EXCEPTION_RETURN("Lv2AtomRingBuffer::createBuffer",);
  62. fHeapBuffer.size = p2size;
  63. setRingBuffer(&fHeapBuffer, true);
  64. }
  65. void deleteBuffer() noexcept
  66. {
  67. CARLA_SAFE_ASSERT_RETURN(fHeapBuffer.buf != nullptr,);
  68. CARLA_SAFE_ASSERT_RETURN(fNeedsDataDelete,);
  69. setRingBuffer(nullptr, false);
  70. delete[] fHeapBuffer.buf;
  71. fHeapBuffer.buf = nullptr;
  72. fHeapBuffer.size = 0;
  73. }
  74. uint32_t getSize() const noexcept
  75. {
  76. return fHeapBuffer.size;
  77. }
  78. // -------------------------------------------------------------------
  79. bool tryLock() const noexcept
  80. {
  81. return fMutex.tryLock();
  82. }
  83. void unlock() const noexcept
  84. {
  85. fMutex.unlock();
  86. }
  87. // -------------------------------------------------------------------
  88. // NOTE: must have been locked before
  89. bool get(const LV2_Atom*& atom, uint32_t& portIndex) noexcept
  90. {
  91. CARLA_SAFE_ASSERT_RETURN(atom != nullptr, false);
  92. if (const LV2_Atom* const retAtom = readAtom(portIndex))
  93. {
  94. atom = retAtom;
  95. return true;
  96. }
  97. return false;
  98. }
  99. // NOTE: must NOT been locked, we do that here
  100. bool put(const LV2_Atom* const atom, const uint32_t portIndex) noexcept
  101. {
  102. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  103. const CarlaMutexLocker cml(fMutex);
  104. return writeAtom(atom, static_cast<int32_t>(portIndex));
  105. }
  106. // NOTE: must NOT been locked, we do that here
  107. bool putChunk(const LV2_Atom* const atom, const void* const data, const uint32_t portIndex) noexcept
  108. {
  109. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  110. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  111. const CarlaMutexLocker cml(fMutex);
  112. return writeAtomChunk(atom, data, static_cast<int32_t>(portIndex));
  113. }
  114. protected:
  115. // -------------------------------------------------------------------
  116. const LV2_Atom* readAtom(uint32_t& portIndex) noexcept
  117. {
  118. fRetAtom.atom.size = 0;
  119. fRetAtom.atom.type = 0;
  120. if (! tryRead(&fRetAtom.atom, sizeof(LV2_Atom)))
  121. return nullptr;
  122. if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0)
  123. return nullptr;
  124. CARLA_SAFE_ASSERT_RETURN(fRetAtom.atom.size < kMaxAtomDataSize, nullptr);
  125. int32_t index = -1;
  126. if (! tryRead(&index, sizeof(int32_t)))
  127. return nullptr;
  128. if (index < 0)
  129. return nullptr;
  130. if (! tryRead(fRetAtom.data, fRetAtom.atom.size))
  131. return nullptr;
  132. portIndex = static_cast<uint32_t>(index);
  133. return &fRetAtom.atom;
  134. }
  135. // -------------------------------------------------------------------
  136. bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) noexcept
  137. {
  138. tryWrite(atom, sizeof(LV2_Atom));
  139. tryWrite(&portIndex, sizeof(int32_t));
  140. tryWrite(LV2_ATOM_BODY_CONST(atom), atom->size);
  141. return commitWrite();
  142. }
  143. bool writeAtomChunk(const LV2_Atom* const atom, const void* const data, const int32_t portIndex) noexcept
  144. {
  145. tryWrite(atom, sizeof(LV2_Atom));
  146. tryWrite(&portIndex, sizeof(int32_t));
  147. tryWrite(data, atom->size);
  148. return commitWrite();
  149. }
  150. // -------------------------------------------------------------------
  151. private:
  152. CarlaMutex fMutex;
  153. HeapBuffer fHeapBuffer;
  154. const bool fNeedsDataDelete;
  155. static const size_t kMaxAtomDataSize = 8192;
  156. struct RetAtom {
  157. LV2_Atom atom;
  158. char data[kMaxAtomDataSize];
  159. } fRetAtom;
  160. friend class Lv2AtomQueue;
  161. CARLA_PREVENT_HEAP_ALLOCATION
  162. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomRingBuffer)
  163. };
  164. // -----------------------------------------------------------------------
  165. #endif // LV2_ATOM_RING_BUFFER_HPP_INCLUDED