2 * Carla JACK API for external applications
3 * Copyright (C) 2016-2022 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 "libjack.hpp"
20 #include "CarlaThread.hpp"
21 #include "CarlaJuceUtils.hpp"
26 // ---------------------------------------------------------------------------------------------------------------------
28 CARLA_BACKEND_START_NAMESPACE
30 // ---------------------------------------------------------------------------------------------------------------------
32 static int64_t getCurrentTimeMilliseconds() noexcept
35 gettimeofday (&tv
, nullptr);
36 return ((int64_t) tv
.tv_sec
) * 1000 + tv
.tv_usec
/ 1000;
39 static int carla_interposed_callback(int, void*);
41 // ---------------------------------------------------------------------------------------------------------------------
43 class CarlaJackRealtimeThread
: public CarlaThread
48 virtual ~Callback() {};
49 virtual void runRealtimeThread() = 0;
52 CarlaJackRealtimeThread(Callback
* const callback
)
53 : CarlaThread("CarlaJackRealtimeThread"),
54 fCallback(callback
) {}
59 fCallback
->runRealtimeThread();
63 Callback
* const fCallback
;
65 CARLA_DECLARE_NON_COPYABLE(CarlaJackRealtimeThread
)
68 // --------------------------------------------------------------------------------------------------------------------
70 class CarlaJackNonRealtimeThread
: public CarlaThread
75 virtual ~Callback() {};
76 virtual void runNonRealtimeThread() = 0;
79 CarlaJackNonRealtimeThread(Callback
* const callback
)
80 : CarlaThread("CarlaJackNonRealtimeThread"),
81 fCallback(callback
) {}
86 fCallback
->runNonRealtimeThread();
90 Callback
* const fCallback
;
92 CARLA_DECLARE_NON_COPYABLE(CarlaJackNonRealtimeThread
)
95 // ---------------------------------------------------------------------------------------------------------------------
97 class CarlaJackAppClient
: public CarlaJackRealtimeThread::Callback
,
98 public CarlaJackNonRealtimeThread::Callback
101 JackServerState fServer
;
102 LinkedList
<JackClientState
*> fClients
;
103 LinkedList
<JackClientState
*> fNewClients
;
110 fShmRtClientControl(),
111 fShmNonRtClientControl(),
112 fShmNonRtServerControl(),
113 fAudioPoolCopy(nullptr),
114 fAudioTmpBuf(nullptr),
115 fDummyMidiInBuffer(true),
116 fDummyMidiOutBuffer(false),
117 fMidiInBuffers(nullptr),
118 fMidiOutBuffers(nullptr),
125 fRealtimeThread(this),
126 fNonRealtimeThread(this),
127 fRealtimeThreadMutex()
129 ,leakDetector_CarlaJackAppClient()
132 carla_debug("CarlaJackAppClient::CarlaJackAppClient() START");
134 const char* const shmIds(std::getenv("CARLA_SHM_IDS"));
135 CARLA_SAFE_ASSERT_INT2_RETURN(shmIds
!= nullptr && std::strlen(shmIds
) == 6*4,
136 shmIds
!= nullptr ? static_cast<int>(std::strlen(shmIds
)) : -1, 6*4,);
138 const char* const libjackSetup(std::getenv("CARLA_LIBJACK_SETUP"));
139 CARLA_SAFE_ASSERT_INT_RETURN(libjackSetup
!= nullptr && std::strlen(libjackSetup
) >= 6,
140 libjackSetup
!= nullptr ? static_cast<int>(std::strlen(libjackSetup
)) : -1,);
142 // make sure we don't get loaded again
143 carla_unsetenv("CARLA_SHM_IDS");
145 // kill ourselves if main carla dies
146 carla_terminateProcessOnParentExit(true);
148 for (int i
=4; --i
>= 0;) {
149 CARLA_SAFE_ASSERT_RETURN(libjackSetup
[i
] >= '0' && libjackSetup
[i
] <= '0'+64,);
151 CARLA_SAFE_ASSERT_RETURN(libjackSetup
[4] >= '0' && libjackSetup
[4] <= '0' + LIBJACK_SESSION_MANAGER_NSM
,);
152 CARLA_SAFE_ASSERT_RETURN(libjackSetup
[5] >= '0' && libjackSetup
[5] < '0'+0x4f,);
154 std::memcpy(fBaseNameAudioPool
, shmIds
+6*0, 6);
155 std::memcpy(fBaseNameRtClientControl
, shmIds
+6*1, 6);
156 std::memcpy(fBaseNameNonRtClientControl
, shmIds
+6*2, 6);
157 std::memcpy(fBaseNameNonRtServerControl
, shmIds
+6*3, 6);
159 fBaseNameAudioPool
[6] = '\0';
160 fBaseNameRtClientControl
[6] = '\0';
161 fBaseNameNonRtClientControl
[6] = '\0';
162 fBaseNameNonRtServerControl
[6] = '\0';
164 fServer
.numAudioIns
= static_cast<uint8_t>(libjackSetup
[0] - '0');
165 fServer
.numAudioOuts
= static_cast<uint8_t>(libjackSetup
[1] - '0');
166 fServer
.numMidiIns
= static_cast<uint8_t>(libjackSetup
[2] - '0');
167 fServer
.numMidiOuts
= static_cast<uint8_t>(libjackSetup
[3] - '0');
169 fSessionManager
= static_cast<uint
>(libjackSetup
[4] - '0');
170 fSetupHints
= static_cast<uint
>(libjackSetup
[5] - '0');
172 if (fSetupHints
& LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN
)
173 fServer
.numMidiOuts
= 16;
175 jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_HINTS_AND_CALLBACK
,
177 (void*)carla_interposed_callback
);
179 jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SET_SESSION_MANAGER
,
183 fNonRealtimeThread
.startThread(false);
186 carla_debug("CarlaJackAppClient::CarlaJackAppClient() DONE");
189 ~CarlaJackAppClient() noexcept override
191 carla_debug("CarlaJackAppClient::~CarlaJackAppClient() START");
195 fNonRealtimeThread
.stopThread(5000);
198 const CarlaMutexLocker
cms(fRealtimeThreadMutex
);
200 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
202 JackClientState
* const jclient(it
.getValue(nullptr));
203 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
214 carla_debug("CarlaJackAppClient::~CarlaJackAppClient() DONE");
217 JackClientState
* createClient(const char* const name
)
222 while (fNonRealtimeThread
.isThreadRunning() && ! fIsReady
)
225 return new JackClientState(fServer
, name
);
228 void destroyClient(JackClientState
* const jclient
)
231 const CarlaMutexLocker
cms(fRealtimeThreadMutex
);
232 fClients
.removeOne(jclient
);
238 bool activateClient(JackClientState
* const jclient
)
240 const CarlaMutexLocker
cms(fRealtimeThreadMutex
);
242 if (! fClients
.append(jclient
))
244 if (! fNewClients
.append(jclient
))
246 fClients
.removeOne(jclient
);
250 jclient
->activated
= true;
251 jclient
->deactivated
= false;
255 bool deactivateClient(JackClientState
* const jclient
)
257 const CarlaMutexLocker
cms(fRealtimeThreadMutex
);
259 if (! fClients
.removeOne(jclient
))
262 jclient
->activated
= false;
263 jclient
->deactivated
= true;
267 const char* getClientNameFromUUID(const jack_uuid_t uuid
) const noexcept
269 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
271 JackClientState
* const jclient(it
.getValue(nullptr));
272 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
274 if (jclient
->uuid
== uuid
)
275 return jclient
->name
;
281 jack_uuid_t
getUUIDForClientName(const char* const name
) const noexcept
283 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
285 JackClientState
* const jclient(it
.getValue(nullptr));
286 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
288 if (std::strcmp(jclient
->name
, name
) == 0)
289 return jclient
->uuid
;
292 return JACK_UUID_EMPTY_INITIALIZER
;
295 pthread_t
getRealtimeThreadId() const noexcept
297 return (pthread_t
)fRealtimeThread
.getThreadId();
300 int handleInterposerCallback(const int cb_action
, void* const ptr
)
302 carla_debug("handleInterposerCallback(%o, %p)", cb_action
, ptr
);
306 case LIBJACK_INTERPOSER_CALLBACK_UI_HIDE
: {
307 const CarlaMutexLocker
cml(fShmNonRtServerControl
.mutex
);
308 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerUiClosed
);
309 fShmNonRtServerControl
.commitWrite();
320 // -------------------------------------------------------------------
323 void runRealtimeThread() override
;
324 void runNonRealtimeThread() override
;
327 bool initSharedMemmory();
328 void clearSharedMemory() noexcept
;
331 bool handleNonRtData();
333 BridgeAudioPool fShmAudioPool
;
334 BridgeRtClientControl fShmRtClientControl
;
335 BridgeNonRtClientControl fShmNonRtClientControl
;
336 BridgeNonRtServerControl fShmNonRtServerControl
;
338 float* fAudioPoolCopy
;
341 JackMidiPortBufferDummy fDummyMidiInBuffer
;
342 JackMidiPortBufferDummy fDummyMidiOutBuffer
;
343 JackMidiPortBufferOnStack
* fMidiInBuffers
;
344 JackMidiPortBufferOnStack
* fMidiOutBuffers
;
346 char fBaseNameAudioPool
[6+1];
347 char fBaseNameRtClientControl
[6+1];
348 char fBaseNameNonRtClientControl
[6+1];
349 char fBaseNameNonRtServerControl
[6+1];
353 volatile bool fIsReady
;
354 int64_t fLastPingTime
;
356 uint fSessionManager
;
359 CarlaJackRealtimeThread fRealtimeThread
;
360 CarlaJackNonRealtimeThread fNonRealtimeThread
;
362 CarlaMutex fRealtimeThreadMutex
;
364 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaJackAppClient
)
367 // ---------------------------------------------------------------------------------------------------------------------
369 bool CarlaJackAppClient::initSharedMemmory()
371 if (! fShmAudioPool
.attachClient(fBaseNameAudioPool
))
373 carla_stderr("Failed to attach to audio pool shared memory");
377 if (! fShmRtClientControl
.attachClient(fBaseNameRtClientControl
))
380 carla_stderr("Failed to attach to rt client control shared memory");
384 if (! fShmRtClientControl
.mapData())
387 carla_stderr("Failed to map rt client control shared memory");
391 if (! fShmNonRtClientControl
.attachClient(fBaseNameNonRtClientControl
))
394 carla_stderr("Failed to attach to non-rt client control shared memory");
398 if (! fShmNonRtClientControl
.mapData())
401 carla_stderr("Failed to map non-rt control client shared memory");
405 if (! fShmNonRtServerControl
.attachClient(fBaseNameNonRtServerControl
))
408 carla_stderr("Failed to attach to non-rt server control shared memory");
412 if (! fShmNonRtServerControl
.mapData())
415 carla_stderr("Failed to map non-rt control server shared memory");
419 PluginBridgeNonRtClientOpcode opcode
;
421 opcode
= fShmNonRtClientControl
.readOpcode();
422 CARLA_SAFE_ASSERT_RETURN(opcode
== kPluginBridgeNonRtClientVersion
, false);
424 const uint32_t apiVersion
= fShmNonRtClientControl
.readUInt();
425 CARLA_SAFE_ASSERT_RETURN(apiVersion
== CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT
, false);
427 const uint32_t shmRtClientDataSize
= fShmNonRtClientControl
.readUInt();
428 CARLA_SAFE_ASSERT_INT2(shmRtClientDataSize
== sizeof(BridgeRtClientData
), shmRtClientDataSize
, sizeof(BridgeRtClientData
));
430 const uint32_t shmNonRtClientDataSize
= fShmNonRtClientControl
.readUInt();
431 CARLA_SAFE_ASSERT_INT2(shmNonRtClientDataSize
== sizeof(BridgeNonRtClientData
), shmNonRtClientDataSize
, sizeof(BridgeNonRtClientData
));
433 const uint32_t shmNonRtServerDataSize
= fShmNonRtClientControl
.readUInt();
434 CARLA_SAFE_ASSERT_INT2(shmNonRtServerDataSize
== sizeof(BridgeNonRtServerData
), shmNonRtServerDataSize
, sizeof(BridgeNonRtServerData
));
436 if (shmRtClientDataSize
!= sizeof(BridgeRtClientData
) ||
437 shmNonRtClientDataSize
!= sizeof(BridgeNonRtClientData
) ||
438 shmNonRtServerDataSize
!= sizeof(BridgeNonRtServerData
))
440 carla_stderr2("CarlaJackAppClient: data size mismatch");
444 opcode
= fShmNonRtClientControl
.readOpcode();
445 CARLA_SAFE_ASSERT_RETURN(opcode
== kPluginBridgeNonRtClientInitialSetup
, false);
447 fServer
.bufferSize
= fShmNonRtClientControl
.readUInt();
448 fServer
.sampleRate
= fShmNonRtClientControl
.readDouble();
450 if (fServer
.bufferSize
== 0 || carla_isZero(fServer
.sampleRate
))
452 carla_stderr2("CarlaJackAppClient: invalid empty state");
456 fAudioTmpBuf
= new float[fServer
.bufferSize
];
457 carla_zeroFloats(fAudioTmpBuf
, fServer
.bufferSize
);
459 fLastPingTime
= getCurrentTimeMilliseconds();
460 CARLA_SAFE_ASSERT(fLastPingTime
> 0);
463 // tell backend we're live
464 const CarlaMutexLocker
_cml(fShmNonRtServerControl
.mutex
);
467 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerReady
);
468 fShmNonRtServerControl
.commitWrite();
469 fShmNonRtServerControl
.waitIfDataIsReachingLimit();
476 void CarlaJackAppClient::clearSharedMemory() noexcept
478 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
480 if (fAudioPoolCopy
!= nullptr)
482 delete[] fAudioPoolCopy
;
483 fAudioPoolCopy
= nullptr;
486 if (fAudioTmpBuf
!= nullptr)
488 delete[] fAudioTmpBuf
;
489 fAudioTmpBuf
= nullptr;
492 if (fMidiInBuffers
!= nullptr)
494 delete[] fMidiInBuffers
;
495 fMidiInBuffers
= nullptr;
498 if (fMidiOutBuffers
!= nullptr)
500 delete[] fMidiOutBuffers
;
501 fMidiOutBuffers
= nullptr;
504 fShmAudioPool
.clear();
505 fShmRtClientControl
.clear();
506 fShmNonRtClientControl
.clear();
507 fShmNonRtServerControl
.clear();
510 bool CarlaJackAppClient::handleRtData()
512 if (fNewClients
.count() != 0)
514 for (LinkedList
<JackClientState
*>::Itenerator it
= fNewClients
.begin2(); it
.valid(); it
.next())
516 JackClientState
* const jclient(it
.getValue(nullptr));
517 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
519 if (jclient
->threadInitCb
!= nullptr)
520 jclient
->threadInitCb(jclient
->threadInitCbPtr
);
526 const BridgeRtClientControl::WaitHelper
helper(fShmRtClientControl
);
533 for (; fShmRtClientControl
.isDataAvailableForReading();)
535 const PluginBridgeRtClientOpcode
opcode(fShmRtClientControl
.readOpcode());
537 if (opcode
!= kPluginBridgeRtClientProcess
&& opcode
!= kPluginBridgeRtClientMidiEvent
) {
538 carla_debug("CarlaJackAppClientRtThread::run() - got opcode: %s", PluginBridgeRtClientOpcode2str(opcode
));
544 case kPluginBridgeRtClientNull
:
547 case kPluginBridgeRtClientSetAudioPool
: {
548 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
550 if (fShmAudioPool
.data
!= nullptr)
552 jackbridge_shm_unmap(fShmAudioPool
.shm
, fShmAudioPool
.data
);
553 fShmAudioPool
.data
= nullptr;
555 if (fAudioPoolCopy
!= nullptr)
557 delete[] fAudioPoolCopy
;
558 fAudioPoolCopy
= nullptr;
560 const uint64_t poolSize(fShmRtClientControl
.readULong());
561 CARLA_SAFE_ASSERT_BREAK(poolSize
> 0);
562 fShmAudioPool
.data
= (float*)jackbridge_shm_map(fShmAudioPool
.shm
, static_cast<size_t>(poolSize
));
563 fAudioPoolCopy
= new float[poolSize
];
567 case kPluginBridgeRtClientSetBufferSize
:
568 if (const uint32_t newBufferSize
= fShmRtClientControl
.readUInt())
570 if (fServer
.bufferSize
!= newBufferSize
)
572 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
574 fServer
.bufferSize
= newBufferSize
;
576 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
578 JackClientState
* const jclient(it
.getValue(nullptr));
579 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
581 if (jclient
->bufferSizeCb
!= nullptr)
582 jclient
->bufferSizeCb(fServer
.bufferSize
, jclient
->bufferSizeCbPtr
);
585 delete[] fAudioTmpBuf
;
586 fAudioTmpBuf
= new float[fServer
.bufferSize
];
587 carla_zeroFloats(fAudioTmpBuf
, fServer
.bufferSize
);
592 case kPluginBridgeRtClientSetSampleRate
: {
593 const double newSampleRate
= fShmRtClientControl
.readDouble();
595 if (carla_isNotZero(newSampleRate
) && carla_isNotEqual(fServer
.sampleRate
, newSampleRate
))
597 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
599 fServer
.sampleRate
= newSampleRate
;
601 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
603 JackClientState
* const jclient(it
.getValue(nullptr));
604 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
606 if (jclient
->sampleRateCb
!= nullptr)
607 jclient
->sampleRateCb(static_cast<uint32_t>(fServer
.sampleRate
), jclient
->sampleRateCbPtr
);
612 case kPluginBridgeRtClientSetOnline
: {
613 const bool offline
= fShmRtClientControl
.readBool();
615 if (fIsOffline
!= offline
)
617 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
619 fIsOffline
= offline
;
621 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
623 JackClientState
* const jclient(it
.getValue(nullptr));
624 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
626 if (jclient
->freewheelCb
!= nullptr)
627 jclient
->freewheelCb(offline
? 1 : 0, jclient
->freewheelCbPtr
);
632 case kPluginBridgeRtClientControlEventParameter
:
635 case kPluginBridgeRtClientControlEventMidiBank
: {
636 const uint32_t time
= fShmRtClientControl
.readUInt();
637 const uint8_t channel
= fShmRtClientControl
.readByte();
638 const uint16_t value
= fShmRtClientControl
.readUShort();
640 if (fServer
.numMidiIns
> 0 && fRealtimeThreadMutex
.tryLock())
642 JackMidiPortBufferOnStack
& midiPortBuf(fMidiInBuffers
[0]);
644 if (midiPortBuf
.count
+1U < JackMidiPortBufferBase::kMaxEventCount
&&
645 midiPortBuf
.bufferPoolPos
+ 6U < JackMidiPortBufferBase::kBufferPoolSize
)
647 jack_midi_event_t
& ev1(midiPortBuf
.events
[midiPortBuf
.count
++]);
650 ev1
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
651 ev1
.buffer
[0] = jack_midi_data_t(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
652 ev1
.buffer
[1] = MIDI_CONTROL_BANK_SELECT
;
654 midiPortBuf
.bufferPoolPos
+= 3;
656 jack_midi_event_t
& ev2(midiPortBuf
.events
[midiPortBuf
.count
++]);
659 ev2
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
660 ev2
.buffer
[0] = jack_midi_data_t(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
661 ev2
.buffer
[1] = MIDI_CONTROL_BANK_SELECT__LSB
;
662 ev2
.buffer
[2] = jack_midi_data_t(value
);
663 midiPortBuf
.bufferPoolPos
+= 3;
666 fRealtimeThreadMutex
.unlock(true);
671 case kPluginBridgeRtClientControlEventMidiProgram
: {
672 const uint32_t time
= fShmRtClientControl
.readUInt();
673 const uint8_t channel
= fShmRtClientControl
.readByte();
674 const uint16_t value
= fShmRtClientControl
.readUShort();
676 if (fServer
.numMidiIns
> 0 && fRealtimeThreadMutex
.tryLock())
678 JackMidiPortBufferOnStack
& midiPortBuf(fMidiInBuffers
[0]);
680 if (midiPortBuf
.count
< JackMidiPortBufferBase::kMaxEventCount
&&
681 midiPortBuf
.bufferPoolPos
+ 2U < JackMidiPortBufferBase::kBufferPoolSize
)
683 jack_midi_event_t
& ev(midiPortBuf
.events
[midiPortBuf
.count
++]);
687 ev
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
688 ev
.buffer
[0] = jack_midi_data_t(MIDI_STATUS_PROGRAM_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
689 ev
.buffer
[1] = jack_midi_data_t(value
);
690 midiPortBuf
.bufferPoolPos
+= 2;
693 fRealtimeThreadMutex
.unlock(true);
698 case kPluginBridgeRtClientControlEventAllSoundOff
: {
699 const uint32_t time
= fShmRtClientControl
.readUInt();
700 const uint8_t channel
= fShmRtClientControl
.readByte();
702 if (fServer
.numMidiIns
> 0 && fRealtimeThreadMutex
.tryLock())
704 JackMidiPortBufferOnStack
& midiPortBuf(fMidiInBuffers
[0]);
706 if (midiPortBuf
.count
< JackMidiPortBufferBase::kMaxEventCount
&&
707 midiPortBuf
.bufferPoolPos
+ 3U < JackMidiPortBufferBase::kBufferPoolSize
)
709 jack_midi_event_t
& ev(midiPortBuf
.events
[midiPortBuf
.count
++]);
713 ev
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
714 ev
.buffer
[0] = jack_midi_data_t(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
715 ev
.buffer
[1] = MIDI_CONTROL_ALL_SOUND_OFF
;
717 midiPortBuf
.bufferPoolPos
+= 3;
720 fRealtimeThreadMutex
.unlock(true);
725 case kPluginBridgeRtClientControlEventAllNotesOff
: {
726 const uint32_t time
= fShmRtClientControl
.readUInt();
727 const uint8_t channel
= fShmRtClientControl
.readByte();
729 if (fServer
.numMidiIns
> 0 && fRealtimeThreadMutex
.tryLock())
731 JackMidiPortBufferOnStack
& midiPortBuf(fMidiInBuffers
[0]);
733 if (midiPortBuf
.count
< JackMidiPortBufferBase::kMaxEventCount
&&
734 midiPortBuf
.bufferPoolPos
+ 3U < JackMidiPortBufferBase::kBufferPoolSize
)
736 jack_midi_event_t
& ev(midiPortBuf
.events
[midiPortBuf
.count
++]);
740 ev
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
741 ev
.buffer
[0] = jack_midi_data_t(MIDI_STATUS_CONTROL_CHANGE
| (channel
& MIDI_CHANNEL_BIT
));
742 ev
.buffer
[1] = MIDI_CONTROL_ALL_NOTES_OFF
;
744 midiPortBuf
.bufferPoolPos
+= 3;
747 fRealtimeThreadMutex
.unlock(true);
752 case kPluginBridgeRtClientMidiEvent
: {
753 const uint32_t time
= fShmRtClientControl
.readUInt();
754 const uint8_t port
= fShmRtClientControl
.readByte();
755 const uint8_t size
= fShmRtClientControl
.readByte();
756 CARLA_SAFE_ASSERT_BREAK(size
> 0);
758 if (port
>= fServer
.numMidiIns
|| size
> JackMidiPortBufferBase::kMaxEventSize
|| ! fRealtimeThreadMutex
.tryLock())
760 for (uint8_t i
=0; i
<size
; ++i
)
761 fShmRtClientControl
.readByte();
765 JackMidiPortBufferOnStack
& midiPortBuf(fMidiInBuffers
[port
]);
767 if (midiPortBuf
.count
< JackMidiPortBufferBase::kMaxEventCount
&&
768 midiPortBuf
.bufferPoolPos
+ size
< JackMidiPortBufferBase::kBufferPoolSize
)
770 jack_midi_event_t
& ev(midiPortBuf
.events
[midiPortBuf
.count
++]);
774 ev
.buffer
= midiPortBuf
.bufferPool
+ midiPortBuf
.bufferPoolPos
;
775 midiPortBuf
.bufferPoolPos
+= size
;
777 for (uint8_t i
=0; i
<size
; ++i
)
778 ev
.buffer
[i
] = fShmRtClientControl
.readByte();
781 fRealtimeThreadMutex
.unlock(true);
785 case kPluginBridgeRtClientProcess
: {
786 const uint32_t frames(fShmRtClientControl
.readUInt());
787 CARLA_SAFE_ASSERT_UINT2_BREAK(frames
== fServer
.bufferSize
, frames
, fServer
.bufferSize
);
789 // TODO tell client of xrun in case buffersize does not match
791 const CarlaMutexTryLocker
cmtl(fRealtimeThreadMutex
, fIsOffline
);
793 if (cmtl
.wasLocked())
795 CARLA_SAFE_ASSERT_BREAK(fShmAudioPool
.data
!= nullptr);
797 // mixdown is default, do buffer addition (for multiple clients) if requested
798 const bool doBufferAddition
= fSetupHints
& LIBJACK_FLAG_AUDIO_BUFFERS_ADDITION
;
799 // mixdown midi outputs based on channel if requested
800 const bool doMidiChanMixdown
= fSetupHints
& LIBJACK_FLAG_MIDI_OUTPUT_CHANNEL_MIXDOWN
;
802 // location to start of audio outputs (shm buffer)
803 float* const fdataRealOuts
= fShmAudioPool
.data
+(fServer
.bufferSize
*fServer
.numAudioIns
);
805 if (doBufferAddition
&& fServer
.numAudioOuts
> 0)
806 carla_zeroFloats(fdataRealOuts
, fServer
.bufferSize
*fServer
.numAudioOuts
);
808 if (! fClients
.isEmpty())
810 // save transport for all clients
811 const BridgeTimeInfo
& bridgeTimeInfo(fShmRtClientControl
.data
->timeInfo
);
813 const bool transportChanged
= fServer
.playing
!= bridgeTimeInfo
.playing
||
814 (bridgeTimeInfo
.playing
&& fServer
.position
.frame
+ frames
!= bridgeTimeInfo
.frame
);
816 fServer
.playing
= bridgeTimeInfo
.playing
;
817 fServer
.position
.frame
= static_cast<jack_nframes_t
>(bridgeTimeInfo
.frame
);
818 fServer
.position
.usecs
= bridgeTimeInfo
.usecs
;
820 fServer
.position
.frame_rate
= static_cast<jack_nframes_t
>(fServer
.sampleRate
);
822 if (bridgeTimeInfo
.validFlags
& kPluginBridgeTimeInfoValidBBT
)
824 fServer
.position
.bar
= bridgeTimeInfo
.bar
;
825 fServer
.position
.beat
= bridgeTimeInfo
.beat
;
826 fServer
.position
.tick
= static_cast<int32_t>(bridgeTimeInfo
.tick
+ 0.5);
828 fServer
.position
.beats_per_bar
= bridgeTimeInfo
.beatsPerBar
;
829 fServer
.position
.beat_type
= bridgeTimeInfo
.beatType
;
831 fServer
.position
.ticks_per_beat
= bridgeTimeInfo
.ticksPerBeat
;
832 fServer
.position
.beats_per_minute
= bridgeTimeInfo
.beatsPerMinute
;
833 fServer
.position
.bar_start_tick
= bridgeTimeInfo
.barStartTick
;
835 #ifdef JACK_TICK_DOUBLE
836 fServer
.position
.tick_double
= bridgeTimeInfo
.tick
;
837 fServer
.position
.valid
= static_cast<jack_position_bits_t
>(JackPositionBBT
|JackTickDouble
);
839 fServer
.position
.valid
= JackPositionBBT
;
844 fServer
.position
.valid
= static_cast<jack_position_bits_t
>(0x0);
847 int numClientOutputsProcessed
= 0;
849 // now go through each client
850 for (LinkedList
<JackClientState
*>::Itenerator it
= fClients
.begin2(); it
.valid(); it
.next())
852 JackClientState
* const jclient(it
.getValue(nullptr));
853 CARLA_SAFE_ASSERT_CONTINUE(jclient
!= nullptr);
855 const CarlaMutexTryLocker
cmtl2(jclient
->mutex
, fIsOffline
);
857 // check if we can process
858 if (cmtl2
.wasNotLocked() || jclient
->processCb
== nullptr || ! jclient
->activated
)
860 if (fServer
.numAudioOuts
> 0)
861 carla_zeroFloats(fdataRealOuts
, fServer
.bufferSize
*fServer
.numAudioOuts
);
863 if (jclient
->deactivated
)
864 fShmRtClientControl
.data
->procFlags
= 1;
868 // report transport sync changes if needed
869 if (transportChanged
&& jclient
->syncCb
!= nullptr)
871 jclient
->syncCb(fServer
.playing
? JackTransportRolling
: JackTransportStopped
,
877 // direct access to shm buffer, used only for inputs
878 float* fdataReal
= fShmAudioPool
.data
;
879 // safe temp location for output, mixed down to shm buffer later on
880 float* fdataCopy
= fAudioPoolCopy
;
881 // wherever we're using fAudioTmpBuf
882 bool needsTmpBufClear
= false;
886 for (LinkedList
<JackPortState
*>::Itenerator it2
= jclient
->audioIns
.begin2(); it2
.valid(); it2
.next())
888 JackPortState
* const jport
= it2
.getValue(nullptr);
889 CARLA_SAFE_ASSERT_CONTINUE(jport
!= nullptr);
891 if (i
++ < fServer
.numAudioIns
)
893 if (numClientOutputsProcessed
== 0 || ! doBufferAddition
)
894 jport
->buffer
= fdataReal
;
896 jport
->buffer
= fdataRealOuts
+ (i
*fServer
.bufferSize
);
898 fdataReal
+= fServer
.bufferSize
;
899 fdataCopy
+= fServer
.bufferSize
;
903 jport
->buffer
= fAudioTmpBuf
;
904 needsTmpBufClear
= true;
907 if (i
< fServer
.numAudioIns
)
909 const std::size_t remainingBufferSize
= fServer
.bufferSize
* static_cast<uint8_t>(fServer
.numAudioIns
- i
);
910 //fdataReal += remainingBufferSize;
911 fdataCopy
+= remainingBufferSize
;
914 // location to start of audio outputs
915 float* const fdataCopyOuts
= fdataCopy
;
919 for (LinkedList
<JackPortState
*>::Itenerator it2
= jclient
->audioOuts
.begin2(); it2
.valid(); it2
.next())
921 JackPortState
* const jport
= it2
.getValue(nullptr);
922 CARLA_SAFE_ASSERT_CONTINUE(jport
!= nullptr);
924 if (i
++ < fServer
.numAudioOuts
)
926 jport
->buffer
= fdataCopy
;
927 fdataCopy
+= fServer
.bufferSize
;
931 jport
->buffer
= fAudioTmpBuf
;
932 needsTmpBufClear
= true;
935 if (i
< fServer
.numAudioOuts
)
937 const std::size_t remainingBufferSize
= fServer
.bufferSize
* static_cast<uint8_t>(fServer
.numAudioOuts
- i
);
938 carla_zeroFloats(fdataCopy
, remainingBufferSize
);
939 //fdataCopy += remainingBufferSize;
944 for (LinkedList
<JackPortState
*>::Itenerator it2
= jclient
->midiIns
.begin2(); it2
.valid(); it2
.next())
946 JackPortState
* const jport
= it2
.getValue(nullptr);
947 CARLA_SAFE_ASSERT_CONTINUE(jport
!= nullptr);
949 if (i
++ < fServer
.numMidiIns
)
950 jport
->buffer
= &fMidiInBuffers
[i
-1];
952 jport
->buffer
= &fDummyMidiInBuffer
;
957 for (LinkedList
<JackPortState
*>::Itenerator it2
= jclient
->midiOuts
.begin2(); it2
.valid(); it2
.next())
959 JackPortState
* const jport
= it2
.getValue(nullptr);
960 CARLA_SAFE_ASSERT_CONTINUE(jport
!= nullptr);
962 if (i
++ < fServer
.numMidiOuts
)
963 jport
->buffer
= &fMidiOutBuffers
[i
-1];
965 jport
->buffer
= &fDummyMidiOutBuffer
;
968 if (needsTmpBufClear
)
969 carla_zeroFloats(fAudioTmpBuf
, fServer
.bufferSize
);
971 jclient
->processCb(fServer
.bufferSize
, jclient
->processCbPtr
);
973 if (fServer
.numAudioOuts
> 0)
975 if (++numClientOutputsProcessed
== 1)
977 // first client, we can copy stuff over
978 carla_copyFloats(fdataRealOuts
, fdataCopyOuts
,
979 fServer
.bufferSize
*fServer
.numAudioOuts
);
983 // subsequent clients, add data (then divide by number of clients later on)
984 carla_add(fdataRealOuts
, fdataCopyOuts
,
985 fServer
.bufferSize
*fServer
.numAudioOuts
);
987 if (doBufferAddition
)
989 // for more than 1 client addition, we need to divide buffers now
990 carla_multiply(fdataRealOuts
,
991 1.0f
/static_cast<float>(numClientOutputsProcessed
),
992 fServer
.bufferSize
*fServer
.numAudioOuts
);
996 if (jclient
->audioOuts
.count() == 1 && fServer
.numAudioOuts
> 1)
998 for (uint8_t j
=1; j
<fServer
.numAudioOuts
; ++j
)
1000 carla_copyFloats(fdataRealOuts
+(fServer
.bufferSize
*j
),
1002 fServer
.bufferSize
);
1009 if (numClientOutputsProcessed
> 1 && ! doBufferAddition
)
1011 // more than 1 client active, need to divide buffers
1012 carla_multiply(fdataRealOuts
,
1013 1.0f
/static_cast<float>(numClientOutputsProcessed
),
1014 fServer
.bufferSize
*fServer
.numAudioOuts
);
1017 // fClients.isEmpty()
1018 else if (fServer
.numAudioOuts
> 0)
1020 carla_zeroFloats(fdataRealOuts
, fServer
.bufferSize
*fServer
.numAudioOuts
);
1023 for (uint8_t i
=0; i
<fServer
.numMidiIns
; ++i
)
1025 fMidiInBuffers
[i
].count
= 0;
1026 fMidiInBuffers
[i
].bufferPoolPos
= 0;
1029 if (fServer
.numMidiOuts
> 0)
1031 uint8_t* midiData
= fShmRtClientControl
.data
->midiOut
;
1032 carla_zeroBytes(midiData
, kBridgeBaseMidiOutHeaderSize
);
1033 std::size_t curMidiDataPos
= 0;
1035 for (uint8_t i
=0; i
<fServer
.numMidiOuts
; ++i
)
1037 JackMidiPortBufferOnStack
& midiPortBuf(fMidiOutBuffers
[i
]);
1039 for (uint16_t j
=0; j
<midiPortBuf
.count
; ++j
)
1041 jack_midi_event_t
& jmevent(midiPortBuf
.events
[j
]);
1043 if (curMidiDataPos
+ kBridgeBaseMidiOutHeaderSize
+ jmevent
.size
>= kBridgeRtClientDataMidiOutSize
)
1046 if (doMidiChanMixdown
&& MIDI_IS_CHANNEL_MESSAGE(jmevent
.buffer
[0]))
1047 jmevent
.buffer
[0] = static_cast<jack_midi_data_t
>(
1048 (jmevent
.buffer
[0] & MIDI_STATUS_BIT
) | (i
& MIDI_CHANNEL_BIT
));
1051 *(uint32_t*)midiData
= jmevent
.time
;
1055 *midiData
++ = doMidiChanMixdown
? 0 : i
;
1058 *midiData
++ = static_cast<uint8_t>(jmevent
.size
);
1061 std::memcpy(midiData
, jmevent
.buffer
, jmevent
.size
);
1062 midiData
+= jmevent
.size
;
1064 curMidiDataPos
+= kBridgeBaseMidiOutHeaderSize
+ jmevent
.size
;
1068 // make last event null, so server stops when reaching it
1069 if (curMidiDataPos
!= 0 &&
1070 curMidiDataPos
+ kBridgeBaseMidiOutHeaderSize
< kBridgeRtClientDataMidiOutSize
)
1072 carla_zeroBytes(midiData
, kBridgeBaseMidiOutHeaderSize
);
1074 // sort events in case of mixdown
1075 if (doMidiChanMixdown
)
1078 uint8_t size
, *midiDataPtr
;
1079 uint8_t tmp
[kBridgeBaseMidiOutHeaderSize
+ JackMidiPortBufferBase::kMaxEventSize
];
1080 bool wasSorted
= true;
1084 midiDataPtr
= fShmRtClientControl
.data
->midiOut
;
1085 uint8_t* prevData
= midiDataPtr
;
1086 uint32_t prevTime
= *(uint32_t*)midiDataPtr
;
1087 uint8_t prevSize
= *(midiDataPtr
+ 5);
1092 time
= *(uint32_t*)midiDataPtr
;
1093 size
= *(midiDataPtr
+ 5); // time and port
1098 if (prevTime
> time
)
1100 // copy previous data to a temporary place
1101 std::memcpy(tmp
, prevData
, kBridgeBaseMidiOutHeaderSize
+ prevSize
);
1102 // override previous data with new one (shifting left)
1103 std::memcpy(prevData
, midiDataPtr
, kBridgeBaseMidiOutHeaderSize
+ size
);
1104 // override new data with old one
1105 std::memcpy(midiDataPtr
, tmp
, kBridgeBaseMidiOutHeaderSize
+ prevSize
);
1106 // done swapping, flag it
1112 prevData
= midiDataPtr
;
1113 midiDataPtr
+= 6 + size
;
1122 carla_stderr2("CarlaJackAppClient: fRealtimeThreadMutex tryLock failed");
1124 fServer
.monotonic_frame
+= frames
;
1128 case kPluginBridgeRtClientQuit
:
1134 if (opcode
!= kPluginBridgeRtClientProcess
&& opcode
!= kPluginBridgeRtClientMidiEvent
) {
1135 carla_debug("CarlaJackAppClientRtThread::run() - opcode %s done", PluginBridgeRtClientOpcode2str(opcode
));
1143 bool CarlaJackAppClient::handleNonRtData()
1147 for (; fShmNonRtClientControl
.isDataAvailableForReading();)
1149 const PluginBridgeNonRtClientOpcode
opcode(fShmNonRtClientControl
.readOpcode());
1151 if (opcode
!= kPluginBridgeNonRtClientPing
) {
1152 carla_debug("CarlaJackAppClient::handleNonRtData() - got opcode: %s", PluginBridgeNonRtClientOpcode2str(opcode
));
1156 if (opcode
!= kPluginBridgeNonRtClientNull
&& opcode
!= kPluginBridgeNonRtClientPingOnOff
&& fLastPingTime
> 0)
1157 fLastPingTime
= getCurrentTimeMilliseconds();
1161 case kPluginBridgeNonRtClientNull
:
1164 case kPluginBridgeNonRtClientVersion
: {
1165 const uint apiVersion
= fShmNonRtServerControl
.readUInt();
1166 CARLA_SAFE_ASSERT_UINT2(apiVersion
== CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT
,
1167 apiVersion
, CARLA_PLUGIN_BRIDGE_API_VERSION_CURRENT
);
1170 case kPluginBridgeNonRtClientPing
: {
1171 const CarlaMutexLocker
_cml(fShmNonRtServerControl
.mutex
);
1173 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerPong
);
1174 fShmNonRtServerControl
.commitWrite();
1177 case kPluginBridgeNonRtClientPingOnOff
: {
1178 const uint32_t onOff(fShmNonRtClientControl
.readBool());
1180 fLastPingTime
= onOff
? getCurrentTimeMilliseconds() : -1;
1183 case kPluginBridgeNonRtClientActivate
:
1184 case kPluginBridgeNonRtClientDeactivate
:
1187 case kPluginBridgeNonRtClientInitialSetup
:
1188 // should never happen!!
1189 fShmNonRtServerControl
.readUInt();
1190 fShmNonRtServerControl
.readDouble();
1193 case kPluginBridgeNonRtClientSetParameterValue
:
1194 case kPluginBridgeNonRtClientSetParameterMidiChannel
:
1195 case kPluginBridgeNonRtClientSetParameterMappedControlIndex
:
1196 case kPluginBridgeNonRtClientSetParameterMappedRange
:
1197 case kPluginBridgeNonRtClientSetProgram
:
1198 case kPluginBridgeNonRtClientSetMidiProgram
:
1199 case kPluginBridgeNonRtClientSetCustomData
:
1200 case kPluginBridgeNonRtClientSetChunkDataFile
:
1201 case kPluginBridgeNonRtClientSetWindowTitle
:
1204 case kPluginBridgeNonRtClientSetOption
:
1205 fShmNonRtClientControl
.readUInt();
1206 fShmNonRtClientControl
.readBool();
1209 case kPluginBridgeNonRtClientSetOptions
:
1210 fShmNonRtClientControl
.readUInt();
1213 case kPluginBridgeNonRtClientSetCtrlChannel
:
1214 fShmNonRtClientControl
.readShort();
1217 case kPluginBridgeNonRtClientGetParameterText
:
1218 fShmNonRtClientControl
.readUInt();
1221 case kPluginBridgeNonRtClientPrepareForSave
:
1223 if (fSessionManager
== LIBJACK_SESSION_MANAGER_AUTO
&& std::getenv("NSM_URL") == nullptr)
1225 struct sigaction sig
;
1226 carla_zeroStruct(sig
);
1228 sigaction(SIGUSR1
, nullptr, &sig
);
1230 if (sig
.sa_handler
!= nullptr)
1231 fSessionManager
= LIBJACK_SESSION_MANAGER_LADISH
;
1234 if (fSessionManager
== LIBJACK_SESSION_MANAGER_LADISH
)
1235 ::kill(::getpid(), SIGUSR1
);
1237 const CarlaMutexLocker
_cml(fShmNonRtServerControl
.mutex
);
1239 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerSaved
);
1240 fShmNonRtServerControl
.commitWrite();
1244 case kPluginBridgeNonRtClientRestoreLV2State
:
1247 case kPluginBridgeNonRtClientShowUI
:
1248 if (jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SHOW_HIDE_GUI
, 1, nullptr) == 1337)
1250 // failed, LD_PRELOAD did not work?
1251 const char* const message("Cannot show UI, LD_PRELOAD not working?");
1252 const std::size_t messageSize(std::strlen(message
));
1254 const CarlaMutexLocker
_cml(fShmNonRtServerControl
.mutex
);
1256 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerUiClosed
);
1257 fShmNonRtServerControl
.commitWrite();
1259 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerError
);
1260 fShmNonRtServerControl
.writeUInt(messageSize
);
1261 fShmNonRtServerControl
.writeCustomData(message
, messageSize
);
1262 fShmNonRtServerControl
.commitWrite();
1266 case kPluginBridgeNonRtClientHideUI
:
1267 jack_carla_interposed_action(LIBJACK_INTERPOSER_ACTION_SHOW_HIDE_GUI
, 0, nullptr);
1270 case kPluginBridgeNonRtClientUiParameterChange
:
1271 case kPluginBridgeNonRtClientUiProgramChange
:
1272 case kPluginBridgeNonRtClientUiMidiProgramChange
:
1273 case kPluginBridgeNonRtClientUiNoteOn
:
1274 case kPluginBridgeNonRtClientUiNoteOff
:
1277 case kPluginBridgeNonRtClientEmbedUI
:
1278 fShmNonRtClientControl
.readULong();
1281 case kPluginBridgeNonRtClientQuit
:
1285 case kPluginBridgeNonRtClientReload
:
1290 if (opcode
!= kPluginBridgeNonRtClientPing
) {
1291 carla_debug("CarlaJackAppClient::handleNonRtData() - opcode %s handled", PluginBridgeNonRtClientOpcode2str(opcode
));
1299 void CarlaJackAppClient::runRealtimeThread()
1301 carla_debug("CarlaJackAppClient runRealtimeThread START");
1303 #ifdef __SSE2_MATH__
1304 // Set FTZ and DAZ flags
1305 _mm_setcsr(_mm_getcsr() | 0x8040);
1308 bool quitReceived
= false;
1310 for (; ! fRealtimeThread
.shouldThreadExit();)
1314 quitReceived
= true;
1319 fNonRealtimeThread
.signalThreadShouldExit();
1321 carla_debug("CarlaJackAppClient runRealtimeThread FINISHED");
1324 return; (void)quitReceived
;
1327 void CarlaJackAppClient::runNonRealtimeThread()
1329 carla_debug("CarlaJackAppClient runNonRealtimeThread START");
1330 CARLA_SAFE_ASSERT_RETURN(initSharedMemmory(),);
1332 if (fServer
.numMidiIns
> 0)
1334 fMidiInBuffers
= new JackMidiPortBufferOnStack
[fServer
.numMidiIns
];
1336 for (uint8_t i
=0; i
<fServer
.numMidiIns
; ++i
)
1337 fMidiInBuffers
[i
].isInput
= true;
1340 if (fServer
.numMidiOuts
> 0)
1342 fMidiOutBuffers
= new JackMidiPortBufferOnStack
[fServer
.numMidiOuts
];
1344 for (uint8_t i
=0; i
<fServer
.numMidiOuts
; ++i
)
1345 fMidiOutBuffers
[i
].isInput
= false;
1348 fRealtimeThread
.startThread(true);
1350 fLastPingTime
= getCurrentTimeMilliseconds();
1351 carla_stdout("Carla Jack Client Ready!");
1353 bool quitReceived
= false,
1356 for (; ! fNonRealtimeThread
.shouldThreadExit();)
1361 quitReceived
= handleNonRtData();
1362 } CARLA_SAFE_EXCEPTION("handleNonRtData");
1368 if (fLastPingTime > 0 && getCurrentTimeMilliseconds() > fLastPingTime + 30000)
1370 carla_stderr("Did not receive ping message from server for 30 secs, closing...");
1373 fRealtimeThread.signalThreadShouldExit();
1379 //callback(true, true, ENGINE_CALLBACK_ENGINE_STOPPED, 0, 0, 0, 0.0f, nullptr);
1383 ::kill(::getpid(), SIGTERM
);
1387 // TODO send shutdown?
1388 carla_stderr("CarlaJackAppClient error: runNonRealtimeThread ended with time out");
1389 ::kill(::getpid(), SIGTERM
);
1396 const CarlaMutexLocker
cms(fRealtimeThreadMutex
);
1398 if (fClients
.isEmpty())
1402 else if (JackClientState
* const jclient
= fClients
.getLast(nullptr))
1404 const CarlaMutexLocker
cms2(jclient
->mutex
);
1405 activated
= jclient
->activated
;
1415 carla_stderr("CarlaJackAppClient error: runNonRealtimeThread ended while client is activated");
1417 const char* const message("Plugin bridge error, process thread has stopped");
1418 const std::size_t messageSize(std::strlen(message
));
1420 const CarlaMutexLocker
_cml(fShmNonRtServerControl
.mutex
);
1421 fShmNonRtServerControl
.writeOpcode(kPluginBridgeNonRtServerError
);
1422 fShmNonRtServerControl
.writeUInt(messageSize
);
1423 fShmNonRtServerControl
.writeCustomData(message
, messageSize
);
1424 fShmNonRtServerControl
.commitWrite();
1428 if (fRealtimeThread
.isThreadRunning())
1430 fRealtimeThread
.signalThreadShouldExit();
1432 const CarlaMutexLocker
cml(fRealtimeThreadMutex
);
1434 if (fShmRtClientControl
.data
!= nullptr)
1435 fShmRtClientControl
.data
->procFlags
= 1;
1438 clearSharedMemory();
1440 fRealtimeThread
.stopThread(5000);
1442 carla_debug("CarlaJackAppClient runNonRealtimeThread FINISHED");
1445 CARLA_BACKEND_END_NAMESPACE
1447 // ---------------------------------------------------------------------------------------------------------------------
1449 using CARLA_BACKEND_NAMESPACE::CarlaJackAppClient
;
1450 using CARLA_BACKEND_NAMESPACE::JackClientState
;
1452 static CarlaJackAppClient gClient
;
1454 CARLA_BACKEND_START_NAMESPACE
1456 static int carla_interposed_callback(int cb_action
, void* ptr
)
1458 return gClient
.handleInterposerCallback(cb_action
, ptr
);
1461 CARLA_BACKEND_END_NAMESPACE
1463 // ---------------------------------------------------------------------------------------------------------------------
1466 jack_client_t
* jack_client_open(const char* client_name
, jack_options_t options
, jack_status_t
* status
, ...)
1468 carla_debug("%s(%s, 0x%x, %p)", __FUNCTION__
, client_name
, options
, status
);
1470 if (JackClientState
* const client
= gClient
.createClient(client_name
))
1472 if (status
!= nullptr)
1473 *status
= static_cast<JackStatus
>(0x0);
1475 return (jack_client_t
*)client
;
1478 if (status
!= nullptr)
1479 *status
= JackServerError
;
1488 jack_client_t
* jack_client_new(const char* client_name
)
1490 return jack_client_open(client_name
, JackNullOption
, nullptr);
1494 int jack_client_close(jack_client_t
* client
)
1496 carla_debug("%s(%p)", __FUNCTION__
, client
);
1498 JackClientState
* const jclient
= (JackClientState
*)client
;
1499 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, 1);
1501 gClient
.destroyClient(jclient
);
1506 int jack_activate(jack_client_t
* client
)
1508 carla_debug("%s(%p)", __FUNCTION__
, client
);
1510 JackClientState
* const jclient
= (JackClientState
*)client
;
1511 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, 1);
1513 return gClient
.activateClient(jclient
) ? 0 : 1;
1517 int jack_deactivate(jack_client_t
* client
)
1519 carla_debug("%s(%p)", __FUNCTION__
, client
);
1521 JackClientState
* const jclient
= (JackClientState
*)client
;
1522 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, 1);
1524 return gClient
.deactivateClient(jclient
) ? 0 : 1;
1527 // ---------------------------------------------------------------------------------------------------------------------
1530 char* jack_get_client_name_by_uuid(jack_client_t
* const client
, const char* const uuidstr
)
1532 carla_debug("%s(%p, %s)", __FUNCTION__
, client
, uuidstr
);
1534 jack_uuid_t uuid
= JACK_UUID_EMPTY_INITIALIZER
;
1535 CARLA_SAFE_ASSERT_RETURN(jack_uuid_parse(uuidstr
, &uuid
) == 0, nullptr);
1537 JackClientState
* const jclient
= (JackClientState
*)client
;
1538 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, nullptr);
1540 const char* clientName
;
1542 if (jclient
->server
.uuid
== uuid
)
1543 return strdup("system");
1545 if (jclient
->uuid
== uuid
)
1547 clientName
= jclient
->name
;
1548 CARLA_SAFE_ASSERT_RETURN(clientName
!= nullptr, nullptr);
1552 CarlaJackAppClient
* const jackAppPtr
= jclient
->server
.jackAppPtr
;
1553 CARLA_SAFE_ASSERT_RETURN(jackAppPtr
!= nullptr && jackAppPtr
== &gClient
, nullptr);
1555 clientName
= jackAppPtr
->getClientNameFromUUID(uuid
);
1556 CARLA_SAFE_ASSERT_RETURN(clientName
!= nullptr, nullptr);
1559 return strdup(clientName
);
1563 char* jack_get_uuid_for_client_name(jack_client_t
* client
, const char* name
)
1565 carla_debug("%s(%p, %s)", __FUNCTION__
, client
, name
);
1567 JackClientState
* const jclient
= (JackClientState
*)client
;
1568 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, nullptr);
1570 if (std::strcmp(name
, "system") == 0)
1572 char* const uuidstr
= static_cast<char*>(std::malloc(JACK_UUID_STRING_SIZE
));
1573 CARLA_SAFE_ASSERT_RETURN(uuidstr
!= nullptr, nullptr);
1575 jack_uuid_unparse(jclient
->server
.uuid
, uuidstr
);
1580 CarlaJackAppClient
* const jackAppPtr
= jclient
->server
.jackAppPtr
;
1581 CARLA_SAFE_ASSERT_RETURN(jackAppPtr
!= nullptr && jackAppPtr
== &gClient
, nullptr);
1583 const jack_uuid_t uuid
= jackAppPtr
->getUUIDForClientName(name
);
1584 CARLA_SAFE_ASSERT_RETURN(uuid
!= JACK_UUID_EMPTY_INITIALIZER
, nullptr);
1586 char* const uuidstr
= static_cast<char*>(std::malloc(JACK_UUID_STRING_SIZE
));
1587 CARLA_SAFE_ASSERT_RETURN(uuidstr
!= nullptr, nullptr);
1589 jack_uuid_unparse(jclient
->uuid
, uuidstr
);
1594 // ---------------------------------------------------------------------------------------------------------------------
1597 pthread_t
jack_client_thread_id(jack_client_t
* client
)
1599 carla_debug("%s(%p)", __FUNCTION__
, client
);
1601 JackClientState
* const jclient
= (JackClientState
*)client
;
1602 CARLA_SAFE_ASSERT_RETURN(jclient
!= nullptr, 0);
1604 CarlaJackAppClient
* const jackAppPtr
= jclient
->server
.jackAppPtr
;
1605 CARLA_SAFE_ASSERT_RETURN(jackAppPtr
!= nullptr && jackAppPtr
== &gClient
, 0);
1607 return jackAppPtr
->getRealtimeThreadId();
1610 // ---------------------------------------------------------------------------------------------------------------------
1612 #include "jackbridge/JackBridge2.cpp"
1613 #include "CarlaBridgeUtils.cpp"
1615 // ---------------------------------------------------------------------------------------------------------------------
1618 CARLA_BACKEND_USE_NAMESPACE
1621 int jack_client_real_time_priority(jack_client_t
* client
)
1623 carla_debug("%s(%p)", __FUNCTION__
, client
);
1625 // code as used by water
1626 const int minPriority
= sched_get_priority_min(SCHED_RR
);
1627 const int maxPriority
= sched_get_priority_max(SCHED_RR
);
1628 return ((maxPriority
- minPriority
) * 9) / 10 + minPriority
;
1634 int jack_client_create_thread(jack_client_t
* client
, pthread_t
* thread
, int priority
,
1635 int realtime
, void *(*start_routine
)(void*), void* arg
)
1637 carla_stderr2("%s(%p, %p, %i, %i, %p, %p)", __FUNCTION__
, client
, thread
, priority
, realtime
, start_routine
, arg
);
1641 typedef void (*JackSessionCallback
)(jack_session_event_t
*, void*);
1644 int jack_set_session_callback(jack_client_t
* client
, JackSessionCallback callback
, void* arg
)
1646 carla_stderr2("%s(%p, %p, %p)", __FUNCTION__
, client
, callback
, arg
);
1650 // ---------------------------------------------------------------------------------------------------------------------