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.

Lv2AtomQueue.hpp 7.5KB

11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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 RingBufferControl<HeapRingBuffer>
  24. {
  25. public:
  26. Lv2AtomRingBufferControl() noexcept
  27. : RingBufferControl<HeapRingBuffer>(nullptr),
  28. fIsDummy(false)
  29. {
  30. fBuffer.size = 0;
  31. fBuffer.buf = nullptr;
  32. }
  33. ~Lv2AtomRingBufferControl() noexcept
  34. {
  35. if (fBuffer.buf != nullptr && ! fIsDummy)
  36. {
  37. delete[] fBuffer.buf;
  38. fBuffer.buf = nullptr;
  39. }
  40. }
  41. // -------------------------------------------------------------------
  42. void createBuffer(const uint32_t size) noexcept
  43. {
  44. if (fBuffer.buf != nullptr)
  45. {
  46. if (! fIsDummy)
  47. delete[] fBuffer.buf;
  48. fBuffer.buf = nullptr;
  49. }
  50. // shouldn't really happen please...
  51. CARLA_SAFE_ASSERT_RETURN(size > 0,);
  52. fBuffer.size = size;
  53. fBuffer.buf = new char[size];
  54. setRingBuffer(&fBuffer, true);
  55. }
  56. // used for tmp buffers only
  57. void copyDump(HeapRingBuffer& rb, char dumpBuf[]) noexcept
  58. {
  59. CARLA_SAFE_ASSERT_RETURN(fBuffer.size == 0,);
  60. CARLA_SAFE_ASSERT_RETURN(fBuffer.buf == nullptr,);
  61. fBuffer.buf = dumpBuf;
  62. fBuffer.size = rb.size;
  63. fBuffer.head = rb.head;
  64. fBuffer.tail = rb.tail;
  65. fBuffer.written = rb.written;
  66. fBuffer.invalidateCommit = rb.invalidateCommit;
  67. fIsDummy = true;
  68. std::memcpy(dumpBuf, rb.buf, rb.size);
  69. setRingBuffer(&fBuffer, false);
  70. }
  71. // -------------------------------------------------------------------
  72. const LV2_Atom* readAtom(uint32_t* const portIndex) noexcept
  73. {
  74. fRetAtom.atom.size = 0;
  75. fRetAtom.atom.type = 0;
  76. tryRead(&fRetAtom.atom, sizeof(LV2_Atom));
  77. if (fRetAtom.atom.size == 0 || fRetAtom.atom.type == 0)
  78. return nullptr;
  79. CARLA_SAFE_ASSERT_RETURN(fRetAtom.atom.size < kMaxDataSize, nullptr);
  80. int32_t index = -1;
  81. tryRead(&index, sizeof(int32_t));
  82. if (index < 0)
  83. return nullptr;
  84. if (portIndex != nullptr)
  85. *portIndex = static_cast<uint32_t>(index);
  86. carla_zeroChar(fRetAtom.data, fRetAtom.atom.size);
  87. tryRead(fRetAtom.data, fRetAtom.atom.size);
  88. return &fRetAtom.atom;
  89. }
  90. // -------------------------------------------------------------------
  91. bool writeAtom(const LV2_Atom* const atom, const int32_t portIndex) noexcept
  92. {
  93. tryWrite(atom, sizeof(LV2_Atom));
  94. tryWrite(&portIndex, sizeof(int32_t));
  95. tryWrite(LV2_ATOM_BODY_CONST(atom), atom->size);
  96. return commitWrite();
  97. }
  98. bool writeAtomChunk(const LV2_Atom* const atom, const void* const data, const int32_t portIndex) noexcept
  99. {
  100. tryWrite(atom, sizeof(LV2_Atom));
  101. tryWrite(&portIndex, sizeof(int32_t));
  102. tryWrite(data, atom->size);
  103. return commitWrite();
  104. }
  105. // -------------------------------------------------------------------
  106. private:
  107. HeapRingBuffer fBuffer;
  108. bool fIsDummy;
  109. static const size_t kMaxDataSize = 8192;
  110. struct RetAtom {
  111. LV2_Atom atom;
  112. char data[kMaxDataSize];
  113. } fRetAtom;
  114. friend class Lv2AtomQueue;
  115. CARLA_PREVENT_HEAP_ALLOCATION
  116. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomRingBufferControl)
  117. };
  118. // -----------------------------------------------------------------------
  119. class Lv2AtomQueue
  120. {
  121. public:
  122. Lv2AtomQueue() noexcept {}
  123. // -------------------------------------------------------------------
  124. void createBuffer(const uint32_t size) noexcept
  125. {
  126. fRingBufferCtrl.createBuffer(size);
  127. }
  128. // -------------------------------------------------------------------
  129. uint32_t getSize() const noexcept
  130. {
  131. return fRingBufferCtrl.fBuffer.size;
  132. }
  133. bool isEmpty() const noexcept
  134. {
  135. return (fRingBufferCtrl.fBuffer.buf == nullptr || !fRingBufferCtrl.isDataAvailable());
  136. }
  137. // must have been locked before
  138. bool get(const LV2_Atom** const atom, uint32_t* const portIndex) noexcept
  139. {
  140. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false);
  141. if (! fRingBufferCtrl.isDataAvailable())
  142. return false;
  143. if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex))
  144. {
  145. *atom = retAtom;
  146. return true;
  147. }
  148. return false;
  149. }
  150. // must NOT been locked, we do that here
  151. bool put(const LV2_Atom* const atom, const uint32_t portIndex) noexcept
  152. {
  153. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  154. const CarlaMutexLocker cml(fMutex);
  155. return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex));
  156. }
  157. // must NOT been locked, we do that here
  158. bool putChunk(const LV2_Atom* const atom, const void* const data, const uint32_t portIndex) noexcept
  159. {
  160. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  161. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  162. const CarlaMutexLocker cml(fMutex);
  163. return fRingBufferCtrl.writeAtomChunk(atom, data, static_cast<int32_t>(portIndex));
  164. }
  165. // -------------------------------------------------------------------
  166. void lock() const noexcept
  167. {
  168. fMutex.lock();
  169. }
  170. bool tryLock() const noexcept
  171. {
  172. return fMutex.tryLock();
  173. }
  174. void unlock() const noexcept
  175. {
  176. fMutex.unlock();
  177. }
  178. // -------------------------------------------------------------------
  179. void copyDataFromQueue(Lv2AtomQueue& queue) noexcept
  180. {
  181. // lock source
  182. const CarlaMutexLocker cml1(queue.fMutex);
  183. {
  184. // copy data from source
  185. const CarlaMutexLocker cml2(fMutex);
  186. fRingBufferCtrl.fBuffer = queue.fRingBufferCtrl.fBuffer;
  187. }
  188. // clear source
  189. queue.fRingBufferCtrl.clear();
  190. }
  191. void copyAndDumpDataFromQueue(Lv2AtomQueue& queue, char dumpBuf[]) noexcept
  192. {
  193. // lock source
  194. const CarlaMutexLocker cml1(queue.fMutex);
  195. {
  196. // copy data from source
  197. const CarlaMutexLocker cml2(fMutex);
  198. fRingBufferCtrl.copyDump(queue.fRingBufferCtrl.fBuffer, dumpBuf);
  199. }
  200. // clear source
  201. queue.fRingBufferCtrl.clear();
  202. }
  203. // -------------------------------------------------------------------
  204. private:
  205. CarlaMutex fMutex;
  206. Lv2AtomRingBufferControl fRingBufferCtrl;
  207. CARLA_PREVENT_HEAP_ALLOCATION
  208. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomQueue)
  209. };
  210. // -----------------------------------------------------------------------
  211. #endif // LV2_ATOM_QUEUE_HPP_INCLUDED