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.

193 lines
4.7KB

  1. /*
  2. * Simple Queue, specially developed for Atom types
  3. * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #ifndef __LV2_ATOM_QUEUE_HPP__
  18. #define __LV2_ATOM_QUEUE_HPP__
  19. #include "carla_utils.hpp"
  20. #include "lv2/atom.h"
  21. #include <cstring> // memcpy, memset
  22. #include <pthread.h>
  23. class Lv2AtomQueue
  24. {
  25. public:
  26. Lv2AtomQueue()
  27. : mutex(PTHREAD_MUTEX_INITIALIZER)
  28. {
  29. index = indexPool = 0;
  30. empty = true;
  31. full = false;
  32. ::memset(dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
  33. }
  34. void copyDataFrom(Lv2AtomQueue* const queue)
  35. {
  36. // lock mutexes
  37. queue->lock();
  38. lock();
  39. // copy data from queue
  40. ::memcpy(data, queue->data, sizeof(datatype)*MAX_SIZE);
  41. ::memcpy(dataPool, queue->dataPool, sizeof(unsigned char)*MAX_POOL_SIZE);
  42. index = queue->index;
  43. indexPool = queue->indexPool;
  44. empty = queue->empty;
  45. full = queue->full;
  46. // unlock our mutex, no longer needed
  47. unlock();
  48. // reset queque
  49. ::memset(queue->data, 0, sizeof(datatype)*MAX_SIZE);
  50. ::memset(queue->dataPool, 0, sizeof(unsigned char)*MAX_POOL_SIZE);
  51. queue->index = queue->indexPool = 0;
  52. queue->empty = true;
  53. queue->full = false;
  54. // unlock queque mutex
  55. queue->unlock();
  56. }
  57. bool isEmpty()
  58. {
  59. return empty;
  60. }
  61. bool isFull()
  62. {
  63. return full;
  64. }
  65. bool lock()
  66. {
  67. return (pthread_mutex_lock(&mutex) == 0);
  68. }
  69. bool tryLock()
  70. {
  71. return (pthread_mutex_trylock(&mutex) == 0);
  72. }
  73. bool unlock()
  74. {
  75. return (pthread_mutex_unlock(&mutex) == 0);
  76. }
  77. void put(const uint32_t portIndex, const LV2_Atom* const atom)
  78. {
  79. CARLA_ASSERT(atom && atom->size > 0);
  80. CARLA_ASSERT(indexPool + atom->size < MAX_POOL_SIZE); // overflow
  81. if (full || atom->size == 0 || indexPool + atom->size >= MAX_POOL_SIZE)
  82. return;
  83. lock();
  84. for (unsigned short i=0; i < MAX_SIZE; i++)
  85. {
  86. if (data[i].size == 0)
  87. {
  88. data[i].portIndex = portIndex;
  89. data[i].size = atom->size;
  90. data[i].type = atom->type;
  91. data[i].poolOffset = indexPool;
  92. ::memcpy(dataPool + indexPool, (const unsigned char*)LV2_ATOM_BODY_CONST(atom), atom->size);
  93. empty = false;
  94. full = (i == MAX_SIZE-1);
  95. indexPool += atom->size;
  96. break;
  97. }
  98. }
  99. unlock();
  100. }
  101. bool get(uint32_t* const portIndex, const LV2_Atom** const atom)
  102. {
  103. CARLA_ASSERT(portIndex && atom);
  104. if (empty || ! (portIndex && atom))
  105. return false;
  106. if (! tryLock())
  107. return false;
  108. full = false;
  109. if (data[index].size == 0)
  110. {
  111. index = indexPool = 0;
  112. empty = true;
  113. unlock();
  114. return false;
  115. }
  116. retAtom.atom.size = data[index].size;
  117. retAtom.atom.type = data[index].type;
  118. ::memcpy(retAtom.data, dataPool + data[index].poolOffset, data[index].size);
  119. *portIndex = data[index].portIndex;
  120. *atom = (LV2_Atom*)&retAtom;
  121. data[index].portIndex = 0;
  122. data[index].size = 0;
  123. data[index].type = 0;
  124. data[index].poolOffset = 0;
  125. index++;
  126. empty = false;
  127. unlock();
  128. return true;
  129. }
  130. private:
  131. struct datatype {
  132. size_t size;
  133. uint32_t type;
  134. uint32_t portIndex;
  135. uint32_t poolOffset;
  136. datatype()
  137. : size(0),
  138. type(0),
  139. portIndex(0),
  140. poolOffset(0) {}
  141. };
  142. static const unsigned short MAX_SIZE = 128;
  143. static const unsigned short MAX_POOL_SIZE = 8192;
  144. datatype data[MAX_SIZE];
  145. unsigned char dataPool[MAX_POOL_SIZE];
  146. struct {
  147. LV2_Atom atom;
  148. unsigned char data[MAX_POOL_SIZE];
  149. } retAtom;
  150. unsigned short index, indexPool;
  151. bool empty, full;
  152. pthread_mutex_t mutex;
  153. };
  154. #endif // __LV2_ATOM_QUEUE_HPP__