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.

239 lines
6.2KB

  1. /*
  2. * Simple Queue, specially developed for Atom types
  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_QUEUE_HPP_INCLUDED
  18. #define LV2_ATOM_QUEUE_HPP_INCLUDED
  19. #include "CarlaMutex.hpp"
  20. #include "CarlaRingBuffer.hpp"
  21. #include "lv2/atom.h"
  22. // -----------------------------------------------------------------------
  23. class Lv2AtomRingBufferControl : public RingBufferControlTemplate<HeapRingBuffer>
  24. {
  25. public:
  26. Lv2AtomRingBufferControl()
  27. : RingBufferControlTemplate(nullptr)
  28. {
  29. fBuffer.size = 0;
  30. fBuffer.buf = nullptr;
  31. }
  32. // -------------------------------------------------------------------
  33. void createBuffer(const uint32_t size)
  34. {
  35. if (fBuffer.buf != nullptr)
  36. delete[] fBuffer.buf;
  37. fBuffer.size = size;
  38. fBuffer.buf = new char[size];
  39. setRingBuffer(&fBuffer, true);
  40. }
  41. // used for tmp buffers only
  42. void copyDump(HeapRingBuffer& rb, char dumpBuf[])
  43. {
  44. CARLA_SAFE_ASSERT_RETURN(fBuffer.size == 0,);
  45. CARLA_SAFE_ASSERT_RETURN(fBuffer.buf == nullptr,);
  46. fBuffer.buf = dumpBuf;
  47. fBuffer.size = rb.size;
  48. fBuffer.head = rb.head;
  49. fBuffer.tail = rb.tail;
  50. fBuffer.written = rb.written;
  51. fBuffer.invalidateCommit = rb.invalidateCommit;
  52. std::memcpy(dumpBuf, rb.buf, rb.size);
  53. }
  54. // -------------------------------------------------------------------
  55. const LV2_Atom* readAtom(uint32_t* const portIndex) noexcept
  56. {
  57. fRetAtom.atom.size = 0;
  58. fRetAtom.atom.type = 0;
  59. tryRead(&fRetAtom.atom, sizeof(LV2_Atom));
  60. if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0)
  61. return nullptr;
  62. CARLA_SAFE_ASSERT_RETURN(fRetAtom.atom.size < kMaxDataSize, nullptr);
  63. int32_t index = -1;
  64. tryRead(&index, sizeof(int32_t));
  65. if (index < 0)
  66. return nullptr;
  67. if (portIndex != nullptr)
  68. *portIndex = static_cast<uint32_t>(index);
  69. carla_zeroChar(fRetAtom.data, fRetAtom.atom.size);
  70. tryRead(fRetAtom.data, fRetAtom.atom.size);
  71. return &fRetAtom.atom;
  72. }
  73. // -------------------------------------------------------------------
  74. bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) noexcept
  75. {
  76. tryWrite(atom, sizeof(LV2_Atom));
  77. tryWrite(&portIndex, sizeof(int32_t));
  78. tryWrite(LV2_ATOM_BODY_CONST(atom), atom->size);
  79. return commitWrite();
  80. }
  81. // -------------------------------------------------------------------
  82. private:
  83. HeapRingBuffer fBuffer;
  84. static const size_t kMaxDataSize = 2048;
  85. struct RetAtom {
  86. LV2_Atom atom;
  87. char data[kMaxDataSize];
  88. } fRetAtom;
  89. friend class Lv2AtomQueue;
  90. CARLA_PREVENT_HEAP_ALLOCATION
  91. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomRingBufferControl)
  92. };
  93. // -----------------------------------------------------------------------
  94. class Lv2AtomQueue
  95. {
  96. public:
  97. Lv2AtomQueue()
  98. {
  99. }
  100. // -------------------------------------------------------------------
  101. void createBuffer(const uint32_t size)
  102. {
  103. fRingBufferCtrl.createBuffer(size);
  104. }
  105. // -------------------------------------------------------------------
  106. uint32_t getSize() const noexcept
  107. {
  108. return fRingBufferCtrl.fBuffer.size;
  109. }
  110. bool isEmpty() const noexcept
  111. {
  112. return !fRingBufferCtrl.isDataAvailable();
  113. }
  114. // must have been locked before
  115. bool get(const LV2_Atom** const atom, uint32_t* const portIndex)
  116. {
  117. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false);
  118. if (! fRingBufferCtrl.isDataAvailable())
  119. return false;
  120. if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex))
  121. {
  122. *atom = retAtom;
  123. return true;
  124. }
  125. return false;
  126. }
  127. // must NOT been locked, we do that here
  128. bool put(const LV2_Atom* const atom, const uint32_t portIndex)
  129. {
  130. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  131. const CarlaMutex::ScopedLocker sl(fMutex);
  132. return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex));
  133. }
  134. // -------------------------------------------------------------------
  135. void lock() const noexcept
  136. {
  137. fMutex.lock();
  138. }
  139. bool tryLock() const noexcept
  140. {
  141. return fMutex.tryLock();
  142. }
  143. void unlock() const noexcept
  144. {
  145. fMutex.unlock();
  146. }
  147. // -------------------------------------------------------------------
  148. void copyDataFromQueue(Lv2AtomQueue& queue)
  149. {
  150. // lock source
  151. const CarlaMutex::ScopedLocker qsl(queue.fMutex);
  152. {
  153. // copy data from source
  154. const CarlaMutex::ScopedLocker sl(fMutex);
  155. fRingBufferCtrl.fBuffer = queue.fRingBufferCtrl.fBuffer;
  156. }
  157. // clear source
  158. queue.fRingBufferCtrl.clear();
  159. }
  160. void copyAndDumpDataFromQueue(Lv2AtomQueue& queue, char dumpBuf[])
  161. {
  162. // lock source
  163. const CarlaMutex::ScopedLocker qsl(queue.fMutex);
  164. {
  165. // copy data from source
  166. const CarlaMutex::ScopedLocker sl(fMutex);
  167. fRingBufferCtrl.copyDump(queue.fRingBufferCtrl.fBuffer, dumpBuf);
  168. }
  169. // clear source
  170. queue.fRingBufferCtrl.clear();
  171. }
  172. // -------------------------------------------------------------------
  173. private:
  174. CarlaMutex fMutex;
  175. Lv2AtomRingBufferControl fRingBufferCtrl;
  176. CARLA_PREVENT_HEAP_ALLOCATION
  177. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomQueue)
  178. };
  179. // -----------------------------------------------------------------------
  180. #endif // LV2_ATOM_QUEUE_HPP_INCLUDED