VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / utils / CarlaBridgeUtils.cpp
blob81bac3198f020fb7fb92ec651f20141dacd14b14
1 /*
2 * Carla Bridge utils
3 * Copyright (C) 2013-2023 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaBridgeUtils.hpp"
19 #include "CarlaShmUtils.hpp"
20 #include "CarlaTimeUtils.hpp"
22 // must be last
23 #include "jackbridge/JackBridge.hpp"
25 #if defined(CARLA_OS_WIN) && !defined(BUILDING_CARLA_FOR_WINE)
26 # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "Local\\carla-bridge_shm_ap_"
27 # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "Local\\carla-bridge_shm_rtC_"
28 # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "Local\\carla-bridge_shm_nonrtC_"
29 # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "Local\\carla-bridge_shm_nonrtS_"
30 #else
31 # define PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "/crlbrdg_shm_ap_"
32 # define PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "/crlbrdg_shm_rtC_"
33 # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "/crlbrdg_shm_nonrtC_"
34 # define PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "/crlbrdg_shm_nonrtS_"
35 #endif
37 // -------------------------------------------------------------------------------------------------------------------
39 template<typename T>
40 bool jackbridge_shm_map2(void* shm, T*& value) noexcept
42 value = (T*)jackbridge_shm_map(shm, sizeof(T));
43 return (value != nullptr);
46 // -------------------------------------------------------------------------------------------------------------------
48 BridgeAudioPool::BridgeAudioPool() noexcept
49 : data(nullptr),
50 dataSize(0),
51 filename(),
52 isServer(false)
54 carla_zeroChars(shm, 64);
55 jackbridge_shm_init(shm);
58 BridgeAudioPool::~BridgeAudioPool() noexcept
60 // should be cleared by now
61 CARLA_SAFE_ASSERT(data == nullptr);
63 clear();
66 bool BridgeAudioPool::initializeServer() noexcept
68 char tmpFileBase[64] = {};
69 std::snprintf(tmpFileBase, sizeof(tmpFileBase)-1, PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL "XXXXXX");
71 const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
72 CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
74 void* const shmptr = shm;
75 carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
76 carla_copyStruct(shm1, shm2);
78 filename = tmpFileBase;
79 isServer = true;
80 return true;
83 bool BridgeAudioPool::attachClient(const char* const basename) noexcept
85 CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
87 // must be invalid right now
88 CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
90 filename = PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL;
91 filename += basename;
93 jackbridge_shm_attach(shm, filename);
95 return jackbridge_shm_is_valid(shm);
98 void BridgeAudioPool::clear() noexcept
100 filename.clear();
102 if (! jackbridge_shm_is_valid(shm))
104 CARLA_SAFE_ASSERT(data == nullptr);
105 return;
108 if (data != nullptr)
110 if (isServer)
111 jackbridge_shm_unmap(shm, data);
112 data = nullptr;
115 dataSize = 0;
116 jackbridge_shm_close(shm);
117 jackbridge_shm_init(shm);
120 void BridgeAudioPool::resize(const uint32_t bufferSize, const uint32_t audioPortCount, const uint32_t cvPortCount) noexcept
122 CARLA_SAFE_ASSERT_RETURN(jackbridge_shm_is_valid(shm),);
123 CARLA_SAFE_ASSERT_RETURN(isServer,);
125 if (data != nullptr)
126 jackbridge_shm_unmap(shm, data);
128 dataSize = (audioPortCount+cvPortCount)*bufferSize*sizeof(float);
130 if (dataSize == 0)
131 dataSize = sizeof(float);
133 data = (float*)jackbridge_shm_map(shm, dataSize);
134 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
136 std::memset(data, 0, dataSize);
139 const char* BridgeAudioPool::getFilenameSuffix() const noexcept
141 CARLA_SAFE_ASSERT_RETURN(filename.isNotEmpty(), nullptr);
143 const std::size_t prefixLength(std::strlen(PLUGIN_BRIDGE_NAMEPREFIX_AUDIO_POOL));
144 CARLA_SAFE_ASSERT_RETURN(filename.length() > prefixLength, nullptr);
146 return filename.buffer() + prefixLength;
149 // -------------------------------------------------------------------------------------------------------------------
151 BridgeRtClientControl::BridgeRtClientControl() noexcept
152 : data(nullptr),
153 filename(),
154 needsSemDestroy(false),
155 isServer(false)
157 carla_zeroChars(shm, 64);
158 jackbridge_shm_init(shm);
161 BridgeRtClientControl::~BridgeRtClientControl() noexcept
163 // should be cleared by now
164 CARLA_SAFE_ASSERT(data == nullptr);
166 clear();
169 bool BridgeRtClientControl::initializeServer() noexcept
171 char tmpFileBase[64] = {};
172 std::snprintf(tmpFileBase, sizeof(tmpFileBase)-1, PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT "XXXXXX");
174 const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
175 CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
177 void* const shmptr = shm;
178 carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
179 carla_copyStruct(shm1, shm2);
181 filename = tmpFileBase;
182 isServer = true;
184 if (! mapData())
186 jackbridge_shm_close(shm);
187 jackbridge_shm_init(shm);
188 return false;
191 CARLA_SAFE_ASSERT(data != nullptr);
193 if (! jackbridge_sem_init(&data->sem.server))
195 unmapData();
196 jackbridge_shm_close(shm);
197 jackbridge_shm_init(shm);
198 return false;
201 if (! jackbridge_sem_init(&data->sem.client))
203 jackbridge_sem_destroy(&data->sem.server);
204 unmapData();
205 jackbridge_shm_close(shm);
206 jackbridge_shm_init(shm);
207 return false;
210 needsSemDestroy = true;
211 return true;
214 bool BridgeRtClientControl::attachClient(const char* const basename) noexcept
216 CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
218 // must be invalid right now
219 CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
221 filename = PLUGIN_BRIDGE_NAMEPREFIX_RT_CLIENT;
222 filename += basename;
224 jackbridge_shm_attach(shm, filename);
226 return jackbridge_shm_is_valid(shm);
229 void BridgeRtClientControl::clear() noexcept
231 filename.clear();
233 if (needsSemDestroy)
235 jackbridge_sem_destroy(&data->sem.client);
236 jackbridge_sem_destroy(&data->sem.server);
237 needsSemDestroy = false;
240 if (data != nullptr)
241 unmapData();
243 if (! jackbridge_shm_is_valid(shm))
244 return;
246 jackbridge_shm_close(shm);
247 jackbridge_shm_init(shm);
250 bool BridgeRtClientControl::mapData() noexcept
252 CARLA_SAFE_ASSERT(data == nullptr);
254 if (! jackbridge_shm_map2<BridgeRtClientData>(shm, data))
255 return false;
257 if (isServer)
259 std::memset(data, 0, sizeof(BridgeRtClientData));
260 setRingBuffer(&data->ringBuffer, true);
262 else
264 CARLA_SAFE_ASSERT(data->midiOut[0] == 0);
265 setRingBuffer(&data->ringBuffer, false);
267 CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.server), false);
268 CARLA_SAFE_ASSERT_RETURN(jackbridge_sem_connect(&data->sem.client), false);
271 return true;
274 void BridgeRtClientControl::unmapData() noexcept
276 if (isServer)
278 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
279 jackbridge_shm_unmap(shm, data);
282 data = nullptr;
283 setRingBuffer(nullptr, false);
286 bool BridgeRtClientControl::waitForClient(const uint msecs) noexcept
288 CARLA_SAFE_ASSERT_RETURN(msecs > 0, false);
289 CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
290 CARLA_SAFE_ASSERT_RETURN(isServer, false);
292 jackbridge_sem_post(&data->sem.server, true);
294 return jackbridge_sem_timedwait(&data->sem.client, msecs, true);
297 bool BridgeRtClientControl::writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept
299 return writeUInt(static_cast<uint32_t>(opcode));
302 PluginBridgeRtClientOpcode BridgeRtClientControl::readOpcode() noexcept
304 CARLA_SAFE_ASSERT_RETURN(! isServer, kPluginBridgeRtClientNull);
306 return static_cast<PluginBridgeRtClientOpcode>(readUInt());
309 BridgeRtClientControl::WaitHelper::WaitHelper(BridgeRtClientControl& c) noexcept
310 : data(c.data),
311 ok(jackbridge_sem_timedwait(&data->sem.server, 5000, false)) {}
313 BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept
315 if (ok)
316 jackbridge_sem_post(&data->sem.client, false);
319 // -------------------------------------------------------------------------------------------------------------------
321 BridgeNonRtClientControl::BridgeNonRtClientControl() noexcept
322 : data(nullptr),
323 filename(),
324 mutex(),
325 isServer(false)
327 carla_zeroChars(shm, 64);
328 jackbridge_shm_init(shm);
331 BridgeNonRtClientControl::~BridgeNonRtClientControl() noexcept
333 // should be cleared by now
334 CARLA_SAFE_ASSERT(data == nullptr);
336 clear();
339 bool BridgeNonRtClientControl::initializeServer() noexcept
341 char tmpFileBase[64] = {};
342 std::snprintf(tmpFileBase, sizeof(tmpFileBase)-1, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT "XXXXXX");
344 const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
345 CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
347 void* const shmptr = shm;
348 carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
349 carla_copyStruct(shm1, shm2);
351 filename = tmpFileBase;
352 isServer = true;
354 if (! mapData())
356 jackbridge_shm_close(shm);
357 jackbridge_shm_init(shm);
358 return false;
361 CARLA_SAFE_ASSERT(data != nullptr);
362 return true;
365 bool BridgeNonRtClientControl::attachClient(const char* const basename) noexcept
367 CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
369 // must be invalid right now
370 CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
372 filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_CLIENT;
373 filename += basename;
375 jackbridge_shm_attach(shm, filename);
377 return jackbridge_shm_is_valid(shm);
380 void BridgeNonRtClientControl::clear() noexcept
382 filename.clear();
384 if (data != nullptr)
385 unmapData();
387 if (! jackbridge_shm_is_valid(shm))
389 if (! isServer) {
390 CARLA_SAFE_ASSERT(data == nullptr);
392 return;
395 jackbridge_shm_close(shm);
396 jackbridge_shm_init(shm);
399 bool BridgeNonRtClientControl::mapData() noexcept
401 CARLA_SAFE_ASSERT(data == nullptr);
403 if (jackbridge_shm_map2<BridgeNonRtClientData>(shm, data))
405 setRingBuffer(&data->ringBuffer, isServer);
406 return true;
409 return false;
412 void BridgeNonRtClientControl::unmapData() noexcept
414 if (isServer)
416 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
417 jackbridge_shm_unmap(shm, data);
420 data = nullptr;
421 setRingBuffer(nullptr, false);
424 void BridgeNonRtClientControl::waitIfDataIsReachingLimit() noexcept
426 CARLA_SAFE_ASSERT_RETURN(isServer,);
428 if (getWritableDataSize() < BigStackBuffer::size/4)
429 return;
431 for (int i=50; --i >= 0;)
433 if (getWritableDataSize() >= BigStackBuffer::size*3/4)
435 writeOpcode(kPluginBridgeNonRtClientPing);
436 commitWrite();
437 return;
439 carla_msleep(20);
442 carla_stderr("Server waitIfDataIsReachingLimit() reached and failed");
445 bool BridgeNonRtClientControl::writeOpcode(const PluginBridgeNonRtClientOpcode opcode) noexcept
447 CARLA_SAFE_ASSERT_RETURN(isServer, false);
449 return writeUInt(static_cast<uint32_t>(opcode));
452 PluginBridgeNonRtClientOpcode BridgeNonRtClientControl::readOpcode() noexcept
454 CARLA_SAFE_ASSERT_RETURN(! isServer, kPluginBridgeNonRtClientNull);
456 return static_cast<PluginBridgeNonRtClientOpcode>(readUInt());
459 // -------------------------------------------------------------------------------------------------------------------
461 BridgeNonRtServerControl::BridgeNonRtServerControl() noexcept
462 : data(nullptr),
463 filename(),
464 mutex(),
465 isServer(false)
467 carla_zeroChars(shm, 64);
468 jackbridge_shm_init(shm);
471 BridgeNonRtServerControl::~BridgeNonRtServerControl() noexcept
473 // should be cleared by now
474 CARLA_SAFE_ASSERT(data == nullptr);
476 clear();
479 bool BridgeNonRtServerControl::initializeServer() noexcept
481 char tmpFileBase[64] = {};
482 std::snprintf(tmpFileBase, sizeof(tmpFileBase)-1, PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER "XXXXXX");
484 const carla_shm_t shm2 = carla_shm_create_temp(tmpFileBase);
485 CARLA_SAFE_ASSERT_RETURN(carla_is_shm_valid(shm2), false);
487 void* const shmptr = shm;
488 carla_shm_t& shm1 = *(carla_shm_t*)shmptr;
489 carla_copyStruct(shm1, shm2);
491 filename = tmpFileBase;
492 isServer = true;
494 if (! mapData())
496 jackbridge_shm_close(shm);
497 jackbridge_shm_init(shm);
498 return false;
501 CARLA_SAFE_ASSERT(data != nullptr);
502 return true;
505 bool BridgeNonRtServerControl::attachClient(const char* const basename) noexcept
507 CARLA_SAFE_ASSERT_RETURN(basename != nullptr && basename[0] != '\0', false);
509 // must be invalid right now
510 CARLA_SAFE_ASSERT_RETURN(! jackbridge_shm_is_valid(shm), false);
512 filename = PLUGIN_BRIDGE_NAMEPREFIX_NON_RT_SERVER;
513 filename += basename;
515 jackbridge_shm_attach(shm, filename);
517 return jackbridge_shm_is_valid(shm);
520 void BridgeNonRtServerControl::clear() noexcept
522 filename.clear();
524 if (data != nullptr)
525 unmapData();
527 if (! jackbridge_shm_is_valid(shm))
529 CARLA_SAFE_ASSERT(data == nullptr);
530 return;
533 jackbridge_shm_close(shm);
534 jackbridge_shm_init(shm);
537 bool BridgeNonRtServerControl::mapData() noexcept
539 CARLA_SAFE_ASSERT(data == nullptr);
541 if (jackbridge_shm_map2<BridgeNonRtServerData>(shm, data))
543 setRingBuffer(&data->ringBuffer, isServer);
544 return true;
547 return false;
550 void BridgeNonRtServerControl::unmapData() noexcept
552 if (isServer)
554 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
555 jackbridge_shm_unmap(shm, data);
558 data = nullptr;
559 setRingBuffer(nullptr, false);
562 PluginBridgeNonRtServerOpcode BridgeNonRtServerControl::readOpcode() noexcept
564 CARLA_SAFE_ASSERT_RETURN(isServer, kPluginBridgeNonRtServerNull);
566 return static_cast<PluginBridgeNonRtServerOpcode>(readUInt());
569 void BridgeNonRtServerControl::waitIfDataIsReachingLimit() noexcept
571 CARLA_SAFE_ASSERT_RETURN(! isServer,);
573 if (getWritableDataSize() < HugeStackBuffer::size/4)
574 return;
576 for (int i=50; --i >= 0;)
578 if (getWritableDataSize() >= HugeStackBuffer::size*3/4)
580 writeOpcode(kPluginBridgeNonRtServerPong);
581 commitWrite();
582 return;
584 carla_msleep(20);
587 carla_stderr("Client waitIfDataIsReachingLimit() reached and failed");
590 bool BridgeNonRtServerControl::writeOpcode(const PluginBridgeNonRtServerOpcode opcode) noexcept
592 CARLA_SAFE_ASSERT_RETURN(! isServer, false);
594 return writeUInt(static_cast<uint32_t>(opcode));
597 // -------------------------------------------------------------------------------------------------------------------