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.

CarlaBridgeUtils.hpp 9.6KB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * Carla Bridge utils imported from dssi-vst code
  3. * Copyright (C) 2004-2010 Chris Cannam <cannam@all-day-breakfast.com>
  4. * Copyright (C) 2013 Filipe Coelho <falktx@falktx.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. enum PluginBridgeInfoType {
  25. kPluginBridgeAudioCount,
  26. kPluginBridgeMidiCount,
  27. kPluginBridgeParameterCount,
  28. kPluginBridgeProgramCount,
  29. kPluginBridgeMidiProgramCount,
  30. kPluginBridgePluginInfo,
  31. kPluginBridgeParameterInfo,
  32. kPluginBridgeParameterData,
  33. kPluginBridgeParameterRanges,
  34. kPluginBridgeProgramInfo,
  35. kPluginBridgeMidiProgramInfo,
  36. kPluginBridgeConfigure,
  37. kPluginBridgeSetParameterValue,
  38. kPluginBridgeSetDefaultValue,
  39. kPluginBridgeSetProgram,
  40. kPluginBridgeSetMidiProgram,
  41. kPluginBridgeSetCustomData,
  42. kPluginBridgeSetChunkData,
  43. kPluginBridgeUpdateNow,
  44. kPluginBridgeError
  45. };
  46. enum PluginBridgeOpcode {
  47. kPluginBridgeOpcodeNull = 0,
  48. kPluginBridgeOpcodeSetAudioPool = 1, // int
  49. kPluginBridgeOpcodeSetBufferSize = 2, // int
  50. kPluginBridgeOpcodeSetSampleRate = 3, // float
  51. kPluginBridgeOpcodeSetParameter = 4, // int, float
  52. kPluginBridgeOpcodeSetProgram = 5, // int
  53. kPluginBridgeOpcodeSetMidiProgram = 6, // int
  54. kPluginBridgeOpcodeMidiEvent = 7, // long, int, char[] (long = timeFrame, int = size max 4)
  55. kPluginBridgeOpcodeProcess = 8,
  56. kPluginBridgeOpcodeQuit = 9
  57. };
  58. const char* const CARLA_BRIDGE_MSG_HIDE_GUI = "CarlaBridgeHideGUI"; //!< Plugin -> Host call, tells host GUI is now hidden
  59. const char* const CARLA_BRIDGE_MSG_SAVED = "CarlaBridgeSaved"; //!< Plugin -> Host call, tells host state is saved
  60. #if 0
  61. const char* const CARLA_BRIDGE_MSG_SAVE_NOW = "CarlaBridgeSaveNow"; //!< Host -> Plugin call, tells plugin to save state now
  62. const char* const CARLA_BRIDGE_MSG_SET_CHUNK = "CarlaBridgeSetChunk"; //!< Host -> Plugin call, tells plugin to set chunk in file \a value
  63. const char* const CARLA_BRIDGE_MSG_SET_CUSTOM = "CarlaBridgeSetCustom"; //!< Host -> Plugin call, tells plugin to set a custom data set using \a value ("type·key·rvalue").
  64. //If \a type is 'chunk' or 'binary' \a rvalue refers to chunk file.
  65. #endif
  66. // ---------------------------------------------------------------------------------------------
  67. struct BridgeRingBuffer {
  68. int head, tail, written;
  69. bool invalidateCommit;
  70. char buf[BRIDGE_SHM_RING_BUFFER_SIZE];
  71. };
  72. struct BridgeShmControl {
  73. // 32 and 64-bit binaries align semaphores differently.
  74. // Let's make sure there's plenty of room for either one.
  75. union {
  76. sem_t runServer;
  77. char _alignServer[128];
  78. };
  79. union {
  80. sem_t runClient;
  81. char _alignClient[128];
  82. };
  83. BridgeRingBuffer ringBuffer;
  84. };
  85. // ---------------------------------------------------------------------------------------------
  86. static inline
  87. const char* PluginBridgeInfoType2str(const PluginBridgeInfoType type)
  88. {
  89. switch (type)
  90. {
  91. case kPluginBridgeAudioCount:
  92. return "kPluginBridgeAudioCount";
  93. case kPluginBridgeMidiCount:
  94. return "kPluginBridgeMidiCount";
  95. case kPluginBridgeParameterCount:
  96. return "kPluginBridgeParameterCount";
  97. case kPluginBridgeProgramCount:
  98. return "kPluginBridgeProgramCount";
  99. case kPluginBridgeMidiProgramCount:
  100. return "kPluginBridgeMidiProgramCount";
  101. case kPluginBridgePluginInfo:
  102. return "kPluginBridgePluginInfo";
  103. case kPluginBridgeParameterInfo:
  104. return "kPluginBridgeParameterInfo";
  105. case kPluginBridgeParameterData:
  106. return "kPluginBridgeParameterData";
  107. case kPluginBridgeParameterRanges:
  108. return "kPluginBridgeParameterRanges";
  109. case kPluginBridgeProgramInfo:
  110. return "kPluginBridgeProgramInfo";
  111. case kPluginBridgeMidiProgramInfo:
  112. return "kPluginBridgeMidiProgramInfo";
  113. case kPluginBridgeConfigure:
  114. return "kPluginBridgeConfigure";
  115. case kPluginBridgeSetParameterValue:
  116. return "kPluginBridgeSetParameterValue";
  117. case kPluginBridgeSetDefaultValue:
  118. return "kPluginBridgeSetDefaultValue";
  119. case kPluginBridgeSetProgram:
  120. return "kPluginBridgeSetProgram";
  121. case kPluginBridgeSetMidiProgram:
  122. return "kPluginBridgeSetMidiProgram";
  123. case kPluginBridgeSetCustomData:
  124. return "kPluginBridgeSetCustomData";
  125. case kPluginBridgeSetChunkData:
  126. return "kPluginBridgeSetChunkData";
  127. case kPluginBridgeUpdateNow:
  128. return "kPluginBridgeUpdateNow";
  129. case kPluginBridgeError:
  130. return "kPluginBridgeError";
  131. }
  132. carla_stderr("CarlaBackend::PluginBridgeInfoType2str(%i) - invalid type", type);
  133. return nullptr;
  134. }
  135. // ---------------------------------------------------------------------------------------------
  136. static inline
  137. void rdwr_tryRead(BridgeRingBuffer* const ringbuf, void* const buf, const size_t size)
  138. {
  139. CARLA_ASSERT(buf != nullptr);
  140. if (buf == nullptr)
  141. return;
  142. char* const charbuf(static_cast<char*>(buf));
  143. size_t tail = ringbuf->tail;
  144. size_t head = ringbuf->head;
  145. size_t wrap = 0;
  146. if (head <= tail) {
  147. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  148. }
  149. if (head - tail + wrap < size) {
  150. return;
  151. }
  152. size_t readto = tail + size;
  153. if (readto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  154. {
  155. readto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  156. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - tail;
  157. std::memcpy(charbuf, ringbuf->buf + tail, firstpart);
  158. std::memcpy(charbuf + firstpart, ringbuf->buf, readto);
  159. }
  160. else
  161. {
  162. std::memcpy(charbuf, ringbuf->buf + tail, size);
  163. }
  164. ringbuf->tail = readto;
  165. }
  166. static inline
  167. void rdwr_tryWrite(BridgeRingBuffer* const ringbuf, const void* const buf, const size_t size)
  168. {
  169. CARLA_ASSERT(buf != nullptr);
  170. if (buf == nullptr)
  171. return;
  172. const char* const charbuf(static_cast<const char*>(buf));
  173. size_t written = ringbuf->written;
  174. size_t tail = ringbuf->tail;
  175. size_t wrap = 0;
  176. if (tail <= written)
  177. {
  178. wrap = BRIDGE_SHM_RING_BUFFER_SIZE;
  179. }
  180. if (tail - written + wrap < size)
  181. {
  182. carla_stderr2("Ring buffer full! Dropping events.");
  183. ringbuf->invalidateCommit = true;
  184. return;
  185. }
  186. size_t writeto = written + size;
  187. if (writeto >= BRIDGE_SHM_RING_BUFFER_SIZE)
  188. {
  189. writeto -= BRIDGE_SHM_RING_BUFFER_SIZE;
  190. size_t firstpart = BRIDGE_SHM_RING_BUFFER_SIZE - written;
  191. std::memcpy(ringbuf->buf + written, charbuf, firstpart);
  192. std::memcpy(ringbuf->buf, charbuf + firstpart, writeto);
  193. }
  194. else
  195. {
  196. std::memcpy(ringbuf->buf + written, charbuf, size);
  197. }
  198. ringbuf->written = writeto;
  199. }
  200. static inline
  201. void rdwr_commitWrite(BridgeRingBuffer* const ringbuf)
  202. {
  203. if (ringbuf->invalidateCommit)
  204. {
  205. ringbuf->written = ringbuf->head;
  206. ringbuf->invalidateCommit = false;
  207. }
  208. else
  209. {
  210. ringbuf->head = ringbuf->written;
  211. }
  212. }
  213. // ---------------------------------------------------------------------------------------------
  214. static inline
  215. bool rdwr_dataAvailable(BridgeRingBuffer* const ringbuf)
  216. {
  217. return (ringbuf->tail != ringbuf->head);
  218. }
  219. static inline
  220. PluginBridgeOpcode rdwr_readOpcode(BridgeRingBuffer* const ringbuf)
  221. {
  222. int i = static_cast<int>(kPluginBridgeOpcodeNull);
  223. rdwr_tryRead(ringbuf, &i, sizeof(int));
  224. return static_cast<PluginBridgeOpcode>(i);
  225. }
  226. static inline
  227. char rdwr_readChar(BridgeRingBuffer* const ringbuf)
  228. {
  229. char c = 0;
  230. rdwr_tryRead(ringbuf, &c, sizeof(char));
  231. return c;
  232. }
  233. static inline
  234. int rdwr_readInt(BridgeRingBuffer* const ringbuf)
  235. {
  236. int i = 0;
  237. rdwr_tryRead(ringbuf, &i, sizeof(int));
  238. return i;
  239. }
  240. static inline
  241. long rdwr_readLong(BridgeRingBuffer* const ringbuf)
  242. {
  243. long l = 0;
  244. rdwr_tryRead(ringbuf, &l, sizeof(long));
  245. return l;
  246. }
  247. static inline
  248. float rdwr_readFloat(BridgeRingBuffer* const ringbuf)
  249. {
  250. float f = 0.0f;
  251. rdwr_tryRead(ringbuf, &f, sizeof(float));
  252. return f;
  253. }
  254. // ---------------------------------------------------------------------------------------------
  255. static inline
  256. void rdwr_writeOpcode(BridgeRingBuffer* const ringbuf, const PluginBridgeOpcode opcode)
  257. {
  258. const int intcode(static_cast<int>(opcode));
  259. rdwr_tryWrite(ringbuf, &intcode, sizeof(int));
  260. }
  261. static inline
  262. void rdwr_writeChar(BridgeRingBuffer* const ringbuf, const char value)
  263. {
  264. rdwr_tryWrite(ringbuf, &value, sizeof(char));
  265. }
  266. static inline
  267. void rdwr_writeInt(BridgeRingBuffer* const ringbuf, const int value)
  268. {
  269. rdwr_tryWrite(ringbuf, &value, sizeof(int));
  270. }
  271. static inline
  272. void rdwr_writeLong(BridgeRingBuffer* const ringbuf, const long value)
  273. {
  274. rdwr_tryWrite(ringbuf, &value, sizeof(long));
  275. }
  276. static inline
  277. void rdwr_writeFloat(BridgeRingBuffer* const ringbuf, const float value)
  278. {
  279. rdwr_tryWrite(ringbuf, &value, sizeof(float));
  280. }
  281. // ---------------------------------------------------------------------------------------------
  282. #endif // __CARLA_BRIDGE_UTILS_HPP__