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
8.3KB

  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. #include "CarlaBridgeUtils.hpp"
  18. #ifndef BUILD_BRIDGE
  19. # include "CarlaShmUtils.hpp"
  20. #endif
  21. // must be last
  22. #include "jackbridge/JackBridge.hpp"
  23. #if defined(CARLA_OS_WIN) && defined(BUILDING_CARLA_FOR_WINDOWS)
  24. # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "Global\\carla-bridge_shm_ap_"
  25. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Global\\carla-bridge_shm_rtC_"
  26. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Global\\carla-bridge_shm_nonrtC_"
  27. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Global\\carla-bridge_shm_nonrtS_"
  28. #else
  29. # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "/crlbrdg_shm_ap_"
  30. # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/crlbrdg_shm_rtC_"
  31. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/crlbrdg_shm_nonrtC_"
  32. # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/crlbrdg_shm_nonrtS_"
  33. #endif
  34. // -------------------------------------------------------------------------------------------------------------------
  35. template<typename T>
  36. bool jackbridge_shm_map2(void* shm, T*& value) noexcept
  37. {
  38. value = (T*)jackbridge_shm_map(shm, sizeof(T));
  39. return (value != nullptr);
  40. }
  41. // -------------------------------------------------------------------------------------------------------------------
  42. BridgeAudioPool::BridgeAudioPool() noexcept
  43. : data(nullptr),
  44. dataSize(0),
  45. filename()
  46. {
  47. carla_zeroChars(shm, 64);
  48. jackbridge_shm_init(shm);
  49. }
  50. BridgeAudioPool::~BridgeAudioPool() noexcept
  51. {
  52. // should be cleared by now
  53. CARLA_SAFE_ASSERT(data == nullptr);
  54. clear();
  55. }
  56. bool BridgeAudioPool::initializeServer() noexcept
  57. {
  58. #ifndef BUILD_BRIDGE
  59. char tmpFileBase[64];
  60. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "XXXXXX");
  61. const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
  62. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
  63. void* const shmptr = shm;
  64. carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
  65. carla_copyStruct(shm1, shm2);
  66. filename = tmpFileBase;
  67. return true;
  68. #else
  69. return false;
  70. #endif
  71. }
  72. bool BridgeAudioPool::attachClient(const char* const basename) noexcept
  73. {
  74. CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
  75. #ifdef BUILD_BRIDGE
  76. // must be invalid right now
  77. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  78. filename = PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL;
  79. filename += basename;
  80. jackbridge_shm_attach(shm, filename);
  81. return jackbridge_shm_is_valid(shm);
  82. #else
  83. return false;
  84. #endif
  85. }
  86. void BridgeAudioPool::clear() noexcept
  87. {
  88. filename.clear();
  89. if (! jackbridge_shm_is_valid(shm))
  90. {
  91. CARLA_SAFE_ASSERT(data == nullptr);
  92. return;
  93. }
  94. if (data != nullptr)
  95. {
  96. #ifndef BUILD_BRIDGE
  97. jackbridge_shm_unmap(shm, data);
  98. #endif
  99. data = nullptr;
  100. }
  101. dataSize = 0;
  102. jackbridge_shm_close(shm);
  103. jackbridge_shm_init(shm);
  104. }
  105. void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept
  106. {
  107. CARLA_SAFE_ASSERT_RETURN(jackbridge_shm_is_valid(shm),);
  108. if (data != nullptr)
  109. jackbridge_shm_unmap(shm, data);
  110. dataSize = (audioPortCount+cvPortCount)*bufferSize*sizeof(float);
  111. if (dataSize == 0)
  112. dataSize = sizeof(float);
  113. data = (float*)jackbridge_shm_map(shm, dataSize);
  114. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  115. std::memset(data, 0, dataSize);
  116. }
  117. // -------------------------------------------------------------------------------------------------------------------
  118. BridgeRtClientControl::BridgeRtClientControl() noexcept
  119. : data(nullptr),
  120. filename(),
  121. needsSemDestroy(false)
  122. {
  123. carla_zeroChars(shm, 64);
  124. jackbridge_shm_init(shm);
  125. }
  126. BridgeRtClientControl::~BridgeRtClientControl() noexcept
  127. {
  128. // should be cleared by now
  129. CARLA_SAFE_ASSERT(data == nullptr);
  130. clear();
  131. }
  132. bool BridgeRtClientControl::initializeServer() noexcept
  133. {
  134. #ifndef BUILD_BRIDGE
  135. char tmpFileBase[64];
  136. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "XXXXXX");
  137. const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
  138. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
  139. void* const shmptr = shm;
  140. carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
  141. carla_copyStruct(shm1, shm2);
  142. // NEW
  143. if (! mapData())
  144. {
  145. jackbridge_shm_close(shm);
  146. jackbridge_shm_init(shm);
  147. return false;
  148. }
  149. CARLA_SAFE_ASSERT(data != nullptr);
  150. if (! jackbridge_sem_init(&data->sem.server))
  151. {
  152. unmapData();
  153. jackbridge_shm_close(shm);
  154. jackbridge_shm_init(shm);
  155. return false;
  156. }
  157. if (! jackbridge_sem_init(&data->sem.client))
  158. {
  159. jackbridge_sem_destroy(&data->sem.server);
  160. unmapData();
  161. jackbridge_shm_close(shm);
  162. jackbridge_shm_init(shm);
  163. return false;
  164. }
  165. // NEW
  166. filename = tmpFileBase;
  167. needsSemDestroy = true;
  168. return true;
  169. #else
  170. return false;
  171. #endif
  172. }
  173. bool BridgeRtClientControl::attachClient(const char* const basename) noexcept
  174. {
  175. CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
  176. #ifdef BUILD_BRIDGE
  177. // must be invalid right now
  178. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  179. filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT;
  180. filename += basename;
  181. jackbridge_shm_attach(shm, filename);
  182. return jackbridge_shm_is_valid(shm);
  183. #else
  184. return false;
  185. #endif
  186. }
  187. void BridgeRtClientControl::clear() noexcept
  188. {
  189. filename.clear();
  190. if (needsSemDestroy)
  191. {
  192. jackbridge_sem_destroy(&data->sem.client);
  193. jackbridge_sem_destroy(&data->sem.server);
  194. needsSemDestroy = false;
  195. }
  196. if (data != nullptr)
  197. unmapData();
  198. if (! jackbridge_shm_is_valid(shm))
  199. return;
  200. jackbridge_shm_close(shm);
  201. jackbridge_shm_init(shm);
  202. }
  203. bool BridgeRtClientControl::mapData() noexcept
  204. {
  205. CARLA_SAFE_ASSERT(data == nullptr);
  206. if (jackbridge_shm_map2<BridgeRtClientData>(shm, data))
  207. {
  208. #ifndef BUILD_BRIDGE
  209. std::memset(data, 0, sizeof(BridgeRtClientData));
  210. setRingBuffer(&data->ringBuffer, true);
  211. #else
  212. CARLA_SAFE_ASSERT(data->midiOut[0] == 0);
  213. setRingBuffer(&data->ringBuffer, false);
  214. CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false);
  215. CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false);
  216. #endif
  217. return true;
  218. }
  219. return false;
  220. }
  221. void BridgeRtClientControl::unmapData() noexcept
  222. {
  223. #ifndef BUILD_BRIDGE
  224. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  225. jackbridge_shm_unmap(shm, data);
  226. #endif
  227. data = nullptr;
  228. setRingBuffer(nullptr, false);
  229. }
  230. bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept
  231. {
  232. CARLA_SAFE_ASSERT_RETURN(msecs > 0, false);
  233. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  234. #ifndef BUILD_BRIDGE
  235. jackbridge_sem_post(&data->sem.server, true);
  236. return jackbridge_sem_timedwait(&data->sem.client, msecs, true);
  237. #else
  238. return false;
  239. #endif
  240. }
  241. PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept
  242. {
  243. #ifdef BUILD_BRIDGE
  244. return static_cast<PluginBridgeRtClientOpcode>(readUInt());
  245. #else
  246. return kPluginBridgeRtClientNull;
  247. #endif
  248. }
  249. void BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
  250. {
  251. #ifndef BUILD_BRIDGE
  252. writeUInt(static_cast<uint32_t>(opcode));
  253. #endif
  254. }
  255. BridgeRtClientControl::WaitHelper::WaitHelper(BridgeRtClientControl& c) noexcept
  256. : data(c.data),
  257. ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {}
  258. BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept
  259. {
  260. if (ok)
  261. jackbridge_sem_post(&data->sem.client, false);
  262. }
  263. // -------------------------------------------------------------------------------------------------------------------