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.

285 lines
7.6KB

  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. /*!
  24. * TODO.
  25. */
  26. enum PluginBridgeInfoType {
  27. kPluginBridgeAudioCount,
  28. kPluginBridgeMidiCount,
  29. kPluginBridgeParameterCount,
  30. kPluginBridgeProgramCount,
  31. kPluginBridgeMidiProgramCount,
  32. kPluginBridgePluginInfo,
  33. kPluginBridgeParameterInfo,
  34. kPluginBridgeParameterData,
  35. kPluginBridgeParameterRanges,
  36. kPluginBridgeProgramInfo,
  37. kPluginBridgeMidiProgramInfo,
  38. kPluginBridgeConfigure,
  39. kPluginBridgeSetParameterValue,
  40. kPluginBridgeSetDefaultValue,
  41. kPluginBridgeSetProgram,
  42. kPluginBridgeSetMidiProgram,
  43. kPluginBridgeSetCustomData,
  44. kPluginBridgeSetChunkData,
  45. kPluginBridgeUpdateNow,
  46. kPluginBridgeError
  47. };
  48. enum PluginBridgeOpcode {
  49. kPluginBridgeOpcodeNull = 0,
  50. kPluginBridgeOpcodeReadyWait = 1,
  51. kPluginBridgeOpcodeSetBufferSize = 2,
  52. kPluginBridgeOpcodeSetSampleRate = 3,
  53. kPluginBridgeOpcodeSetParameter = 4,
  54. kPluginBridgeOpcodeProcess = 5,
  55. kPluginBridgeOpcodeQuit = 6
  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. static inline
  84. const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type)
  85. {
  86. switch (type)
  87. {
  88. case kPluginBridgeAudioCount:
  89. return "kPluginBridgeAudioCount";
  90. case kPluginBridgeMidiCount:
  91. return "kPluginBridgeMidiCount";
  92. case kPluginBridgeParameterCount:
  93. return "kPluginBridgeParameterCount";
  94. case kPluginBridgeProgramCount:
  95. return "kPluginBridgeProgramCount";
  96. case kPluginBridgeMidiProgramCount:
  97. return "kPluginBridgeMidiProgramCount";
  98. case kPluginBridgePluginInfo:
  99. return "kPluginBridgePluginInfo";
  100. case kPluginBridgeParameterInfo:
  101. return "kPluginBridgeParameterInfo";
  102. case kPluginBridgeParameterData:
  103. return "kPluginBridgeParameterData";
  104. case kPluginBridgeParameterRanges:
  105. return "kPluginBridgeParameterRanges";
  106. case kPluginBridgeProgramInfo:
  107. return "kPluginBridgeProgramInfo";
  108. case kPluginBridgeMidiProgramInfo:
  109. return "kPluginBridgeMidiProgramInfo";
  110. case kPluginBridgeConfigure:
  111. return "kPluginBridgeConfigure";
  112. case kPluginBridgeSetParameterValue:
  113. return "kPluginBridgeSetParameterValue";
  114. case kPluginBridgeSetDefaultValue:
  115. return "kPluginBridgeSetDefaultValue";
  116. case kPluginBridgeSetProgram:
  117. return "kPluginBridgeSetProgram";
  118. case kPluginBridgeSetMidiProgram:
  119. return "kPluginBridgeSetMidiProgram";
  120. case kPluginBridgeSetCustomData:
  121. return "kPluginBridgeSetCustomData";
  122. case kPluginBridgeSetChunkData:
  123. return "kPluginBridgeSetChunkData";
  124. case kPluginBridgeUpdateNow:
  125. return "kPluginBridgeUpdateNow";
  126. case kPluginBridgeError:
  127. return "kPluginBridgeError";
  128. }
  129. carla_stderr("CarlaBackend::PluginBridgeInfoType2str(%i) - invalid type", type);
  130. return nullptr;
  131. }
  132. // ---------------------------------------------------------------------------------------------
  133. static inline
  134. void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size)
  135. {
  136. char* const charbuf(static_cast<char*>(buf));
  137. size_t tail = ringbuf->tail;
  138. size_t head = ringbuf->head;
  139. size_t wrap = 0;
  140. if (head <= tail) {
  141. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  142. }
  143. if (head - tail + wrap < size) {
  144. return;
  145. }
  146. size_t readto = tail + size;
  147. if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  148. {
  149. readto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  150. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail;
  151. std::memcpy(charbuf, ringbuf->buf + tail, firstpart);
  152. std::memcpy(charbuf + firstpart, ringbuf->buf, readto);
  153. }
  154. else
  155. {
  156. std::memcpy(charbuf, ringbuf->buf + tail, size);
  157. }
  158. ringbuf->tail = readto;
  159. }
  160. static inline
  161. void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size)
  162. {
  163. const char* const charbuf(static_cast<const char*>(buf));
  164. size_t written = ringbuf->written;
  165. size_t tail = ringbuf->tail;
  166. size_t wrap = 0;
  167. if (tail <= written)
  168. {
  169. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  170. }
  171. if (tail - written + wrap < size)
  172. {
  173. carla_stderr2("Ring buffer full! Dropping events.");
  174. ringbuf->invalidateCommit = true;
  175. return;
  176. }
  177. size_t writeto = written + size;
  178. if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  179. {
  180. writeto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  181. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written;
  182. std::memcpy(ringbuf->buf + written, charbuf, firstpart);
  183. std::memcpy(ringbuf->buf, charbuf + firstpart, writeto);
  184. }
  185. else
  186. {
  187. std::memcpy(ringbuf->buf + written, charbuf, size);
  188. }
  189. ringbuf->written = writeto;
  190. }
  191. static inline
  192. void rdwr_commitWrite(BridgeRingBuffer* const ringbuf)
  193. {
  194. if (ringbuf->invalidateCommit)
  195. {
  196. ringbuf->written = ringbuf->head;
  197. ringbuf->invalidateCommit = false;
  198. }
  199. else
  200. {
  201. ringbuf->head = ringbuf->written;
  202. }
  203. }
  204. // ---------------------------------------------------------------------------------------------
  205. static inline
  206. bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf)
  207. {
  208. return (ringbuf->tail != ringbuf->head);
  209. }
  210. static inline
  211. PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf)
  212. {
  213. int i = kPluginBridgeOpcodeNull;
  214. rdwr_tryRead(ringbuf, &i, sizeof(int));
  215. return static_cast<PluginBridgeOpcode>(i);
  216. }
  217. static inline
  218. int rdwr_readInt(BridgeRingBuffer* const ringbuf)
  219. {
  220. int i = 0;
  221. rdwr_tryRead(ringbuf, &i, sizeof(int));
  222. return i;
  223. }
  224. static inline
  225. float rdwr_readFloat(BridgeRingBuffer* const ringbuf)
  226. {
  227. float f = 0.0f;
  228. rdwr_tryRead(ringbuf, &f, sizeof(float));
  229. return f;
  230. }
  231. // ---------------------------------------------------------------------------------------------
  232. static inline
  233. void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode)
  234. {
  235. const int i = opcode;
  236. rdwr_tryWrite(ringbuf, &i, sizeof(int));
  237. }
  238. static inline
  239. void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value)
  240. {
  241. rdwr_tryWrite(ringbuf, &value, sizeof(int));
  242. }
  243. static inline
  244. void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value)
  245. {
  246. rdwr_tryWrite(ringbuf, &value, sizeof(float));
  247. }
  248. // ---------------------------------------------------------------------------------------------
  249. #endif // __CARLA_BRIDGE_UTILS_HPP__