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.

195 lines
4.8KB

  1. /*
  2. * Simple Queue, specially developed for Atom types
  3. * Copyright (C) 2012-2013 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 GPL.txt file
  16. */
  17. #ifndef LV2_ATOM_QUEUE_HPP_INCLUDED
  18. #define LV2_ATOM_QUEUE_HPP_INCLUDED
  19. #include "CarlaLv2Utils.hpp"
  20. #include "CarlaMutex.hpp"
  21. // -----------------------------------------------------------------------
  22. class Lv2AtomQueue
  23. {
  24. public:
  25. Lv2AtomQueue()
  26. : fIndex(0),
  27. fIndexPool(0),
  28. fEmpty(true),
  29. fFull(false)
  30. {
  31. std::memset(fDataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
  32. }
  33. void copyDataFrom(Lv2AtomQueue* const queue)
  34. {
  35. // lock mutexes
  36. queue->lock();
  37. lock();
  38. // copy data from queue
  39. std::memcpy(fData, queue->fData, sizeof(DataType)*MAX_SIZE);
  40. std::memcpy(fDataPool, queue->fDataPool, sizeof(unsigned char)*MAX_POOL_SIZE);
  41. fIndex = queue->fIndex;
  42. fIndexPool = queue->fIndexPool;
  43. fEmpty = queue->fEmpty;
  44. fFull = queue->fFull;
  45. // unlock our mutex, no longer needed
  46. unlock();
  47. // reset queque
  48. std::memset(queue->fData, 0, sizeof(DataType)*MAX_SIZE);
  49. std::memset(queue->fDataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
  50. queue->fIndex = queue->fIndexPool = 0;
  51. queue->fEmpty = true;
  52. queue->fFull = false;
  53. // unlock queque mutex
  54. queue->unlock();
  55. }
  56. bool isEmpty() const
  57. {
  58. return fEmpty;
  59. }
  60. bool isFull() const
  61. {
  62. return fFull;
  63. }
  64. void lock()
  65. {
  66. fMutex.lock();
  67. }
  68. bool tryLock()
  69. {
  70. return fMutex.tryLock();
  71. }
  72. void unlock()
  73. {
  74. fMutex.unlock();
  75. }
  76. bool put(const uint32_t portIndex, const LV2_Atom* const atom)
  77. {
  78. CARLA_ASSERT(atom != nullptr && atom->size > 0);
  79. CARLA_ASSERT(fIndexPool + atom->size < MAX_POOL_SIZE); // overflow
  80. if (fFull || atom == nullptr || fIndexPool + atom->size >= MAX_POOL_SIZE)
  81. return false;
  82. if (atom->size == 0)
  83. return true;
  84. bool ret = false;
  85. lock();
  86. for (unsigned short i=0; i < MAX_SIZE; ++i)
  87. {
  88. if (fData[i].size == 0)
  89. {
  90. fData[i].portIndex = portIndex;
  91. fData[i].size = atom->size;
  92. fData[i].type = atom->type;
  93. fData[i].poolOffset = fIndexPool;
  94. std::memcpy(fDataPool + fIndexPool, LV2NV_ATOM_BODY_CONST(atom), atom->size);
  95. fEmpty = false;
  96. fFull = (i == MAX_SIZE-1);
  97. fIndexPool += atom->size;
  98. ret = true;
  99. break;
  100. }
  101. }
  102. unlock();
  103. return ret;
  104. }
  105. // needs to be locked first!
  106. bool get(uint32_t* const portIndex, const LV2_Atom** const atom)
  107. {
  108. CARLA_ASSERT(portIndex != nullptr && atom != nullptr);
  109. if (fEmpty || portIndex == nullptr || atom == nullptr)
  110. return false;
  111. fFull = false;
  112. if (fData[fIndex].size == 0)
  113. {
  114. fIndex = fIndexPool = 0;
  115. fEmpty = true;
  116. unlock();
  117. return false;
  118. }
  119. fRetAtom.atom.size = fData[fIndex].size;
  120. fRetAtom.atom.type = fData[fIndex].type;
  121. std::memcpy(fRetAtom.data, fDataPool + fData[fIndex].poolOffset, fData[fIndex].size);
  122. *portIndex = fData[fIndex].portIndex;
  123. *atom = (LV2_Atom*)&fRetAtom;
  124. fData[fIndex].portIndex = 0;
  125. fData[fIndex].size = 0;
  126. fData[fIndex].type = 0;
  127. fData[fIndex].poolOffset = 0;
  128. fEmpty = false;
  129. ++fIndex;
  130. return true;
  131. }
  132. private:
  133. struct DataType {
  134. size_t size;
  135. uint32_t type;
  136. uint32_t portIndex;
  137. uint32_t poolOffset;
  138. DataType()
  139. : size(0),
  140. type(0),
  141. portIndex(0),
  142. poolOffset(0) {}
  143. };
  144. static const unsigned short MAX_SIZE = 128;
  145. static const unsigned short MAX_POOL_SIZE = 8192;
  146. DataType fData[MAX_SIZE];
  147. unsigned char fDataPool[MAX_POOL_SIZE];
  148. struct RetAtom {
  149. LV2_Atom atom;
  150. unsigned char data[MAX_POOL_SIZE];
  151. } fRetAtom;
  152. unsigned short fIndex, fIndexPool;
  153. bool fEmpty, fFull;
  154. CarlaMutex fMutex;
  155. };
  156. #endif // LV2_ATOM_QUEUE_HPP_INCLUDED