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 4.8KB

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