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.

616 lines
15KB

  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. #ifndef BUILD_BRIDGE
  106. void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept
  107. {
  108. CARLA_SAFE_ASSERT_RETURN(jackbridge_shm_is_valid(shm),);
  109. if (data != nullptr)
  110. jackbridge_shm_unmap(shm, data);
  111. dataSize = (audioPortCount+cvPortCount)*bufferSize*sizeof(float);
  112. if (dataSize == 0)
  113. dataSize = sizeof(float);
  114. data = (float*)jackbridge_shm_map(shm, dataSize);
  115. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  116. std::memset(data, 0, dataSize);
  117. }
  118. #endif
  119. // -------------------------------------------------------------------------------------------------------------------
  120. BridgeRtClientControl::BridgeRtClientControl() noexcept
  121. : data(nullptr),
  122. filename(),
  123. needsSemDestroy(false)
  124. {
  125. carla_zeroChars(shm, 64);
  126. jackbridge_shm_init(shm);
  127. }
  128. BridgeRtClientControl::~BridgeRtClientControl() noexcept
  129. {
  130. // should be cleared by now
  131. CARLA_SAFE_ASSERT(data == nullptr);
  132. clear();
  133. }
  134. bool BridgeRtClientControl::initializeServer() noexcept
  135. {
  136. #ifndef BUILD_BRIDGE
  137. char tmpFileBase[64];
  138. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "XXXXXX");
  139. const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
  140. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
  141. void* const shmptr = shm;
  142. carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
  143. carla_copyStruct(shm1, shm2);
  144. // NEW
  145. if (! mapData())
  146. {
  147. jackbridge_shm_close(shm);
  148. jackbridge_shm_init(shm);
  149. return false;
  150. }
  151. CARLA_SAFE_ASSERT(data != nullptr);
  152. if (! jackbridge_sem_init(&data->sem.server))
  153. {
  154. unmapData();
  155. jackbridge_shm_close(shm);
  156. jackbridge_shm_init(shm);
  157. return false;
  158. }
  159. if (! jackbridge_sem_init(&data->sem.client))
  160. {
  161. jackbridge_sem_destroy(&data->sem.server);
  162. unmapData();
  163. jackbridge_shm_close(shm);
  164. jackbridge_shm_init(shm);
  165. return false;
  166. }
  167. // NEW
  168. filename = tmpFileBase;
  169. needsSemDestroy = true;
  170. return true;
  171. #else
  172. return false;
  173. #endif
  174. }
  175. bool BridgeRtClientControl::attachClient(const char* const basename) noexcept
  176. {
  177. CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
  178. #ifdef BUILD_BRIDGE
  179. // must be invalid right now
  180. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  181. filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT;
  182. filename += basename;
  183. jackbridge_shm_attach(shm, filename);
  184. return jackbridge_shm_is_valid(shm);
  185. #else
  186. return false;
  187. #endif
  188. }
  189. void BridgeRtClientControl::clear() noexcept
  190. {
  191. filename.clear();
  192. if (needsSemDestroy)
  193. {
  194. jackbridge_sem_destroy(&data->sem.client);
  195. jackbridge_sem_destroy(&data->sem.server);
  196. needsSemDestroy = false;
  197. }
  198. if (data != nullptr)
  199. unmapData();
  200. if (! jackbridge_shm_is_valid(shm))
  201. return;
  202. jackbridge_shm_close(shm);
  203. jackbridge_shm_init(shm);
  204. }
  205. bool BridgeRtClientControl::mapData() noexcept
  206. {
  207. CARLA_SAFE_ASSERT(data == nullptr);
  208. if (jackbridge_shm_map2<BridgeRtClientData>(shm, data))
  209. {
  210. #ifdef BUILD_BRIDGE
  211. CARLA_SAFE_ASSERT(data->midiOut[0] == 0);
  212. setRingBuffer(&data->ringBuffer, false);
  213. CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false);
  214. CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false);
  215. #else
  216. std::memset(data, 0, sizeof(BridgeRtClientData));
  217. setRingBuffer(&data->ringBuffer, true);
  218. #endif
  219. return true;
  220. }
  221. return false;
  222. }
  223. void BridgeRtClientControl::unmapData() noexcept
  224. {
  225. #ifndef BUILD_BRIDGE
  226. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  227. jackbridge_shm_unmap(shm, data);
  228. #endif
  229. data = nullptr;
  230. setRingBuffer(nullptr, false);
  231. }
  232. #ifndef BUILD_BRIDGE
  233. bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept
  234. {
  235. CARLA_SAFE_ASSERT_RETURN(msecs > 0, false);
  236. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  237. jackbridge_sem_post(&data->sem.server, true);
  238. return jackbridge_sem_timedwait(&data->sem.client, msecs, true);
  239. return false;
  240. }
  241. void BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
  242. {
  243. writeUInt(static_cast<uint32_t>(opcode));
  244. }
  245. #else
  246. PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept
  247. {
  248. return static_cast<PluginBridgeRtClientOpcode>(readUInt());
  249. }
  250. BridgeRtClientControl::WaitHelper::WaitHelper(BridgeRtClientControl& c) noexcept
  251. : data(c.data),
  252. ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {}
  253. BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept
  254. {
  255. if (ok)
  256. jackbridge_sem_post(&data->sem.client, false);
  257. }
  258. #endif
  259. // -------------------------------------------------------------------------------------------------------------------
  260. BridgeNonRtClientControl::BridgeNonRtClientControl() noexcept
  261. : data(nullptr),
  262. filename(),
  263. mutex()
  264. {
  265. carla_zeroChars(shm, 64);
  266. jackbridge_shm_init(shm);
  267. }
  268. BridgeNonRtClientControl::~BridgeNonRtClientControl() noexcept
  269. {
  270. // should be cleared by now
  271. CARLA_SAFE_ASSERT(data == nullptr);
  272. clear();
  273. }
  274. bool BridgeNonRtClientControl::initializeServer() noexcept
  275. {
  276. #ifndef BUILD_BRIDGE
  277. char tmpFileBase[64];
  278. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "XXXXXX");
  279. const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
  280. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
  281. void* const shmptr = shm;
  282. carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
  283. carla_copyStruct(shm1, shm2);
  284. if (! mapData())
  285. {
  286. jackbridge_shm_close(shm);
  287. jackbridge_shm_init(shm);
  288. return false;
  289. }
  290. CARLA_SAFE_ASSERT(data != nullptr);
  291. filename = tmpFileBase;
  292. return true;
  293. #else
  294. return false;
  295. #endif
  296. }
  297. bool BridgeNonRtClientControl::attachClient(const char* const basename) noexcept
  298. {
  299. CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
  300. #ifdef BUILD_BRIDGE
  301. // must be invalid right now
  302. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  303. filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT;
  304. filename += basename;
  305. jackbridge_shm_attach(shm, filename);
  306. return jackbridge_shm_is_valid(shm);
  307. #else
  308. return false;
  309. #endif
  310. }
  311. void BridgeNonRtClientControl::clear() noexcept
  312. {
  313. filename.clear();
  314. if (data != nullptr)
  315. unmapData();
  316. if (! jackbridge_shm_is_valid(shm))
  317. {
  318. #ifdef BUILD_BRIDGE
  319. CARLA_SAFE_ASSERT(data == nullptr);
  320. #endif
  321. return;
  322. }
  323. jackbridge_shm_close(shm);
  324. jackbridge_shm_init(shm);
  325. }
  326. bool BridgeNonRtClientControl::mapData() noexcept
  327. {
  328. CARLA_SAFE_ASSERT(data == nullptr);
  329. if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
  330. {
  331. #ifdef BUILD_BRIDGE
  332. setRingBuffer(&data->ringBuffer, false);
  333. #else
  334. setRingBuffer(&data->ringBuffer, true);
  335. #endif
  336. return true;
  337. }
  338. return false;
  339. }
  340. void BridgeNonRtClientControl::unmapData() noexcept
  341. {
  342. #ifndef BUILD_BRIDGE
  343. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  344. jackbridge_shm_unmap(shm, data);
  345. #endif
  346. data = nullptr;
  347. setRingBuffer(nullptr, false);
  348. }
  349. #ifndef BUILD_BRIDGE
  350. void BridgeNonRtClientControl::waitIfDataIsReachingLimit() noexcept
  351. {
  352. if (getAvailableDataSize() < BigStackBuffer::size/4)
  353. return;
  354. for (int i=50; --i >= 0;)
  355. {
  356. if (getAvailableDataSize() >= BigStackBuffer::size*3/4)
  357. {
  358. writeOpcode(kPluginBridgeNonRtClientPing);
  359. commitWrite();
  360. return;
  361. }
  362. carla_msleep(20);
  363. }
  364. carla_stderr("Server waitIfDataIsReachingLimit() reached and failed");
  365. }
  366. void BridgeNonRtClientControl::writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept
  367. {
  368. writeUInt(static_cast<uint32_t>(opcode));
  369. }
  370. #else
  371. PluginBridgeNonRtClientOpcode BridgeNonRtClientControl::readOpcode() noexcept
  372. {
  373. return static_cast<PluginBridgeNonRtClientOpcode>(readUInt());
  374. return kPluginBridgeNonRtClientNull;
  375. }
  376. #endif
  377. // -------------------------------------------------------------------------------------------------------------------
  378. BridgeNonRtServerControl::BridgeNonRtServerControl() noexcept
  379. : data(nullptr),
  380. filename(),
  381. mutex()
  382. {
  383. carla_zeroChars(shm, 64);
  384. jackbridge_shm_init(shm);
  385. }
  386. BridgeNonRtServerControl::~BridgeNonRtServerControl() noexcept
  387. {
  388. // should be cleared by now
  389. CARLA_SAFE_ASSERT(data == nullptr);
  390. clear();
  391. }
  392. bool BridgeNonRtServerControl::initializeServer() noexcept
  393. {
  394. #ifndef BUILD_BRIDGE
  395. char tmpFileBase[64];
  396. std::sprintf(tmpFileBase, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "XXXXXX");
  397. const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
  398. CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
  399. void* const shmptr = shm;
  400. carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
  401. carla_copyStruct(shm1, shm2);
  402. if (! mapData())
  403. {
  404. jackbridge_shm_close(shm);
  405. jackbridge_shm_init(shm);
  406. return false;
  407. }
  408. CARLA_SAFE_ASSERT(data != nullptr);
  409. filename = tmpFileBase;
  410. return true;
  411. #else
  412. return false;
  413. #endif
  414. }
  415. bool BridgeNonRtServerControl::attachClient(const char* const basename) noexcept
  416. {
  417. CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
  418. #ifdef BUILD_BRIDGE
  419. // must be invalid right now
  420. CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
  421. filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER;
  422. filename += basename;
  423. jackbridge_shm_attach(shm, filename);
  424. return jackbridge_shm_is_valid(shm);
  425. #else
  426. return false;
  427. #endif
  428. }
  429. void BridgeNonRtServerControl::clear() noexcept
  430. {
  431. filename.clear();
  432. if (data != nullptr)
  433. unmapData();
  434. if (! jackbridge_shm_is_valid(shm))
  435. {
  436. CARLA_SAFE_ASSERT(data == nullptr);
  437. return;
  438. }
  439. jackbridge_shm_close(shm);
  440. jackbridge_shm_init(shm);
  441. }
  442. bool BridgeNonRtServerControl::mapData() noexcept
  443. {
  444. CARLA_SAFE_ASSERT(data == nullptr);
  445. if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data))
  446. {
  447. #ifdef BUILD_BRIDGE
  448. setRingBuffer(&data->ringBuffer, false);
  449. #else
  450. setRingBuffer(&data->ringBuffer, true);
  451. #endif
  452. return true;
  453. }
  454. return false;
  455. }
  456. void BridgeNonRtServerControl::unmapData() noexcept
  457. {
  458. #ifndef BUILD_BRIDGE
  459. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  460. jackbridge_shm_unmap(shm, data);
  461. #endif
  462. data = nullptr;
  463. setRingBuffer(nullptr, false);
  464. }
  465. #ifndef BUILD_BRIDGE
  466. PluginBridgeNonRtServerOpcode BridgeNonRtServerControl::readOpcode() noexcept
  467. {
  468. return static_cast<PluginBridgeNonRtServerOpcode>(readUInt());
  469. }
  470. #else
  471. void BridgeNonRtServerControl::waitIfDataIsReachingLimit() noexcept
  472. {
  473. if (getAvailableDataSize() < HugeStackBuffer::size/4)
  474. return;
  475. for (int i=50; --i >= 0;)
  476. {
  477. if (getAvailableDataSize() >= HugeStackBuffer::size*3/4)
  478. {
  479. writeOpcode(kPluginBridgeNonRtServerPong);
  480. commitWrite();
  481. return;
  482. }
  483. carla_msleep(20);
  484. }
  485. carla_stderr("Client waitIfDataIsReachingLimit() reached and failed");
  486. }
  487. void BridgeNonRtServerControl::writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept
  488. {
  489. writeUInt(static_cast<uint32_t>(opcode));
  490. }
  491. #endif
  492. // -------------------------------------------------------------------------------------------------------------------