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.

330 lines
9.6KB

  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__