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.

323 lines
14KB

  1. /*
  2. * Carla Bridge utils
  3. * Copyright (C) 2013-2014 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 "CarlaRingBuffer.hpp"
  20. #if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS)
  21. # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "Global\\carla-bridge_shm_ap_"
  22. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Global\\carla-bridge_shm_rtC_"
  23. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Global\\carla-bridge_shm_nonrtC_"
  24. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Global\\carla-bridge_shm_nonrtS_"
  25. #else
  26. # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "/carla-bridge_shm_ap_"
  27. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/carla-bridge_shm_rtC_"
  28. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/carla-bridge_shm_nonrtC_"
  29. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/carla-bridge_shm_nonrtS_"
  30. #endif
  31. // -----------------------------------------------------------------------
  32. // Server sends these to client during RT
  33. enum PluginBridgeRtClientOpcode {
  34. kPluginBridgeRtClientNull = 0,
  35. kPluginBridgeRtClientSetAudioPool, // ulong/ptr
  36. kPluginBridgeRtClientControlEventParameter, // uint/frame, byte/chan, ushort, float
  37. kPluginBridgeRtClientControlEventMidiBank, // uint/frame, byte/chan, ushort
  38. kPluginBridgeRtClientControlEventMidiProgram, // uint/frame, byte/chan, ushort
  39. kPluginBridgeRtClientControlEventAllSoundOff, // uint/frame, byte/chan
  40. kPluginBridgeRtClientControlEventAllNotesOff, // uint/frame, byte/chan
  41. kPluginBridgeRtClientMidiEvent, // uint/frame, byte/port, byte/size, byte[]/data
  42. kPluginBridgeRtClientProcess,
  43. kPluginBridgeRtClientQuit
  44. };
  45. // Server sends these to client during non-RT
  46. enum PluginBridgeNonRtClientOpcode {
  47. kPluginBridgeNonRtClientNull = 0,
  48. kPluginBridgeNonRtClientPing,
  49. kPluginBridgeNonRtClientPingOnOff, // bool
  50. kPluginBridgeNonRtClientActivate,
  51. kPluginBridgeNonRtClientDeactivate,
  52. kPluginBridgeNonRtClientSetBufferSize, // uint
  53. kPluginBridgeNonRtClientSetSampleRate, // double
  54. kPluginBridgeNonRtClientSetOffline,
  55. kPluginBridgeNonRtClientSetOnline,
  56. kPluginBridgeNonRtClientSetParameterValue, // uint, float
  57. kPluginBridgeNonRtClientSetParameterMidiChannel, // uint, byte
  58. kPluginBridgeNonRtClientSetParameterMidiCC, // uint, short
  59. kPluginBridgeNonRtClientSetProgram, // int
  60. kPluginBridgeNonRtClientSetMidiProgram, // int
  61. kPluginBridgeNonRtClientSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[]
  62. kPluginBridgeNonRtClientSetChunkDataFile, // uint/size, str[] (filename, base64 content)
  63. kPluginBridgeNonRtClientSetCtrlChannel, // short
  64. kPluginBridgeNonRtClientSetOption, // uint/option, bool
  65. kPluginBridgeNonRtClientPrepareForSave,
  66. kPluginBridgeNonRtClientShowUI,
  67. kPluginBridgeNonRtClientHideUI,
  68. kPluginBridgeNonRtClientUiParameterChange, // uint, float
  69. kPluginBridgeNonRtClientUiProgramChange, // uint
  70. kPluginBridgeNonRtClientUiMidiProgramChange, // uint
  71. kPluginBridgeNonRtClientUiNoteOn, // byte, byte, byte
  72. kPluginBridgeNonRtClientUiNoteOff, // byte, byte
  73. kPluginBridgeNonRtClientQuit
  74. };
  75. // Client sends these to server during non-RT
  76. enum PluginBridgeNonRtServerOpcode {
  77. kPluginBridgeNonRtServerNull = 0,
  78. kPluginBridgeNonRtServerPong,
  79. kPluginBridgeNonRtServerPluginInfo1, // uint/category, uint/hints, uint/optionsAvailable, uint/optionsEnabled, long/uniqueId
  80. kPluginBridgeNonRtServerPluginInfo2, // uint/size, str[] (realName), uint/size, str[] (label), uint/size, str[] (maker), uint/size, str[] (copyright)
  81. kPluginBridgeNonRtServerAudioCount, // uint/ins, uint/outs
  82. kPluginBridgeNonRtServerMidiCount, // uint/ins, uint/outs
  83. kPluginBridgeNonRtServerParameterCount, // uint/count
  84. kPluginBridgeNonRtServerProgramCount, // uint/count
  85. kPluginBridgeNonRtServerMidiProgramCount, // uint/count
  86. kPluginBridgeNonRtServerParameterData1, // uint/index, int/rindex, uint/type, uint/hints, short/cc
  87. kPluginBridgeNonRtServerParameterData2, // uint/index, uint/size, str[] (name), uint/size, str[] (symbol), uint/size, str[] (unit)
  88. kPluginBridgeNonRtServerParameterRanges, // uint/index, float/def, float/min, float/max, float/step, float/stepSmall, float/stepLarge
  89. kPluginBridgeNonRtServerParameterValue, // uint/index, float/value
  90. kPluginBridgeNonRtServerParameterValue2, // uint/index, float/value (used for init/output parameters only, don't resend values)
  91. kPluginBridgeNonRtServerDefaultValue, // uint/index, float/value
  92. kPluginBridgeNonRtServerCurrentProgram, // int/index
  93. kPluginBridgeNonRtServerCurrentMidiProgram, // int/index
  94. kPluginBridgeNonRtServerProgramName, // uint/index, uint/size, str[] (name)
  95. kPluginBridgeNonRtServerMidiProgramData, // uint/index, uint/bank, uint/program, uint/size, str[] (name)
  96. kPluginBridgeNonRtServerSetCustomData, // uint/size, str[], uint/size, str[], uint/size, str[]
  97. kPluginBridgeNonRtServerSetChunkDataFile, // uint/size, str[] (filename, base64 content)
  98. kPluginBridgeNonRtServerSetLatency, // uint
  99. kPluginBridgeNonRtServerReady,
  100. kPluginBridgeNonRtServerSaved,
  101. kPluginBridgeNonRtServerUiClosed,
  102. kPluginBridgeNonRtServerError // uint/size, str[]
  103. };
  104. // -----------------------------------------------------------------------
  105. struct BridgeSemaphore {
  106. union {
  107. void* server;
  108. char _padServer[64];
  109. };
  110. union {
  111. void* client;
  112. char _padClient[64];
  113. };
  114. };
  115. // needs to be 64bit aligned
  116. struct BridgeTimeInfo {
  117. uint64_t playing;
  118. uint64_t frame;
  119. uint64_t usecs;
  120. uint32_t valid;
  121. // bbt
  122. int32_t bar, beat, tick;
  123. float beatsPerBar, beatType;
  124. double barStartTick, ticksPerBeat, beatsPerMinute;
  125. };
  126. // -----------------------------------------------------------------------
  127. static const std::size_t kBridgeRtClientDataMidiOutSize = 512*4;
  128. // Server => Client RT
  129. struct BridgeRtClientData {
  130. BridgeSemaphore sem;
  131. BridgeTimeInfo timeInfo;
  132. SmallStackBuffer ringBuffer;
  133. uint8_t midiOut[kBridgeRtClientDataMidiOutSize];
  134. };
  135. // Server => Client Non-RT
  136. struct BridgeNonRtClientData {
  137. BigStackBuffer ringBuffer;
  138. };
  139. // Client => Server Non-RT
  140. struct BridgeNonRtServerData {
  141. HugeStackBuffer ringBuffer;
  142. };
  143. // -----------------------------------------------------------------------
  144. static inline
  145. const char* PluginBridgeRtClientOpcode2str(const PluginBridgeRtClientOpcode opcode) noexcept
  146. {
  147. switch (opcode)
  148. {
  149. case kPluginBridgeRtClientNull:
  150. return "kPluginBridgeRtClientNull";
  151. case kPluginBridgeRtClientSetAudioPool:
  152. return "kPluginBridgeRtClientSetAudioPool";
  153. case kPluginBridgeRtClientControlEventParameter:
  154. return "kPluginBridgeRtClientControlEventParameter";
  155. case kPluginBridgeRtClientControlEventMidiBank:
  156. return "kPluginBridgeRtClientControlEventMidiBank";
  157. case kPluginBridgeRtClientControlEventMidiProgram:
  158. return "kPluginBridgeRtClientControlEventMidiProgram";
  159. case kPluginBridgeRtClientControlEventAllSoundOff:
  160. return "kPluginBridgeRtClientControlEventAllSoundOff";
  161. case kPluginBridgeRtClientControlEventAllNotesOff:
  162. return "kPluginBridgeRtClientControlEventAllNotesOff";
  163. case kPluginBridgeRtClientMidiEvent:
  164. return "kPluginBridgeRtClientMidiEvent";
  165. case kPluginBridgeRtClientProcess:
  166. return "kPluginBridgeRtClientProcess";
  167. case kPluginBridgeRtClientQuit:
  168. return "kPluginBridgeRtClientQuit";
  169. }
  170. carla_stderr("CarlaBackend::PluginBridgeRtClientOpcode2str(%i) - invalid opcode", opcode);
  171. return nullptr;
  172. }
  173. static inline
  174. const char* PluginBridgeNonRtClientOpcode2str(const PluginBridgeNonRtClientOpcode opcode) noexcept
  175. {
  176. switch (opcode)
  177. {
  178. case kPluginBridgeNonRtClientNull:
  179. return "kPluginBridgeNonRtClientNull";
  180. case kPluginBridgeNonRtClientPing:
  181. return "kPluginBridgeNonRtClientPing";
  182. case kPluginBridgeNonRtClientPingOnOff:
  183. return "kPluginBridgeNonRtClientPingOnOff";
  184. case kPluginBridgeNonRtClientActivate:
  185. return "kPluginBridgeNonRtClientActivate";
  186. case kPluginBridgeNonRtClientDeactivate:
  187. return "kPluginBridgeNonRtClientDeactivate";
  188. case kPluginBridgeNonRtClientSetBufferSize:
  189. return "kPluginBridgeNonRtClientSetBufferSize";
  190. case kPluginBridgeNonRtClientSetSampleRate:
  191. return "kPluginBridgeNonRtClientSetSampleRate";
  192. case kPluginBridgeNonRtClientSetOffline:
  193. return "kPluginBridgeNonRtClientSetOffline";
  194. case kPluginBridgeNonRtClientSetOnline:
  195. return "kPluginBridgeNonRtClientSetOnline";
  196. case kPluginBridgeNonRtClientSetParameterValue:
  197. return "kPluginBridgeNonRtClientSetParameterValue";
  198. case kPluginBridgeNonRtClientSetParameterMidiChannel:
  199. return "kPluginBridgeNonRtClientSetParameterMidiChannel";
  200. case kPluginBridgeNonRtClientSetParameterMidiCC:
  201. return "kPluginBridgeNonRtClientSetParameterMidiCC";
  202. case kPluginBridgeNonRtClientSetProgram:
  203. return "kPluginBridgeNonRtClientSetProgram";
  204. case kPluginBridgeNonRtClientSetMidiProgram:
  205. return "kPluginBridgeNonRtClientSetMidiProgram";
  206. case kPluginBridgeNonRtClientSetCustomData:
  207. return "kPluginBridgeNonRtClientSetCustomData";
  208. case kPluginBridgeNonRtClientSetChunkDataFile:
  209. return "kPluginBridgeNonRtClientSetChunkDataFile";
  210. case kPluginBridgeNonRtClientSetCtrlChannel:
  211. return "kPluginBridgeNonRtClientSetCtrlChannel";
  212. case kPluginBridgeNonRtClientSetOption:
  213. return "kPluginBridgeNonRtClientSetOption";
  214. case kPluginBridgeNonRtClientPrepareForSave:
  215. return "kPluginBridgeNonRtClientPrepareForSave";
  216. case kPluginBridgeNonRtClientShowUI:
  217. return "kPluginBridgeNonRtClientShowUI";
  218. case kPluginBridgeNonRtClientHideUI:
  219. return "kPluginBridgeNonRtClientHideUI";
  220. case kPluginBridgeNonRtClientUiParameterChange:
  221. return "kPluginBridgeNonRtClientUiParameterChange";
  222. case kPluginBridgeNonRtClientUiProgramChange:
  223. return "kPluginBridgeNonRtClientUiProgramChange";
  224. case kPluginBridgeNonRtClientUiMidiProgramChange:
  225. return "kPluginBridgeNonRtClientUiMidiProgramChange";
  226. case kPluginBridgeNonRtClientUiNoteOn:
  227. return "kPluginBridgeNonRtClientUiNoteOn";
  228. case kPluginBridgeNonRtClientUiNoteOff:
  229. return "kPluginBridgeNonRtClientUiNoteOff";
  230. case kPluginBridgeNonRtClientQuit:
  231. return "kPluginBridgeNonRtClientQuit";
  232. }
  233. carla_stderr("CarlaBackend::PluginBridgeNonRtClientOpcode2str(%i) - invalid opcode", opcode);
  234. return nullptr;
  235. }
  236. static inline
  237. const char* PluginBridgeNonRtServerOpcode2str(const PluginBridgeNonRtServerOpcode opcode) noexcept
  238. {
  239. switch (opcode)
  240. {
  241. case kPluginBridgeNonRtServerNull:
  242. return "kPluginBridgeNonRtServerNull";
  243. case kPluginBridgeNonRtServerPong:
  244. return "kPluginBridgeNonRtServerPong";
  245. case kPluginBridgeNonRtServerPluginInfo1:
  246. return "kPluginBridgeNonRtServerPluginInfo1";
  247. case kPluginBridgeNonRtServerPluginInfo2:
  248. return "kPluginBridgeNonRtServerPluginInfo2";
  249. case kPluginBridgeNonRtServerAudioCount:
  250. return "kPluginBridgeNonRtServerAudioCount";
  251. case kPluginBridgeNonRtServerMidiCount:
  252. return "kPluginBridgeNonRtServerMidiCount";
  253. case kPluginBridgeNonRtServerParameterCount:
  254. return "kPluginBridgeNonRtServerParameterCount";
  255. case kPluginBridgeNonRtServerProgramCount:
  256. return "kPluginBridgeNonRtServerProgramCount";
  257. case kPluginBridgeNonRtServerMidiProgramCount:
  258. return "kPluginBridgeNonRtServerMidiProgramCount";
  259. case kPluginBridgeNonRtServerParameterData1:
  260. return "kPluginBridgeNonRtServerParameterData1";
  261. case kPluginBridgeNonRtServerParameterData2:
  262. return "kPluginBridgeNonRtServerParameterData2";
  263. case kPluginBridgeNonRtServerParameterRanges:
  264. return "kPluginBridgeNonRtServerParameterRanges";
  265. case kPluginBridgeNonRtServerParameterValue:
  266. return "kPluginBridgeNonRtServerParameterValue";
  267. case kPluginBridgeNonRtServerParameterValue2:
  268. return "kPluginBridgeNonRtServerParameterValue2";
  269. case kPluginBridgeNonRtServerDefaultValue:
  270. return "kPluginBridgeNonRtServerDefaultValue";
  271. case kPluginBridgeNonRtServerCurrentProgram:
  272. return "kPluginBridgeNonRtServerCurrentProgram";
  273. case kPluginBridgeNonRtServerCurrentMidiProgram:
  274. return "kPluginBridgeNonRtServerCurrentMidiProgram";
  275. case kPluginBridgeNonRtServerProgramName:
  276. return "kPluginBridgeNonRtServerProgramName";
  277. case kPluginBridgeNonRtServerMidiProgramData:
  278. return "kPluginBridgeNonRtServerMidiProgramData";
  279. case kPluginBridgeNonRtServerSetCustomData:
  280. return "kPluginBridgeNonRtServerSetCustomData";
  281. case kPluginBridgeNonRtServerSetChunkDataFile:
  282. return "kPluginBridgeNonRtServerSetChunkDataFile";
  283. case kPluginBridgeNonRtServerSetLatency:
  284. return "kPluginBridgeNonRtServerSetLatency";
  285. case kPluginBridgeNonRtServerReady:
  286. return "kPluginBridgeNonRtServerReady";
  287. case kPluginBridgeNonRtServerSaved:
  288. return "kPluginBridgeNonRtServerSaved";
  289. case kPluginBridgeNonRtServerUiClosed:
  290. return "kPluginBridgeNonRtServerUiClosed";
  291. case kPluginBridgeNonRtServerError:
  292. return "kPluginBridgeNonRtServerError";
  293. }
  294. carla_stderr("CarlaBackend::PluginBridgeNonRtServerOpcode2str%i) - invalid opcode", opcode);
  295. return nullptr;
  296. }
  297. // -----------------------------------------------------------------------
  298. #endif // CARLA_BRIDGE_UTILS_HPP_INCLUDED