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"
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_"
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_"
37 // -------------------------------------------------------------------------------------------------------------------
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
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);
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
;
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
;
93 jackbridge_shm_attach(shm
, filename
);
95 return jackbridge_shm_is_valid(shm
);
98 void BridgeAudioPool::clear() noexcept
102 if (! jackbridge_shm_is_valid(shm
))
104 CARLA_SAFE_ASSERT(data
== nullptr);
111 jackbridge_shm_unmap(shm
, data
);
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
,);
126 jackbridge_shm_unmap(shm
, data
);
128 dataSize
= (audioPortCount
+cvPortCount
)*bufferSize
*sizeof(float);
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
154 needsSemDestroy(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);
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
;
186 jackbridge_shm_close(shm
);
187 jackbridge_shm_init(shm
);
191 CARLA_SAFE_ASSERT(data
!= nullptr);
193 if (! jackbridge_sem_init(&data
->sem
.server
))
196 jackbridge_shm_close(shm
);
197 jackbridge_shm_init(shm
);
201 if (! jackbridge_sem_init(&data
->sem
.client
))
203 jackbridge_sem_destroy(&data
->sem
.server
);
205 jackbridge_shm_close(shm
);
206 jackbridge_shm_init(shm
);
210 needsSemDestroy
= 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
235 jackbridge_sem_destroy(&data
->sem
.client
);
236 jackbridge_sem_destroy(&data
->sem
.server
);
237 needsSemDestroy
= false;
243 if (! jackbridge_shm_is_valid(shm
))
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
))
259 std::memset(data
, 0, sizeof(BridgeRtClientData
));
260 setRingBuffer(&data
->ringBuffer
, true);
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);
274 void BridgeRtClientControl::unmapData() noexcept
278 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr,);
279 jackbridge_shm_unmap(shm
, data
);
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
311 ok(jackbridge_sem_timedwait(&data
->sem
.server
, 5000, false)) {}
313 BridgeRtClientControl::WaitHelper::~WaitHelper() noexcept
316 jackbridge_sem_post(&data
->sem
.client
, false);
319 // -------------------------------------------------------------------------------------------------------------------
321 BridgeNonRtClientControl::BridgeNonRtClientControl() noexcept
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);
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
;
356 jackbridge_shm_close(shm
);
357 jackbridge_shm_init(shm
);
361 CARLA_SAFE_ASSERT(data
!= nullptr);
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
387 if (! jackbridge_shm_is_valid(shm
))
390 CARLA_SAFE_ASSERT(data
== nullptr);
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
);
412 void BridgeNonRtClientControl::unmapData() noexcept
416 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr,);
417 jackbridge_shm_unmap(shm
, data
);
421 setRingBuffer(nullptr, false);
424 void BridgeNonRtClientControl::waitIfDataIsReachingLimit() noexcept
426 CARLA_SAFE_ASSERT_RETURN(isServer
,);
428 if (getWritableDataSize() < BigStackBuffer::size
/4)
431 for (int i
=50; --i
>= 0;)
433 if (getWritableDataSize() >= BigStackBuffer::size
*3/4)
435 writeOpcode(kPluginBridgeNonRtClientPing
);
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
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);
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
;
496 jackbridge_shm_close(shm
);
497 jackbridge_shm_init(shm
);
501 CARLA_SAFE_ASSERT(data
!= nullptr);
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
527 if (! jackbridge_shm_is_valid(shm
))
529 CARLA_SAFE_ASSERT(data
== nullptr);
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
);
550 void BridgeNonRtServerControl::unmapData() noexcept
554 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr,);
555 jackbridge_shm_unmap(shm
, data
);
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)
576 for (int i
=50; --i
>= 0;)
578 if (getWritableDataSize() >= HugeStackBuffer::size
*3/4)
580 writeOpcode(kPluginBridgeNonRtServerPong
);
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 // -------------------------------------------------------------------------------------------------------------------