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.

326 lines
12KB

  1. /*
  2. * Carla Bridge utils
  3. * Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or 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 doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_BRIDGE_UTILS_HPP_INCLUDED
  18. #define CARLA_BRIDGE_UTILS_HPP_INCLUDED
  19. #include "CarlaBridgeDefines.hpp"
  20. #include "CarlaMutex.hpp"
  21. #include "CarlaString.hpp"
  22. #if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS)
  23. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Global\\carla-bridge_shm_rtC_"
  24. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Global\\carla-bridge_shm_nonrtC_"
  25. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Global\\carla-bridge_shm_nonrtS_"
  26. #else
  27. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/crlbrdg_shm_rtC_"
  28. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/crlbrdg_shm_nonrtC_"
  29. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/crlbrdg_shm_nonrtS_"
  30. #endif
  31. // -------------------------------------------------------------------------------------------------------------------
  32. static inline
  33. const char* PluginBridgeRtClientOpcode2str(const PluginBridgeRtClientOpcode opcode) noexcept
  34. {
  35. switch (opcode)
  36. {
  37. case kPluginBridgeRtClientNull:
  38. return "kPluginBridgeRtClientNull";
  39. case kPluginBridgeRtClientSetAudioPool:
  40. return "kPluginBridgeRtClientSetAudioPool";
  41. case kPluginBridgeRtClientControlEventParameter:
  42. return "kPluginBridgeRtClientControlEventParameter";
  43. case kPluginBridgeRtClientControlEventMidiBank:
  44. return "kPluginBridgeRtClientControlEventMidiBank";
  45. case kPluginBridgeRtClientControlEventMidiProgram:
  46. return "kPluginBridgeRtClientControlEventMidiProgram";
  47. case kPluginBridgeRtClientControlEventAllSoundOff:
  48. return "kPluginBridgeRtClientControlEventAllSoundOff";
  49. case kPluginBridgeRtClientControlEventAllNotesOff:
  50. return "kPluginBridgeRtClientControlEventAllNotesOff";
  51. case kPluginBridgeRtClientMidiEvent:
  52. return "kPluginBridgeRtClientMidiEvent";
  53. case kPluginBridgeRtClientProcess:
  54. return "kPluginBridgeRtClientProcess";
  55. case kPluginBridgeRtClientQuit:
  56. return "kPluginBridgeRtClientQuit";
  57. }
  58. carla_stderr("CarlaBackend::PluginBridgeRtClientOpcode2str(%i) - invalid opcode", opcode);
  59. return nullptr;
  60. }
  61. static inline
  62. const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcode opcode) noexcept
  63. {
  64. switch (opcode)
  65. {
  66. case kPluginBridgeNonRtClientNull:
  67. return "kPluginBridgeNonRtClientNull";
  68. case kPluginBridgeNonRtClientPing:
  69. return "kPluginBridgeNonRtClientPing";
  70. case kPluginBridgeNonRtClientPingOnOff:
  71. return "kPluginBridgeNonRtClientPingOnOff";
  72. case kPluginBridgeNonRtClientActivate:
  73. return "kPluginBridgeNonRtClientActivate";
  74. case kPluginBridgeNonRtClientDeactivate:
  75. return "kPluginBridgeNonRtClientDeactivate";
  76. case kPluginBridgeNonRtClientSetBufferSize:
  77. return "kPluginBridgeNonRtClientSetBufferSize";
  78. case kPluginBridgeNonRtClientSetSampleRate:
  79. return "kPluginBridgeNonRtClientSetSampleRate";
  80. case kPluginBridgeNonRtClientSetOffline:
  81. return "kPluginBridgeNonRtClientSetOffline";
  82. case kPluginBridgeNonRtClientSetOnline:
  83. return "kPluginBridgeNonRtClientSetOnline";
  84. case kPluginBridgeNonRtClientSetParameterValue:
  85. return "kPluginBridgeNonRtClientSetParameterValue";
  86. case kPluginBridgeNonRtClientSetParameterMidiChannel:
  87. return "kPluginBridgeNonRtClientSetParameterMidiChannel";
  88. case kPluginBridgeNonRtClientSetParameterMidiCC:
  89. return "kPluginBridgeNonRtClientSetParameterMidiCC";
  90. case kPluginBridgeNonRtClientSetProgram:
  91. return "kPluginBridgeNonRtClientSetProgram";
  92. case kPluginBridgeNonRtClientSetMidiProgram:
  93. return "kPluginBridgeNonRtClientSetMidiProgram";
  94. case kPluginBridgeNonRtClientSetCustomData:
  95. return "kPluginBridgeNonRtClientSetCustomData";
  96. case kPluginBridgeNonRtClientSetChunkDataFile:
  97. return "kPluginBridgeNonRtClientSetChunkDataFile";
  98. case kPluginBridgeNonRtClientSetCtrlChannel:
  99. return "kPluginBridgeNonRtClientSetCtrlChannel";
  100. case kPluginBridgeNonRtClientSetOption:
  101. return "kPluginBridgeNonRtClientSetOption";
  102. case kPluginBridgeNonRtClientPrepareForSave:
  103. return "kPluginBridgeNonRtClientPrepareForSave";
  104. case kPluginBridgeNonRtClientShowUI:
  105. return "kPluginBridgeNonRtClientShowUI";
  106. case kPluginBridgeNonRtClientHideUI:
  107. return "kPluginBridgeNonRtClientHideUI";
  108. case kPluginBridgeNonRtClientUiParameterChange:
  109. return "kPluginBridgeNonRtClientUiParameterChange";
  110. case kPluginBridgeNonRtClientUiProgramChange:
  111. return "kPluginBridgeNonRtClientUiProgramChange";
  112. case kPluginBridgeNonRtClientUiMidiProgramChange:
  113. return "kPluginBridgeNonRtClientUiMidiProgramChange";
  114. case kPluginBridgeNonRtClientUiNoteOn:
  115. return "kPluginBridgeNonRtClientUiNoteOn";
  116. case kPluginBridgeNonRtClientUiNoteOff:
  117. return "kPluginBridgeNonRtClientUiNoteOff";
  118. case kPluginBridgeNonRtClientQuit:
  119. return "kPluginBridgeNonRtClientQuit";
  120. }
  121. carla_stderr("CarlaBackend::PluginBridgeNonRtClientOpcode2str(%i) - invalid opcode", opcode);
  122. return nullptr;
  123. }
  124. static inline
  125. const char* PluginBridgeNonRtServerOpcode2str(const PluginBridgeNonRtServerOpcode opcode) noexcept
  126. {
  127. switch (opcode)
  128. {
  129. case kPluginBridgeNonRtServerNull:
  130. return "kPluginBridgeNonRtServerNull";
  131. case kPluginBridgeNonRtServerPong:
  132. return "kPluginBridgeNonRtServerPong";
  133. case kPluginBridgeNonRtServerPluginInfo1:
  134. return "kPluginBridgeNonRtServerPluginInfo1";
  135. case kPluginBridgeNonRtServerPluginInfo2:
  136. return "kPluginBridgeNonRtServerPluginInfo2";
  137. case kPluginBridgeNonRtServerAudioCount:
  138. return "kPluginBridgeNonRtServerAudioCount";
  139. case kPluginBridgeNonRtServerMidiCount:
  140. return "kPluginBridgeNonRtServerMidiCount";
  141. case kPluginBridgeNonRtServerCvCount:
  142. return "kPluginBridgeNonRtServerCvCount";
  143. case kPluginBridgeNonRtServerParameterCount:
  144. return "kPluginBridgeNonRtServerParameterCount";
  145. case kPluginBridgeNonRtServerProgramCount:
  146. return "kPluginBridgeNonRtServerProgramCount";
  147. case kPluginBridgeNonRtServerMidiProgramCount:
  148. return "kPluginBridgeNonRtServerMidiProgramCount";
  149. case kPluginBridgeNonRtServerPortName:
  150. return "kPluginBridgeNonRtServerPortName";
  151. case kPluginBridgeNonRtServerParameterData1:
  152. return "kPluginBridgeNonRtServerParameterData1";
  153. case kPluginBridgeNonRtServerParameterData2:
  154. return "kPluginBridgeNonRtServerParameterData2";
  155. case kPluginBridgeNonRtServerParameterRanges:
  156. return "kPluginBridgeNonRtServerParameterRanges";
  157. case kPluginBridgeNonRtServerParameterValue:
  158. return "kPluginBridgeNonRtServerParameterValue";
  159. case kPluginBridgeNonRtServerParameterValue2:
  160. return "kPluginBridgeNonRtServerParameterValue2";
  161. case kPluginBridgeNonRtServerDefaultValue:
  162. return "kPluginBridgeNonRtServerDefaultValue";
  163. case kPluginBridgeNonRtServerCurrentProgram:
  164. return "kPluginBridgeNonRtServerCurrentProgram";
  165. case kPluginBridgeNonRtServerCurrentMidiProgram:
  166. return "kPluginBridgeNonRtServerCurrentMidiProgram";
  167. case kPluginBridgeNonRtServerProgramName:
  168. return "kPluginBridgeNonRtServerProgramName";
  169. case kPluginBridgeNonRtServerMidiProgramData:
  170. return "kPluginBridgeNonRtServerMidiProgramData";
  171. case kPluginBridgeNonRtServerSetCustomData:
  172. return "kPluginBridgeNonRtServerSetCustomData";
  173. case kPluginBridgeNonRtServerSetChunkDataFile:
  174. return "kPluginBridgeNonRtServerSetChunkDataFile";
  175. case kPluginBridgeNonRtServerSetLatency:
  176. return "kPluginBridgeNonRtServerSetLatency";
  177. case kPluginBridgeNonRtServerReady:
  178. return "kPluginBridgeNonRtServerReady";
  179. case kPluginBridgeNonRtServerSaved:
  180. return "kPluginBridgeNonRtServerSaved";
  181. case kPluginBridgeNonRtServerUiClosed:
  182. return "kPluginBridgeNonRtServerUiClosed";
  183. case kPluginBridgeNonRtServerError:
  184. return "kPluginBridgeNonRtServerError";
  185. }
  186. carla_stderr("CarlaBackend::PluginBridgeNonRtServerOpcode2str%i) - invalid opcode", opcode);
  187. return nullptr;
  188. }
  189. // -------------------------------------------------------------------------------------------------------------------
  190. struct BridgeAudioPool {
  191. float* data;
  192. std::size_t dataSize;
  193. CarlaString filename;
  194. char shm[64];
  195. BridgeAudioPool() noexcept;
  196. ~BridgeAudioPool() noexcept;
  197. bool initializeServer() noexcept;
  198. bool attachClient(const char* const fname) noexcept;
  199. void clear() noexcept;
  200. #ifndef BUILD_BRIDGE
  201. void resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept;
  202. #endif
  203. CARLA_DECLARE_NON_COPY_STRUCT(BridgeAudioPool)
  204. };
  205. // -------------------------------------------------------------------------------------------------------------------
  206. struct BridgeRtClientControl : public CarlaRingBufferControl<SmallStackBuffer> {
  207. BridgeRtClientData* data;
  208. CarlaString filename;
  209. bool needsSemDestroy; // client only
  210. char shm[64];
  211. BridgeRtClientControl() noexcept;
  212. ~BridgeRtClientControl() noexcept override;
  213. bool initializeServer() noexcept;
  214. bool attachClient(const char* const basename) noexcept;
  215. void clear() noexcept;
  216. bool mapData() noexcept;
  217. void unmapData() noexcept;
  218. #ifndef BUILD_BRIDGE
  219. // non-bridge, server
  220. bool waitForClient(const uint msecs) noexcept;
  221. void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept;
  222. #else
  223. // bridge, client
  224. PluginBridgeRtClientOpcode readOpcode() noexcept;
  225. // helper class that automatically posts semaphore on destructor
  226. struct WaitHelper {
  227. BridgeRtClientData* const data;
  228. const bool ok;
  229. WaitHelper(BridgeRtClientControl& c) noexcept;
  230. ~WaitHelper() noexcept;
  231. CARLA_DECLARE_NON_COPY_STRUCT(WaitHelper)
  232. };
  233. #endif
  234. CARLA_DECLARE_NON_COPY_STRUCT(BridgeRtClientControl)
  235. };
  236. // -------------------------------------------------------------------------------------------------------------------
  237. struct BridgeNonRtClientControl : public CarlaRingBufferControl<BigStackBuffer> {
  238. BridgeNonRtClientData* data;
  239. CarlaString filename;
  240. CarlaMutex mutex;
  241. char shm[64];
  242. BridgeNonRtClientControl() noexcept;
  243. ~BridgeNonRtClientControl() noexcept override;
  244. bool initializeServer() noexcept;
  245. bool attachClient(const char* const basename) noexcept;
  246. void clear() noexcept;
  247. bool mapData() noexcept;
  248. void unmapData() noexcept;
  249. #ifndef BUILD_BRIDGE
  250. // non-bridge, server
  251. void waitIfDataIsReachingLimit() noexcept;
  252. void writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept;
  253. #else
  254. // bridge, client
  255. PluginBridgeNonRtClientOpcode readOpcode() noexcept;
  256. #endif
  257. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtClientControl)
  258. };
  259. // -------------------------------------------------------------------------------------------------------------------
  260. struct BridgeNonRtServerControl : public CarlaRingBufferControl<HugeStackBuffer> {
  261. BridgeNonRtServerData* data;
  262. CarlaString filename;
  263. CarlaMutex mutex;
  264. char shm[64];
  265. BridgeNonRtServerControl() noexcept;
  266. ~BridgeNonRtServerControl() noexcept override;
  267. bool initializeServer() noexcept;
  268. bool attachClient(const char* const basename) noexcept;
  269. void clear() noexcept;
  270. bool mapData() noexcept;
  271. void unmapData() noexcept;
  272. #ifndef BUILD_BRIDGE
  273. // non-bridge, server
  274. PluginBridgeNonRtServerOpcode readOpcode() noexcept;
  275. #else
  276. // bridge, client
  277. void waitIfDataIsReachingLimit() noexcept;
  278. void writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept;
  279. #endif
  280. CARLA_DECLARE_NON_COPY_STRUCT(BridgeNonRtServerControl)
  281. };
  282. // -------------------------------------------------------------------------------------------------------------------
  283. #endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED