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.4KB

11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
11 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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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()
  27. : RingBufferControl(nullptr),
  28. fIsDummy(false)
  29. {
  30. fBuffer.size = 0;
  31. fBuffer.buf = nullptr;
  32. }
  33. ~Lv2AtomRingBufferControl()
  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)
  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[])
  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()
  123. {
  124. }
  125. // -------------------------------------------------------------------
  126. void createBuffer(const uint32_t size)
  127. {
  128. fRingBufferCtrl.createBuffer(size);
  129. }
  130. // -------------------------------------------------------------------
  131. uint32_t getSize() const noexcept
  132. {
  133. return fRingBufferCtrl.fBuffer.size;
  134. }
  135. bool isEmpty() const noexcept
  136. {
  137. return (fRingBufferCtrl.fBuffer.buf == nullptr || !fRingBufferCtrl.isDataAvailable());
  138. }
  139. // must have been locked before
  140. bool get(const LV2_Atom** const atom, uint32_t* const portIndex)
  141. {
  142. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false);
  143. if (! fRingBufferCtrl.isDataAvailable())
  144. return false;
  145. if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex))
  146. {
  147. *atom = retAtom;
  148. return true;
  149. }
  150. return false;
  151. }
  152. // must NOT been locked, we do that here
  153. bool put(const LV2_Atom* const atom, const uint32_t portIndex)
  154. {
  155. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  156. const CarlaMutex::ScopedLocker sl(fMutex);
  157. return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex));
  158. }
  159. // must NOT been locked, we do that here
  160. bool putChunk(const LV2_Atom* const atom, const void* const data, const uint32_t portIndex)
  161. {
  162. CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);
  163. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  164. const CarlaMutex::ScopedLocker sl(fMutex);
  165. return fRingBufferCtrl.writeAtomChunk(atom, data, static_cast<int32_t>(portIndex));
  166. }
  167. // -------------------------------------------------------------------
  168. void lock() const noexcept
  169. {
  170. fMutex.lock();
  171. }
  172. bool tryLock() const noexcept
  173. {
  174. return fMutex.tryLock();
  175. }
  176. void unlock() const noexcept
  177. {
  178. fMutex.unlock();
  179. }
  180. // -------------------------------------------------------------------
  181. void copyDataFromQueue(Lv2AtomQueue& queue)
  182. {
  183. // lock source
  184. const CarlaMutex::ScopedLocker qsl(queue.fMutex);
  185. {
  186. // copy data from source
  187. const CarlaMutex::ScopedLocker sl(fMutex);
  188. fRingBufferCtrl.fBuffer = queue.fRingBufferCtrl.fBuffer;
  189. }
  190. // clear source
  191. queue.fRingBufferCtrl.clear();
  192. }
  193. void copyAndDumpDataFromQueue(Lv2AtomQueue& queue, char dumpBuf[])
  194. {
  195. // lock source
  196. const CarlaMutex::ScopedLocker qsl(queue.fMutex);
  197. {
  198. // copy data from source
  199. const CarlaMutex::ScopedLocker sl(fMutex);
  200. fRingBufferCtrl.copyDump(queue.fRingBufferCtrl.fBuffer, dumpBuf);
  201. }
  202. // clear source
  203. queue.fRingBufferCtrl.clear();
  204. }
  205. // -------------------------------------------------------------------
  206. private:
  207. CarlaMutex fMutex;
  208. Lv2AtomRingBufferControl fRingBufferCtrl;
  209. CARLA_PREVENT_HEAP_ALLOCATION
  210. CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomQueue)
  211. };
  212. // -----------------------------------------------------------------------
  213. #endif // LV2_ATOM_QUEUE_HPP_INCLUDED