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.

234 lines
5.8KB

  1. /*
  2. * Carla Bridge utils imported from dssi-vst code
  3. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
  4. * Copyright (C) 2004-2010 Chris Cannam <cannam@all-day-breakfast.com>
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License as
  8. * published by the Free Software Foundation; either version 2 of
  9. * the License, or any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * For a full copy of the GNU General Public License see the GPL.txt file
  17. */
  18. #ifndef __CARLA_BRIDGE_UTILS_HPP__
  19. #define __CARLA_BRIDGE_UTILS_HPP__
  20. #include "CarlaUtils.hpp"
  21. #include <semaphore.h>
  22. #define BRIDGE_SHM_RING_BUFFER_SIZE 2048
  23. #ifndef BUILD_BRIDGE
  24. /*!
  25. * TODO.
  26. */
  27. enum PluginBridgeInfoType {
  28. kPluginBridgeAudioCount,
  29. kPluginBridgeMidiCount,
  30. kPluginBridgeParameterCount,
  31. kPluginBridgeProgramCount,
  32. kPluginBridgeMidiProgramCount,
  33. kPluginBridgePluginInfo,
  34. kPluginBridgeParameterInfo,
  35. kPluginBridgeParameterData,
  36. kPluginBridgeParameterRanges,
  37. kPluginBridgeProgramInfo,
  38. kPluginBridgeMidiProgramInfo,
  39. kPluginBridgeConfigure,
  40. kPluginBridgeSetParameterValue,
  41. kPluginBridgeSetDefaultValue,
  42. kPluginBridgeSetProgram,
  43. kPluginBridgeSetMidiProgram,
  44. kPluginBridgeSetCustomData,
  45. kPluginBridgeSetChunkData,
  46. kPluginBridgeUpdateNow,
  47. kPluginBridgeError
  48. };
  49. #endif
  50. enum PluginBridgeOpcode {
  51. kPluginBridgeOpcodeNull = 0,
  52. kPluginBridgeOpcodeReadyWait = 1,
  53. kPluginBridgeOpcodeBufferSize = 2,
  54. kPluginBridgeOpcodeSampleRate = 3,
  55. kPluginBridgeOpcodeProcess = 4
  56. };
  57. /*!
  58. * TODO.
  59. */
  60. struct BridgeRingBuffer {
  61. int head;
  62. int tail;
  63. int written;
  64. bool invalidateCommit;
  65. char buf[BRIDGE_SHM_RING_BUFFER_SIZE];
  66. };
  67. /*!
  68. * TODO.
  69. */
  70. struct BridgeShmControl {
  71. // 32 and 64-bit binaries align semaphores differently.
  72. // Let's make sure there's plenty of room for either one.
  73. union {
  74. sem_t runServer;
  75. char _alignServer[32];
  76. };
  77. union {
  78. sem_t runClient;
  79. char _alignClient[32];
  80. };
  81. BridgeRingBuffer ringBuffer;
  82. };
  83. // ---------------------------------------------------------------------------------------------
  84. static inline
  85. void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size)
  86. {
  87. char* const charbuf = static_cast<char*>(buf);
  88. size_t tail = ringbuf->tail;
  89. size_t head = ringbuf->head;
  90. size_t wrap = 0;
  91. if (head <= tail) {
  92. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  93. }
  94. if (head - tail + wrap < size) {
  95. return;
  96. }
  97. size_t readto = tail + size;
  98. if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  99. {
  100. readto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  101. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail;
  102. std::memcpy(charbuf, ringbuf->buf + tail, firstpart);
  103. std::memcpy(charbuf + firstpart, ringbuf->buf, readto);
  104. }
  105. else
  106. {
  107. std::memcpy(charbuf, ringbuf->buf + tail, size);
  108. }
  109. ringbuf->tail = readto;
  110. }
  111. static inline
  112. void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size)
  113. {
  114. const char* const charbuf = static_cast<const char*>(buf);
  115. size_t written = ringbuf->written;
  116. size_t tail = ringbuf->tail;
  117. size_t wrap = 0;
  118. if (tail <= written)
  119. {
  120. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  121. }
  122. if (tail - written + wrap < size)
  123. {
  124. carla_stderr2("Operation ring buffer full! Dropping events.");
  125. ringbuf->invalidateCommit = true;
  126. return;
  127. }
  128. size_t writeto = written + size;
  129. if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  130. {
  131. writeto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  132. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written;
  133. std::memcpy(ringbuf->buf + written, charbuf, firstpart);
  134. std::memcpy(ringbuf->buf, charbuf + firstpart, writeto);
  135. }
  136. else
  137. {
  138. std::memcpy(ringbuf->buf + written, charbuf, size);
  139. }
  140. ringbuf->written = writeto;
  141. }
  142. static inline
  143. void rdwr_commitWrite(BridgeRingBuffer* const ringbuf)
  144. {
  145. if (ringbuf->invalidateCommit)
  146. {
  147. ringbuf->written = ringbuf->head;
  148. ringbuf->invalidateCommit = false;
  149. }
  150. else
  151. {
  152. ringbuf->head = ringbuf->written;
  153. }
  154. }
  155. // ---------------------------------------------------------------------------------------------
  156. static inline
  157. bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf)
  158. {
  159. return (ringbuf->tail != ringbuf->head);
  160. }
  161. static inline
  162. PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf)
  163. {
  164. int i = kPluginBridgeOpcodeNull;
  165. rdwr_tryRead(ringbuf, &i, sizeof(int));
  166. return static_cast<PluginBridgeOpcode>(i);
  167. }
  168. static inline
  169. int rdwr_readInt(BridgeRingBuffer* const ringbuf)
  170. {
  171. int i = 0;
  172. rdwr_tryRead(ringbuf, &i, sizeof(int));
  173. return i;
  174. }
  175. static inline
  176. float rdwr_readFloat(BridgeRingBuffer* const ringbuf)
  177. {
  178. float f = 0.0f;
  179. rdwr_tryRead(ringbuf, &f, sizeof(float));
  180. return f;
  181. }
  182. // ---------------------------------------------------------------------------------------------
  183. static inline
  184. void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode)
  185. {
  186. const int i = opcode;
  187. rdwr_tryWrite(ringbuf, &i, sizeof(int));
  188. }
  189. static inline
  190. void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value)
  191. {
  192. rdwr_tryWrite(ringbuf, &value, sizeof(int));
  193. }
  194. static inline
  195. void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value)
  196. {
  197. rdwr_tryWrite(ringbuf, &value, sizeof(float));
  198. }
  199. // ---------------------------------------------------------------------------------------------
  200. #endif // __CARLA_BRIDGE_UTILS_HPP__