3 * Copyright (C) 2011-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 "CarlaEngineClient.hpp"
19 #include "CarlaEngineInit.hpp"
20 #include "CarlaEngineInternal.hpp"
21 #include "CarlaPlugin.hpp"
23 #include "CarlaBackendUtils.hpp"
24 #include "CarlaEngineUtils.hpp"
25 #include "CarlaMathUtils.hpp"
26 #include "CarlaMIDI.h"
27 #include "CarlaPatchbayUtils.hpp"
28 #include "CarlaStringList.hpp"
33 # include "carla_juce/carla_juce.h"
37 # include <xmmintrin.h>
41 #include "jackbridge/JackBridge.hpp"
43 #ifdef JACKBRIDGE_DIRECT
44 # define JackPortIsControlVoltage 0x100
47 #define URI_CANVAS_ICON "http://kxstudio.sf.net/ns/canvas/icon"
49 #define URI_MAIN_CLIENT_NAME "https://kx.studio/ns/carla/main-client-name"
50 #define URI_POSITION "https://kx.studio/ns/carla/position"
51 #define URI_PLUGIN_ICON "https://kx.studio/ns/carla/plugin-icon"
52 #define URI_PLUGIN_ID "https://kx.studio/ns/carla/plugin-id"
54 #define URI_TYPE_INTEGER "http://www.w3.org/2001/XMLSchema#integer"
55 #define URI_TYPE_STRING "text/plain"
57 CARLA_BACKEND_START_NAMESPACE
59 class CarlaEngineJack
;
60 class CarlaEngineJackClient
;
63 struct CarlaJackPortHints
{
71 // NOTE: assumes fThreadSafeMetadataMutex lock done from caller
72 static CarlaJackPortHints
fromPort(const jack_port_t
* const jackPort
)
74 CarlaJackPortHints ph
= { false, false, false, false, false, false };
76 const int portFlags
= jackbridge_port_flags(jackPort
);
77 const char* const portType
= jackbridge_port_type(jackPort
);
79 ph
.isHardware
= portFlags
& JackPortIsPhysical
;
80 ph
.isInput
= portFlags
& JackPortIsInput
;
81 ph
.isAudio
= portType
!= nullptr && std::strcmp(portType
, JACK_DEFAULT_AUDIO_TYPE
) == 0;
82 ph
.isMIDI
= portType
!= nullptr && std::strcmp(portType
, JACK_DEFAULT_MIDI_TYPE
) == 0;
86 if (ph
.isAudio
&& portFlags
& JackPortIsControlVoltage
)
92 if (const jack_uuid_t uuid
= jackbridge_port_uuid(jackPort
))
94 char* value
= nullptr;
97 if (jackbridge_get_property(uuid
, JACKEY_SIGNAL_TYPE
, &value
, &type
)
100 && std::strcmp(type
, URI_TYPE_STRING
) == 0)
102 ph
.isCV
= (std::strcmp(value
, "CV") == 0);
103 ph
.isOSC
= (std::strcmp(value
, "OSC") == 0);
110 jackbridge_free(value
);
111 jackbridge_free(type
);
120 // -----------------------------------------------------------------------
124 static const GroupNameToId kGroupNameToIdFallback
= { 0, { '\0' } };
125 static /* */ PortNameToId kPortNameToIdFallbackNC
= { 0, 0, { '\0' }, { '\0' }, { '\0' } };
126 static const PortNameToId kPortNameToIdFallback
= { 0, 0, { '\0' }, { '\0' }, { '\0' } };
127 static const ConnectionToId kConnectionToIdFallback
= { 0, 0, 0, 0, 0 };
129 static EngineEvent kFallbackJackEngineEvent
= {
130 kEngineEventTypeNull
, 0, 0, {{ kEngineControlEventTypeNull
, 0, -1, 0.0f
, true }}
133 // -----------------------------------------------------------------------
134 // Carla Engine Port removal helper
136 class CarlaEngineJackAudioPort
;
137 class CarlaEngineJackCVPort
;
138 class CarlaEngineJackEventPort
;
140 struct JackPortDeletionCallback
{
141 virtual ~JackPortDeletionCallback() noexcept
{}
142 virtual void jackAudioPortDeleted(CarlaEngineJackAudioPort
* const) noexcept
= 0;
143 virtual void jackCVPortDeleted(CarlaEngineJackCVPort
* const) noexcept
= 0;
144 virtual void jackEventPortDeleted(CarlaEngineJackEventPort
* const) noexcept
= 0;
147 // -----------------------------------------------------------------------
148 // Carla Engine JACK-Audio port
150 class CarlaEngineJackAudioPort
: public CarlaEngineAudioPort
153 CarlaEngineJackAudioPort(const CarlaEngineClient
& client
,
154 const bool isInputPort
,
155 const uint32_t indexOffset
,
156 jack_client_t
* const jackClient
,
157 jack_port_t
* const jackPort
,
158 CarlaRecursiveMutex
& rmutex
,
159 JackPortDeletionCallback
* const delCallback
) noexcept
160 : CarlaEngineAudioPort(client
, isInputPort
, indexOffset
),
161 fJackClient(jackClient
),
163 fThreadSafeMetadataMutex(rmutex
),
164 kDeletionCallback(delCallback
)
166 carla_debug("CarlaEngineJackAudioPort::CarlaEngineJackAudioPort(%s, %p, %p)", bool2str(isInputPort
), jackClient
, jackPort
);
168 switch (kClient
.getEngine().getProccessMode())
170 case ENGINE_PROCESS_MODE_SINGLE_CLIENT
:
171 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
:
172 CARLA_SAFE_ASSERT_RETURN(jackClient
!= nullptr && jackPort
!= nullptr,);
174 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
176 if (const jack_uuid_t uuid
= jackbridge_port_uuid(jackPort
))
177 jackbridge_set_property(jackClient
, uuid
, JACKEY_SIGNAL_TYPE
, "AUDIO", URI_TYPE_STRING
);
182 CARLA_SAFE_ASSERT(jackClient
== nullptr && jackPort
== nullptr);
187 ~CarlaEngineJackAudioPort() noexcept override
189 carla_debug("CarlaEngineJackAudioPort::~CarlaEngineJackAudioPort()");
191 if (fJackClient
!= nullptr && fJackPort
!= nullptr)
194 jackbridge_port_unregister(fJackClient
, fJackPort
);
195 } CARLA_SAFE_EXCEPTION("Audio port unregister");
197 fJackClient
= nullptr;
201 if (kDeletionCallback
!= nullptr)
202 kDeletionCallback
->jackAudioPortDeleted(this);
205 void initBuffer() noexcept override
207 if (fJackPort
== nullptr)
208 return CarlaEngineAudioPort::initBuffer();
210 const uint32_t bufferSize(kClient
.getEngine().getBufferSize());
213 fBuffer
= (float*)jackbridge_port_get_buffer(fJackPort
, bufferSize
);
221 carla_zeroFloats(fBuffer
, bufferSize
);
224 void invalidate() noexcept
226 fJackClient
= nullptr;
230 void setMetaData(const char* const key
, const char* const value
, const char* const type
) override
232 if (fJackPort
== nullptr)
233 return CarlaEngineAudioPort::setMetaData(key
, value
, type
);
235 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
238 if (const jack_uuid_t uuid
= jackbridge_port_uuid(fJackPort
))
239 jackbridge_set_property(fJackClient
, uuid
, key
, value
, type
);
240 } CARLA_SAFE_EXCEPTION("Port setMetaData");
244 jack_client_t
* fJackClient
;
245 jack_port_t
* fJackPort
;
247 CarlaRecursiveMutex
& fThreadSafeMetadataMutex
;
248 JackPortDeletionCallback
* const kDeletionCallback
;
250 friend class CarlaEngineJackClient
;
252 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort
)
255 // -----------------------------------------------------------------------
256 // Carla Engine JACK-CV port
258 class CarlaEngineJackCVPort
: public CarlaEngineCVPort
261 CarlaEngineJackCVPort(const CarlaEngineClient
& client
,
262 const bool isInputPort
,
263 const uint32_t indexOffset
,
264 jack_client_t
* const jackClient
,
265 jack_port_t
* const jackPort
,
266 CarlaRecursiveMutex
& rmutex
,
267 JackPortDeletionCallback
* const delCallback
) noexcept
268 : CarlaEngineCVPort(client
, isInputPort
, indexOffset
),
269 fJackClient(jackClient
),
271 fThreadSafeMetadataMutex(rmutex
),
272 kDeletionCallback(delCallback
)
274 carla_debug("CarlaEngineJackCVPort::CarlaEngineJackCVPort(%s, %p, %p)", bool2str(isInputPort
), jackClient
, jackPort
);
276 switch (kClient
.getEngine().getProccessMode())
278 case ENGINE_PROCESS_MODE_SINGLE_CLIENT
:
279 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
:
280 CARLA_SAFE_ASSERT_RETURN(jackClient
!= nullptr && jackPort
!= nullptr,);
282 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
284 if (const jack_uuid_t uuid
= jackbridge_port_uuid(jackPort
))
285 jackbridge_set_property(jackClient
, uuid
, JACKEY_SIGNAL_TYPE
, "CV", URI_TYPE_STRING
);
290 CARLA_SAFE_ASSERT(jackClient
== nullptr && jackPort
== nullptr);
295 ~CarlaEngineJackCVPort() noexcept override
297 carla_debug("CarlaEngineJackCVPort::~CarlaEngineJackCVPort()");
299 if (fJackClient
!= nullptr && fJackPort
!= nullptr)
302 jackbridge_port_unregister(fJackClient
, fJackPort
);
303 } CARLA_SAFE_EXCEPTION("CV port unregister");
305 fJackClient
= nullptr;
309 if (kDeletionCallback
!= nullptr)
310 kDeletionCallback
->jackCVPortDeleted(this);
313 void initBuffer() noexcept override
315 if (fJackPort
== nullptr)
316 return CarlaEngineCVPort::initBuffer();
318 const uint32_t bufferSize(kClient
.getEngine().getBufferSize());
321 fBuffer
= (float*)jackbridge_port_get_buffer(fJackPort
, bufferSize
);
329 carla_zeroFloats(fBuffer
, bufferSize
);
332 void invalidate() noexcept
334 fJackClient
= nullptr;
338 void setMetaData(const char* const key
, const char* const value
, const char* const type
) override
340 if (fJackPort
== nullptr)
341 return CarlaEngineCVPort::setMetaData(key
, value
, type
);
343 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
346 if (const jack_uuid_t uuid
= jackbridge_port_uuid(fJackPort
))
347 jackbridge_set_property(fJackClient
, uuid
, key
, value
, type
);
348 } CARLA_SAFE_EXCEPTION("Port setMetaData");
352 jack_client_t
* fJackClient
;
353 jack_port_t
* fJackPort
;
355 CarlaRecursiveMutex
& fThreadSafeMetadataMutex
;
356 JackPortDeletionCallback
* const kDeletionCallback
;
358 friend class CarlaEngineJackClient
;
360 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackCVPort
)
363 // -----------------------------------------------------------------------
364 // Carla Engine JACK-Event port
366 class CarlaEngineJackEventPort
: public CarlaEngineEventPort
369 CarlaEngineJackEventPort(const CarlaEngineClient
& client
,
370 const bool isInputPort
,
371 const uint32_t indexOffset
,
372 jack_client_t
* const jackClient
,
373 jack_port_t
* const jackPort
,
374 CarlaRecursiveMutex
& rmutex
,
375 JackPortDeletionCallback
* const delCallback
) noexcept
376 : CarlaEngineEventPort(client
, isInputPort
, indexOffset
),
377 fJackClient(jackClient
),
379 fJackBuffer(nullptr),
380 fRetEvent(kFallbackJackEngineEvent
),
381 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
382 fCvSourceEvents(nullptr),
383 fCvSourceEventCount(0),
385 fThreadSafeMetadataMutex(rmutex
),
386 kDeletionCallback(delCallback
)
388 carla_debug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %p, %p)", bool2str(isInputPort
), jackClient
, jackPort
);
390 switch (kClient
.getEngine().getProccessMode())
392 case ENGINE_PROCESS_MODE_SINGLE_CLIENT
:
393 case ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
:
394 CARLA_SAFE_ASSERT_RETURN(jackClient
!= nullptr && jackPort
!= nullptr,);
397 CARLA_SAFE_ASSERT(jackClient
== nullptr && jackPort
== nullptr);
402 ~CarlaEngineJackEventPort() noexcept override
404 carla_debug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()");
406 if (fJackClient
!= nullptr && fJackPort
!= nullptr)
409 jackbridge_port_unregister(fJackClient
, fJackPort
);
410 } CARLA_SAFE_EXCEPTION("Event port unregister");
412 fJackClient
= nullptr;
416 if (kDeletionCallback
!= nullptr)
417 kDeletionCallback
->jackEventPortDeleted(this);
420 void initBuffer() noexcept override
422 if (fJackPort
== nullptr)
423 return CarlaEngineEventPort::initBuffer();
425 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
426 fCvSourceEvents
= nullptr;
427 fCvSourceEventCount
= 0;
431 fJackBuffer
= jackbridge_port_get_buffer(fJackPort
, kClient
.getEngine().getBufferSize());
434 fJackBuffer
= nullptr;
439 jackbridge_midi_clear_buffer(fJackBuffer
);
442 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
443 void setCvSourceEvents(EngineEvent
* const events
, const uint32_t eventCount
) noexcept
445 fCvSourceEvents
= events
;
446 fCvSourceEventCount
= eventCount
;
450 uint32_t getEventCount() const noexcept override
452 if (fJackPort
== nullptr)
453 return CarlaEngineEventPort::getEventCount();
455 CARLA_SAFE_ASSERT_RETURN(kIsInput
, 0);
456 CARLA_SAFE_ASSERT_RETURN(fJackBuffer
!= nullptr, 0);
459 return jackbridge_midi_get_event_count(fJackBuffer
)
460 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
461 + fCvSourceEventCount
464 } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_get_event_count", 0);
467 EngineEvent
& getEvent(const uint32_t index
) const noexcept override
469 if (fJackPort
== nullptr)
470 return CarlaEngineEventPort::getEvent(index
);
472 CARLA_SAFE_ASSERT_RETURN(kIsInput
, kFallbackJackEngineEvent
);
473 CARLA_SAFE_ASSERT_RETURN(fJackBuffer
!= nullptr, kFallbackJackEngineEvent
);
475 return getEventUnchecked(index
);
478 EngineEvent
& getEventUnchecked(uint32_t index
) const noexcept override
480 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
481 if (index
< fCvSourceEventCount
)
482 return fCvSourceEvents
[index
];
484 index
-= fCvSourceEventCount
;
487 jack_midi_event_t jackEvent
;
492 test
= jackbridge_midi_event_get(&jackEvent
, fJackBuffer
, index
);
493 } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_get", kFallbackJackEngineEvent
);
496 return kFallbackJackEngineEvent
;
498 CARLA_SAFE_ASSERT_RETURN(jackEvent
.size
< 0xFF /* uint8_t max */, kFallbackJackEngineEvent
);
502 if (kIndexOffset
< 0xFF /* uint8_t max */)
504 port
= static_cast<uint8_t>(kIndexOffset
);
509 carla_safe_assert_uint("kIndexOffset < 0xFF", __FILE__
, __LINE__
, kIndexOffset
);
512 fRetEvent
.time
= jackEvent
.time
;
513 fRetEvent
.fillFromMidiData(static_cast<uint8_t>(jackEvent
.size
), jackEvent
.buffer
, port
);
518 bool writeControlEvent(const uint32_t time
, const uint8_t channel
,
519 const EngineControlEventType type
,
520 const uint16_t param
,
521 const int8_t midiValue
,
522 const float value
) noexcept override
524 if (fJackPort
== nullptr)
525 return CarlaEngineEventPort::writeControlEvent(time
, channel
, type
, param
, midiValue
, value
);
527 CARLA_SAFE_ASSERT_RETURN(! kIsInput
, false);
528 CARLA_SAFE_ASSERT_RETURN(fJackBuffer
!= nullptr, false);
529 CARLA_SAFE_ASSERT_RETURN(type
!= kEngineControlEventTypeNull
, false);
530 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
, false);
531 CARLA_SAFE_ASSERT_RETURN(param
< MAX_MIDI_VALUE
, false);
532 CARLA_SAFE_ASSERT(value
>= 0.0f
&& value
<= 1.0f
);
534 if (type
== kEngineControlEventTypeParameter
) {
535 CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param
));
538 uint8_t data
[3] = { 0, 0, 0 };
540 EngineControlEvent ctrlEvent
= { type
, param
, midiValue
, value
, false };
541 const uint8_t size
= ctrlEvent
.convertToMidiData(channel
, data
);
547 return jackbridge_midi_event_write(fJackBuffer
, time
, data
, size
);
548 } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_write", false);
551 bool writeMidiEvent(const uint32_t time
, const uint8_t channel
, const uint8_t size
, const uint8_t* const data
) noexcept override
553 if (fJackPort
== nullptr)
554 return CarlaEngineEventPort::writeMidiEvent(time
, channel
, size
, data
);
556 CARLA_SAFE_ASSERT_RETURN(! kIsInput
, false);
557 CARLA_SAFE_ASSERT_RETURN(fJackBuffer
!= nullptr, false);
558 CARLA_SAFE_ASSERT_RETURN(channel
< MAX_MIDI_CHANNELS
, false);
559 CARLA_SAFE_ASSERT_RETURN(size
> 0, false);
560 CARLA_SAFE_ASSERT_RETURN(data
!= nullptr, false);
562 jack_midi_data_t jdata
[size
];
564 jdata
[0] = static_cast<jack_midi_data_t
>(MIDI_GET_STATUS_FROM_DATA(data
) + channel
);
566 for (uint8_t i
=1; i
< size
; ++i
)
570 return jackbridge_midi_event_write(fJackBuffer
, time
, jdata
, size
);
571 } CARLA_SAFE_EXCEPTION_RETURN("jack_midi_event_write", false);
574 void invalidate() noexcept
576 fJackClient
= nullptr;
580 void setMetaData(const char* const key
, const char* const value
, const char* const type
) override
582 if (fJackPort
== nullptr)
583 return CarlaEngineEventPort::setMetaData(key
, value
, type
);
585 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
588 if (const jack_uuid_t uuid
= jackbridge_port_uuid(fJackPort
))
589 jackbridge_set_property(fJackClient
, uuid
, key
, value
, type
);
590 } CARLA_SAFE_EXCEPTION("Port setMetaData");
594 jack_client_t
* fJackClient
;
595 jack_port_t
* fJackPort
;
598 mutable EngineEvent fRetEvent
;
600 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
601 EngineEvent
* fCvSourceEvents
;
602 uint32_t fCvSourceEventCount
;
605 CarlaRecursiveMutex
& fThreadSafeMetadataMutex
;
606 JackPortDeletionCallback
* const kDeletionCallback
;
608 friend class CarlaEngineJackClient
;
610 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort
)
613 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
614 // -----------------------------------------------------------------------
615 // Jack Engine CV source ports
617 class CarlaEngineJackCVSourcePorts
: public CarlaEngineCVSourcePorts
620 CarlaEngineJackCVSourcePorts(const bool useClient
)
621 : CarlaEngineCVSourcePorts(),
622 fUseClient(useClient
),
624 fBufferToDeleteLater(nullptr)
627 ~CarlaEngineJackCVSourcePorts() override
629 if (fBufferToDeleteLater
!= nullptr)
631 delete[] fBufferToDeleteLater
;
632 fBufferToDeleteLater
= nullptr;
636 bool addCVSource(CarlaEngineCVPort
* const port
, const uint32_t portIndexOffset
, const bool reconfigureNow
) override
639 return CarlaEngineCVSourcePorts::addCVSource(port
, portIndexOffset
, reconfigureNow
);
641 const CarlaRecursiveMutexLocker
crml(pData
->rmutex
);
643 if (! CarlaEngineCVSourcePorts::addCVSource(port
, portIndexOffset
, reconfigureNow
))
646 if (pData
->cvs
.size() == 1 && fBuffer
== nullptr)
648 EngineEvent
* const buffer
= new EngineEvent
[kMaxEngineEventInternalCount
];
649 carla_zeroStructs(buffer
, kMaxEngineEventInternalCount
);
657 bool removeCVSource(const uint32_t portIndexOffset
) override
660 return CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset
);
662 const CarlaRecursiveMutexLocker
crml(pData
->rmutex
);
664 if (! CarlaEngineCVSourcePorts::removeCVSource(portIndexOffset
))
667 if (pData
->cvs
.size() == 0 && fBuffer
!= nullptr)
669 if (fBufferToDeleteLater
!= nullptr)
670 delete[] fBufferToDeleteLater
;
672 fBufferToDeleteLater
= fBuffer
;
679 void initPortBuffers(const float* const* const buffers
,
680 const uint32_t frames
,
681 const bool sampleAccurate
,
682 CarlaEngineEventPort
* const eventPort
) override
685 return CarlaEngineCVSourcePorts::initPortBuffers(buffers
, frames
, sampleAccurate
, eventPort
);
687 CARLA_SAFE_ASSERT_RETURN(buffers
!= nullptr,);
688 CARLA_SAFE_ASSERT_RETURN(eventPort
!= nullptr,);
690 const CarlaRecursiveMutexTryLocker
crmtl(pData
->rmutex
);
692 if (! crmtl
.wasLocked())
695 const int numCVs
= pData
->cvs
.size();
700 EngineEvent
* const buffer
= fBuffer
;
701 CARLA_SAFE_ASSERT_RETURN(buffer
!= nullptr,);
703 uint32_t eventCount
= 0;
706 for (int i
= 0; i
< numCVs
&& eventCount
< kMaxEngineEventInternalCount
; ++i
)
708 CarlaEngineEventCV
& ecv(pData
->cvs
.getReference(i
));
709 CARLA_SAFE_ASSERT_CONTINUE(ecv
.cvPort
!= nullptr);
710 CARLA_SAFE_ASSERT_CONTINUE(buffers
[i
] != nullptr);
712 float previousValue
= ecv
.previousValue
;
713 ecv
.cvPort
->getRange(min
, max
);
717 if (carla_isNotEqual(v
, previousValue
))
721 EngineEvent
& event(buffer
[eventCount
++]);
723 event
.type
= kEngineEventTypeControl
;
725 event
.channel
= kEngineEventNonMidiChannel
;
727 event
.ctrl
.type
= kEngineControlEventTypeParameter
;
728 event
.ctrl
.param
= static_cast<uint16_t>(ecv
.indexOffset
);
729 event
.ctrl
.midiValue
= -1;
730 event
.ctrl
.normalizedValue
= carla_fixedValue(0.0f
, 1.0f
, (v
- min
) / (max
- min
));
733 ecv
.previousValue
= previousValue
;
737 if (CarlaEngineJackEventPort
* const jackEventPort
= dynamic_cast<CarlaEngineJackEventPort
*>(eventPort
))
738 jackEventPort
->setCvSourceEvents(buffer
, eventCount
);
741 CarlaRecursiveMutex
& getMutex() const noexcept
743 return pData
->rmutex
;
746 uint32_t getPortCount() const noexcept
748 return static_cast<uint32_t>(pData
->cvs
.size());
751 CarlaEngineCVPort
* getPort(const uint32_t portIndexOffset
) const
753 const int ioffset
= static_cast<int>(portIndexOffset
);
754 return pData
->cvs
[ioffset
].cvPort
;
757 void resetGraphAndPlugin() noexcept
759 pData
->graph
= nullptr;
760 pData
->plugin
.reset();
763 void setGraphAndPlugin(PatchbayGraph
* const graph
, const CarlaPluginPtr plugin
) noexcept
765 pData
->graph
= graph
;
766 pData
->plugin
= plugin
;
770 const bool fUseClient
;
771 EngineEvent
* fBuffer
;
772 EngineEvent
* fBufferToDeleteLater
;
774 CARLA_DECLARE_NON_COPYABLE(CarlaEngineJackCVSourcePorts
)
778 // -----------------------------------------------------------------------
779 // Jack Engine client
781 class CarlaEngineJackClient
: public CarlaEngineClientForSubclassing
,
782 private JackPortDeletionCallback
785 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
786 CarlaEngineJackClient(const CarlaEngine
& engine
,
787 EngineInternalGraph
& egraph
,
788 CarlaRecursiveMutex
& rmutex
,
789 const CarlaPluginPtr plugin
,
790 const CarlaString
& mainClientName
,
791 jack_client_t
* const jackClient
)
792 : CarlaEngineClientForSubclassing(engine
, egraph
, plugin
),
794 CarlaEngineJackClient(const CarlaEngine
& engine
,
795 CarlaRecursiveMutex
& rmutex
,
796 const CarlaString
& mainClientName
,
797 jack_client_t
* const jackClient
)
798 : CarlaEngineClientForSubclassing(engine
),
800 fJackClient(jackClient
),
801 fUseClient(engine
.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT
||
802 engine
.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
),
806 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
807 fCVSourcePorts(fUseClient
),
809 fPreRenameConnections(),
810 fPreRenamePluginId(),
811 fPreRenamePluginIcon(),
812 fReservedPluginPtr(),
814 fThreadSafeMetadataMutex(rmutex
),
815 fMainClientName(mainClientName
)
817 carla_debug("CarlaEngineJackClient::CarlaEngineJackClient(%p)", jackClient
);
821 CARLA_SAFE_ASSERT(jackClient
!= nullptr);
825 CARLA_SAFE_ASSERT(jackClient
== nullptr);
829 ~CarlaEngineJackClient() noexcept override
831 carla_debug("CarlaEngineJackClient::~CarlaEngineJackClient()");
833 if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
&& fJackClient
!= nullptr) // FIXME
834 jackbridge_client_close(fJackClient
);
836 // ports must have been deleted by now!
837 //fAudioPorts.clear();
839 //fEventPorts.clear();
841 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
842 const CarlaMutexLocker
cml(fPreRenameMutex
);
844 fPreRenameConnections
.clear();
845 fPreRenamePluginId
.clear();
846 fPreRenamePluginIcon
.clear();
850 void activate() noexcept override
852 carla_debug("CarlaEngineJackClient::activate()");
854 if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
856 CARLA_SAFE_ASSERT_RETURN(fJackClient
!= nullptr && ! isActive(),);
859 jackbridge_activate(fJackClient
);
863 CarlaEngineClient::activate();
865 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
866 const CarlaMutexLocker
cml(fPreRenameMutex
);
868 if (fJackClient
!= nullptr)
870 // restore pre-rename connections
871 const char* portNameA
= nullptr;
872 const char* portNameB
= nullptr;
873 bool doConnection
= false;
875 for (CarlaStringList::Itenerator it
= fPreRenameConnections
.begin2(); it
.valid(); it
.next())
877 const bool connectNow
= doConnection
;
878 doConnection
= !doConnection
;
881 portNameB
= it
.getValue(nullptr);
883 portNameA
= it
.getValue(nullptr);
888 CARLA_SAFE_ASSERT_CONTINUE(portNameA
!= nullptr && portNameA
[0] != '\0');
889 CARLA_SAFE_ASSERT_CONTINUE(portNameB
!= nullptr && portNameB
[0] != '\0');
891 jackbridge_connect(fJackClient
, portNameA
, portNameB
);
894 if (fPreRenamePluginId
.isNotEmpty())
896 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
898 if (char* const uuidstr
= jackbridge_client_get_uuid(fJackClient
))
902 if (jackbridge_uuid_parse(uuidstr
, &uuid
))
904 jackbridge_set_property(fJackClient
, uuid
,
905 URI_MAIN_CLIENT_NAME
,
909 jackbridge_set_property(fJackClient
, uuid
,
914 if (fPreRenamePluginIcon
.isNotEmpty())
915 jackbridge_set_property(fJackClient
, uuid
,
917 fPreRenamePluginIcon
,
921 jackbridge_free(uuidstr
);
926 fPreRenameConnections
.clear();
927 fPreRenamePluginId
.clear();
928 fPreRenamePluginIcon
.clear();
932 void deactivate(const bool willClose
) noexcept override
934 carla_debug("CarlaEngineJackClient::deactivate(%s)", bool2str(willClose
));
936 if (getProcessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
938 if (fJackClient
!= nullptr && isActive())
941 jackbridge_deactivate(fJackClient
);
946 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
949 fCVSourcePorts
.resetGraphAndPlugin();
950 fReservedPluginPtr
= nullptr;
954 CarlaEngineClient::deactivate(willClose
);
957 bool isOk() const noexcept override
960 return (fJackClient
!= nullptr);
962 return CarlaEngineClient::isOk();
965 CarlaEnginePort
* addPort(const EnginePortType portType
, const char* const name
, const bool isInput
, const uint32_t indexOffset
) override
967 carla_debug("CarlaEngineJackClient::addPort(%i:%s, \"%s\", %s)", portType
, EnginePortType2Str(portType
), name
, bool2str(isInput
));
969 jack_port_t
* jackPort
= nullptr;
970 const char* realName
= name
;
972 // Create JACK port first, if needed
975 CARLA_SAFE_ASSERT_RETURN(fJackClient
!= nullptr, nullptr);
977 realName
= pData
->getUniquePortName(name
);
981 case kEnginePortTypeNull
:
983 case kEnginePortTypeAudio
:
984 jackPort
= jackbridge_port_register(fJackClient
,
986 JACK_DEFAULT_AUDIO_TYPE
,
987 isInput
? JackPortIsInput
: JackPortIsOutput
,
990 case kEnginePortTypeCV
:
991 jackPort
= jackbridge_port_register(fJackClient
,
993 JACK_DEFAULT_AUDIO_TYPE
,
994 static_cast<uint64_t>(JackPortIsControlVoltage
|
995 (isInput
? JackPortIsInput
996 : JackPortIsOutput
)),
999 case kEnginePortTypeEvent
:
1000 jackPort
= jackbridge_port_register(fJackClient
,
1002 JACK_DEFAULT_MIDI_TYPE
,
1003 isInput
? JackPortIsInput
: JackPortIsOutput
,
1008 CARLA_SAFE_ASSERT_RETURN(jackPort
!= nullptr, nullptr);
1011 // Create Engine port
1014 case kEnginePortTypeNull
:
1016 case kEnginePortTypeAudio
: {
1017 pData
->addAudioPortName(isInput
, realName
);
1018 if (realName
!= name
) delete[] realName
;
1019 CarlaEngineJackAudioPort
* const enginePort(new CarlaEngineJackAudioPort(*this,
1024 fThreadSafeMetadataMutex
,
1026 fAudioPorts
.append(enginePort
);
1029 case kEnginePortTypeCV
: {
1030 pData
->addCVPortName(isInput
, realName
);
1031 if (realName
!= name
) delete[] realName
;
1032 CarlaEngineJackCVPort
* const enginePort(new CarlaEngineJackCVPort(*this,
1037 fThreadSafeMetadataMutex
,
1039 fCVPorts
.append(enginePort
);
1042 case kEnginePortTypeEvent
: {
1043 pData
->addEventPortName(isInput
, realName
);
1044 if (realName
!= name
) delete[] realName
;
1045 CarlaEngineJackEventPort
* const enginePort(new CarlaEngineJackEventPort(*this,
1050 fThreadSafeMetadataMutex
,
1052 fEventPorts
.append(enginePort
);
1057 carla_stderr("CarlaEngineJackClient::addPort(%i, \"%s\", %s) - invalid type", portType
, name
, bool2str(isInput
));
1061 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1062 CarlaEngineCVSourcePorts
* createCVSourcePorts() override
1064 fCVSourcePorts
.setGraphAndPlugin(getPatchbayGraphOrNull(), getPlugin());
1065 return &fCVSourcePorts
;
1068 CarlaEngineJackCVSourcePorts
& getCVSourcePorts() noexcept
1070 return fCVSourcePorts
;
1074 void invalidate() noexcept
1076 for (LinkedList
<CarlaEngineJackAudioPort
*>::Itenerator it
= fAudioPorts
.begin2(); it
.valid(); it
.next())
1078 CarlaEngineJackAudioPort
* const port(it
.getValue(nullptr));
1079 CARLA_SAFE_ASSERT_CONTINUE(port
!= nullptr);
1084 for (LinkedList
<CarlaEngineJackCVPort
*>::Itenerator it
= fCVPorts
.begin2(); it
.valid(); it
.next())
1086 CarlaEngineJackCVPort
* const port(it
.getValue(nullptr));
1087 CARLA_SAFE_ASSERT_CONTINUE(port
!= nullptr);
1092 for (LinkedList
<CarlaEngineJackEventPort
*>::Itenerator it
= fEventPorts
.begin2(); it
.valid(); it
.next())
1094 CarlaEngineJackEventPort
* const port(it
.getValue(nullptr));
1095 CARLA_SAFE_ASSERT_CONTINUE(port
!= nullptr);
1100 fJackClient
= nullptr;
1101 CarlaEngineClient::deactivate(true);
1104 const char* getJackClientName() const noexcept
1106 CARLA_SAFE_ASSERT_RETURN(fJackClient
!= nullptr, nullptr);
1109 return jackbridge_get_client_name(fJackClient
);
1110 } CARLA_SAFE_EXCEPTION_RETURN("jack_get_client_name", nullptr);
1113 void jackAudioPortDeleted(CarlaEngineJackAudioPort
* const port
) noexcept override
1115 fAudioPorts
.removeAll(port
);
1118 void jackCVPortDeleted(CarlaEngineJackCVPort
* const port
) noexcept override
1120 fCVPorts
.removeAll(port
);
1123 void jackEventPortDeleted(CarlaEngineJackEventPort
* const port
) noexcept override
1125 fEventPorts
.removeAll(port
);
1128 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1129 bool renameInSingleClient(const CarlaString
& newClientName
)
1131 const CarlaString
clientNamePrefix(newClientName
+ ":");
1133 return _renamePorts(fAudioPorts
, clientNamePrefix
) &&
1134 _renamePorts(fCVPorts
, clientNamePrefix
) &&
1135 _renamePorts(fEventPorts
, clientNamePrefix
);
1138 void closeForRename(jack_client_t
* const newClient
, const CarlaString
& newClientName
) noexcept
1140 if (fJackClient
!= nullptr)
1145 const CarlaString
clientNamePrefix(newClientName
+ ":");
1147 // store current client connections
1148 const CarlaMutexLocker
cml(fPreRenameMutex
);
1150 fPreRenameConnections
.clear();
1151 fPreRenamePluginId
.clear();
1152 fPreRenamePluginIcon
.clear();
1154 _savePortsConnections(fAudioPorts
, clientNamePrefix
);
1155 _savePortsConnections(fCVPorts
, clientNamePrefix
);
1156 _savePortsConnections(fEventPorts
, clientNamePrefix
);
1161 jackbridge_deactivate(fJackClient
);
1166 jackbridge_client_close(fJackClient
);
1172 fAudioPorts
.clear();
1174 fEventPorts
.clear();
1175 pData
->clearPorts();
1177 fJackClient
= newClient
;
1180 void reservePluginPtr(CarlaPluginPtr
* const pluginPtr
)
1182 fReservedPluginPtr
= pluginPtr
;
1185 void setNewPluginId(const uint id
) const
1187 CARLA_SAFE_ASSERT_RETURN(fJackClient
!= nullptr,);
1189 // NOTE: no fThreadSafeMetadataMutex lock here, assumed done from caller
1191 if (char* const uuidstr
= jackbridge_client_get_uuid(fJackClient
))
1195 if (jackbridge_uuid_parse(uuidstr
, &uuid
))
1198 std::snprintf(buf
, 31, "%u", id
);
1200 jackbridge_set_property(fJackClient
, uuid
,
1206 jackbridge_free(uuidstr
);
1212 jack_client_t
* fJackClient
;
1213 const bool fUseClient
;
1215 LinkedList
<CarlaEngineJackAudioPort
*> fAudioPorts
;
1216 LinkedList
<CarlaEngineJackCVPort
*> fCVPorts
;
1217 LinkedList
<CarlaEngineJackEventPort
*> fEventPorts
;
1219 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1220 CarlaEngineJackCVSourcePorts fCVSourcePorts
;
1222 CarlaMutex fPreRenameMutex
;
1223 CarlaStringList fPreRenameConnections
;
1224 CarlaString fPreRenamePluginId
;
1225 CarlaString fPreRenamePluginIcon
;
1227 CarlaScopedPointer
<CarlaPluginPtr
> fReservedPluginPtr
;
1229 template<typename T
>
1230 bool _renamePorts(const LinkedList
<T
*>& t
, const CarlaString
& clientNamePrefix
)
1232 for (typename LinkedList
<T
*>::Itenerator it
= t
.begin2(); it
.valid(); it
.next())
1234 T
* const port(it
.getValue(nullptr));
1235 CARLA_SAFE_ASSERT_CONTINUE(port
!= nullptr);
1236 CARLA_SAFE_ASSERT_CONTINUE(port
->fJackPort
!= nullptr);
1238 const char* shortPortName(jackbridge_port_short_name(port
->fJackPort
));
1239 CARLA_SAFE_ASSERT_CONTINUE(shortPortName
!= nullptr && shortPortName
[0] != '\0');
1241 const char* const oldClientNameSep(std::strstr(shortPortName
, ":"));
1242 CARLA_SAFE_ASSERT_CONTINUE(oldClientNameSep
!= nullptr && oldClientNameSep
[0] != '\0' && oldClientNameSep
[1] != '\0');
1244 shortPortName
+= oldClientNameSep
-shortPortName
+ 1;
1246 const CarlaString
newPortName(clientNamePrefix
+ shortPortName
);
1248 if (! jackbridge_port_rename(fJackClient
, port
->fJackPort
, newPortName
))
1255 template<typename T
>
1256 void _savePortsConnections(const LinkedList
<T
*>& t
, const CarlaString
& clientNamePrefix
)
1258 for (typename LinkedList
<T
*>::Itenerator it
= t
.begin2(); it
.valid(); it
.next())
1260 T
* const port(it
.getValue(nullptr));
1261 CARLA_SAFE_ASSERT_CONTINUE(port
!= nullptr);
1262 CARLA_SAFE_ASSERT_CONTINUE(port
->fJackPort
!= nullptr);
1264 const char* const shortPortName(jackbridge_port_short_name(port
->fJackPort
));
1265 CARLA_SAFE_ASSERT_CONTINUE(shortPortName
!= nullptr && shortPortName
[0] != '\0');
1267 const CarlaString
portName(clientNamePrefix
+ shortPortName
);
1269 if (const char** const connections
= jackbridge_port_get_all_connections(fJackClient
, port
->fJackPort
))
1271 for (int i
=0; connections
[i
] != nullptr; ++i
)
1275 fPreRenameConnections
.append(connections
[i
]);
1276 fPreRenameConnections
.append(portName
);
1280 fPreRenameConnections
.append(portName
);
1281 fPreRenameConnections
.append(connections
[i
]);
1285 jackbridge_free(connections
);
1290 void _saveProperties()
1292 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
1294 if (char* const uuidstr
= jackbridge_client_get_uuid(fJackClient
))
1298 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
1299 jackbridge_free(uuidstr
);
1301 CARLA_CUSTOM_SAFE_ASSERT_ONCE_RETURN("JACK meta-data support unavailable", parsed
,);
1303 char* value
= nullptr;
1304 char* type
= nullptr;
1306 CARLA_SAFE_ASSERT_RETURN(jackbridge_get_property(uuid
,
1310 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr,);
1311 CARLA_SAFE_ASSERT_RETURN(std::strcmp(type
, URI_TYPE_INTEGER
) == 0,);
1312 fPreRenamePluginId
= value
;
1314 jackbridge_free(value
);
1315 jackbridge_free(type
);
1316 value
= type
= nullptr;
1318 if (jackbridge_get_property(uuid
, URI_PLUGIN_ICON
, &value
, &type
))
1320 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr,);
1321 CARLA_SAFE_ASSERT_RETURN(std::strcmp(type
, URI_TYPE_STRING
) == 0,);
1322 fPreRenamePluginIcon
= value
;
1324 jackbridge_free(value
);
1325 jackbridge_free(type
);
1329 #endif // BUILD_BRIDGE_ALTERNATIVE_ARCH
1331 CarlaRecursiveMutex
& fThreadSafeMetadataMutex
;
1332 const CarlaString
& fMainClientName
;
1334 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient
)
1337 // -----------------------------------------------------------------------
1340 class CarlaEngineJack
: public CarlaEngine
1341 #ifndef BUILD_BRIDGE
1342 , private CarlaThread
1348 #ifndef BUILD_BRIDGE
1349 CarlaThread("CarlaEngineJackCallbacks"),
1352 fExternalPatchbayHost(true),
1353 fExternalPatchbayOsc(true),
1356 fThreadSafeMetadataMutex(),
1360 fClientNamePrefix(),
1361 fTimebaseMaster(false),
1362 fTimebaseRolling(false),
1367 fPatchbayProcThreadProtectionMutex(),
1369 fLastPatchbaySetGroupPos(),
1371 fPostPonedEventsMutex(),
1372 fIsInternalClient(false)
1375 carla_debug("CarlaEngineJack::CarlaEngineJack()");
1378 pData
->options
.processMode
= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
;
1380 carla_zeroPointers(fRackPorts
, kRackPortCount
);
1384 ~CarlaEngineJack() noexcept override
1386 carla_debug("CarlaEngineJack::~CarlaEngineJack()");
1387 CARLA_SAFE_ASSERT(fClient
== nullptr);
1389 #ifndef BUILD_BRIDGE
1390 fUsedGroups
.clear();
1392 fUsedConnections
.clear();
1393 CARLA_SAFE_ASSERT(fPostPonedEvents
.count() == 0);
1397 // -------------------------------------------------------------------
1400 uint
getMaxClientNameSize() const noexcept override
1402 #ifndef BUILD_BRIDGE
1403 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
||
1404 pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
1408 return static_cast<uint
>(jackbridge_client_name_size()-1);
1409 } CARLA_SAFE_EXCEPTION_RETURN("jack_client_name_size", 32);
1412 return CarlaEngine::getMaxClientNameSize();
1415 uint
getMaxPortNameSize() const noexcept override
1417 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
|| pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
1420 return static_cast<uint
>(jackbridge_port_name_size()-1);
1421 } CARLA_SAFE_EXCEPTION_RETURN("jack_port_name_size", 255);
1424 return CarlaEngine::getMaxPortNameSize();
1427 // -------------------------------------------------------------------
1428 // Virtual, per-engine type calls
1430 bool init(const char* const clientName
) override
1432 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr || (clientName
!= nullptr && clientName
[0] != '\0'), false);
1433 carla_debug("CarlaEngineJack::init(\"%s\")", clientName
);
1435 if (!jackbridge_is_ok())
1437 setLastError("JACK is not available or installed");
1442 fExternalPatchbayHost
= true;
1443 fExternalPatchbayOsc
= true;
1445 CarlaString truncatedClientName
;
1447 if (fClient
== nullptr && clientName
!= nullptr)
1449 truncatedClientName
= clientName
;
1450 truncatedClientName
.truncate(getMaxClientNameSize());
1456 if (! pData
->init(truncatedClientName
))
1459 setLastError("Failed to init internal data");
1463 if (pData
->bufferSize
== 0 || carla_isEqual(pData
->sampleRate
, 0.0))
1465 // open temp client to get initial buffer-size and sample-rate values
1466 if (jack_client_t
* const tmpClient
= jackbridge_client_open(truncatedClientName
, JackNoStartServer
, nullptr))
1468 pData
->bufferSize
= jackbridge_get_buffer_size(tmpClient
);
1469 pData
->sampleRate
= jackbridge_get_sample_rate(tmpClient
);
1471 jackbridge_client_close(tmpClient
);
1476 setLastError("Failed to init temporary jack client");
1483 #else // BUILD_BRIDGE
1484 if (fClient
== nullptr && clientName
!= nullptr)
1485 fClient
= jackbridge_client_open(truncatedClientName
, JackNoStartServer
, nullptr);
1487 if (fClient
== nullptr)
1489 setLastError("Failed to create new JACK client");
1493 const char* const jackClientName
= jackbridge_get_client_name(fClient
);
1495 if (! pData
->init(jackClientName
))
1497 jackbridge_client_close(fClient
);
1499 setLastError("Failed to init internal data");
1503 // if main jack client does not match our requested one, setup client name prefix as needed
1504 if (truncatedClientName
!= jackClientName
)
1506 if (const char* const suffix
= std::strrchr(jackClientName
, '-'))
1508 if (fClientNamePrefix
.isNotEmpty())
1510 fClientNamePrefix
.truncate(fClientNamePrefix
.rfind('.') + 1);
1514 fClientNamePrefix
= truncatedClientName
;
1515 fClientNamePrefix
+= ".";
1518 fClientNamePrefix
+= suffix
+ 1;
1519 fClientNamePrefix
+= "/";
1523 fClientName
= jackClientName
;
1525 const EngineOptions
& opts(pData
->options
);
1527 pData
->bufferSize
= jackbridge_get_buffer_size(fClient
);
1528 pData
->sampleRate
= jackbridge_get_sample_rate(fClient
);
1529 pData
->initTime(opts
.transportExtra
);
1531 jackbridge_set_thread_init_callback(fClient
, carla_jack_thread_init_callback
, nullptr);
1532 jackbridge_set_buffer_size_callback(fClient
, carla_jack_bufsize_callback
, this);
1533 jackbridge_set_sample_rate_callback(fClient
, carla_jack_srate_callback
, this);
1534 jackbridge_set_freewheel_callback(fClient
, carla_jack_freewheel_callback
, this);
1535 // jackbridge_set_latency_callback(fClient, carla_jack_latency_callback, this);
1536 jackbridge_set_process_callback(fClient
, carla_jack_process_callback
, this);
1537 jackbridge_on_shutdown(fClient
, carla_jack_shutdown_callback
, this);
1539 fTimebaseRolling
= false;
1541 if (opts
.transportMode
== ENGINE_TRANSPORT_MODE_JACK
)
1542 fTimebaseMaster
= jackbridge_set_timebase_callback(fClient
, true, carla_jack_timebase_callback
, this);
1544 fTimebaseMaster
= false;
1546 initJackPatchbay(true, false, jackClientName
, pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
);
1548 jackbridge_set_client_registration_callback(fClient
, carla_jack_client_registration_callback
, this);
1549 jackbridge_set_port_registration_callback(fClient
, carla_jack_port_registration_callback
, this);
1550 jackbridge_set_port_connect_callback(fClient
, carla_jack_port_connect_callback
, this);
1551 jackbridge_set_port_rename_callback(fClient
, carla_jack_port_rename_callback
, this);
1552 jackbridge_set_property_change_callback(fClient
, carla_jack_property_change_callback
, this);
1553 jackbridge_set_xrun_callback(fClient
, carla_jack_xrun_callback
, this);
1555 if (opts
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
|| opts
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
1557 fRackPorts
[kRackPortAudioIn1
] = jackbridge_port_register(fClient
, "audio-in1", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
1558 fRackPorts
[kRackPortAudioIn2
] = jackbridge_port_register(fClient
, "audio-in2", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsInput
, 0);
1559 fRackPorts
[kRackPortAudioOut1
] = jackbridge_port_register(fClient
, "audio-out1", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
1560 fRackPorts
[kRackPortAudioOut2
] = jackbridge_port_register(fClient
, "audio-out2", JACK_DEFAULT_AUDIO_TYPE
, JackPortIsOutput
, 0);
1561 fRackPorts
[kRackPortEventIn
] = jackbridge_port_register(fClient
, "events-in", JACK_DEFAULT_MIDI_TYPE
, JackPortIsInput
, 0);
1562 fRackPorts
[kRackPortEventOut
] = jackbridge_port_register(fClient
, "events-out", JACK_DEFAULT_MIDI_TYPE
, JackPortIsOutput
, 0);
1564 if (opts
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
)
1567 pData
->graph
.create(0, 0, 0, 0);
1571 pData
->graph
.create(2, 2, 0, 0);
1572 // pData->graph.setUsingExternalHost(true);
1573 // pData->graph.setUsingExternalOSC(true);
1574 patchbayRefresh(true, false, false);
1580 const CarlaString
& tcp(pData
->osc
.getServerPathTCP());
1581 const CarlaString
& udp(pData
->osc
.getServerPathUDP());
1583 if (tcp
.isNotEmpty() || udp
.isNotEmpty())
1585 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
1587 if (char* const uuidstr
= jackbridge_client_get_uuid(fClient
))
1591 if (jackbridge_uuid_parse(uuidstr
, &uuid
))
1593 if (tcp
.isNotEmpty())
1594 jackbridge_set_property(fClient
, uuid
,
1595 "https://kx.studio/ns/carla/osc-tcp", tcp
, URI_TYPE_STRING
);
1597 if (udp
.isNotEmpty())
1598 jackbridge_set_property(fClient
, uuid
,
1599 "https://kx.studio/ns/carla/osc-udp", udp
, URI_TYPE_STRING
);
1602 jackbridge_free(uuidstr
);
1608 if (jackbridge_activate(fClient
))
1610 if (opts
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
||
1611 opts
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
1613 if (pData
->options
.audioDevice
!= nullptr &&
1614 std::strcmp(pData
->options
.audioDevice
, "Auto-Connect ON") == 0 &&
1615 std::getenv("LADISH_APP_NAME") == nullptr &&
1616 std::getenv("NSM_URL") == nullptr)
1618 char strBuf
[STR_MAX
];
1620 if (jackbridge_port_by_name(fClient
, "system:capture_1") != nullptr)
1622 std::snprintf(strBuf
, STR_MAX
, "%s:audio-in1", jackClientName
);
1623 strBuf
[STR_MAX
-1] = '\0';
1625 jackbridge_connect(fClient
, "system:capture_1", strBuf
);
1627 std::snprintf(strBuf
, STR_MAX
, "%s:audio-in2", jackClientName
);
1628 strBuf
[STR_MAX
-1] = '\0';
1630 if (jackbridge_port_by_name(fClient
, "system:capture_2") != nullptr)
1631 jackbridge_connect(fClient
, "system:capture_2", strBuf
);
1633 jackbridge_connect(fClient
, "system:capture_1", strBuf
);
1636 if (jackbridge_port_by_name(fClient
, "system:playback_1") != nullptr)
1638 std::snprintf(strBuf
, STR_MAX
, "%s:audio-out1", jackClientName
);
1639 strBuf
[STR_MAX
-1] = '\0';
1641 jackbridge_connect(fClient
, strBuf
, "system:playback_1");
1643 std::snprintf(strBuf
, STR_MAX
, "%s:audio-out2", jackClientName
);
1644 strBuf
[STR_MAX
-1] = '\0';
1646 if (jackbridge_port_by_name(fClient
, "system:playback_2") != nullptr)
1647 jackbridge_connect(fClient
, strBuf
, "system:playback_2");
1649 jackbridge_connect(fClient
, strBuf
, "system:playback_1");
1654 if (fIsInternalClient
)
1657 callback(true, true,
1658 ENGINE_CALLBACK_ENGINE_STARTED
, 0,
1661 static_cast<int>(pData
->bufferSize
),
1662 static_cast<float>(pData
->sampleRate
),
1663 getCurrentDriverName());
1667 if (opts
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
||
1668 opts
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
1670 pData
->graph
.destroy();
1674 jackbridge_client_close(fClient
);
1677 setLastError("Failed to activate the JACK client");
1679 #endif // BUILD_BRIDGE
1682 #ifndef BUILD_BRIDGE
1683 bool initInternal(jack_client_t
* const client
)
1686 fIsInternalClient
= true;
1688 return init(nullptr);
1692 bool close() override
1694 carla_debug("CarlaEngineJack::close()");
1699 CarlaEngine::close();
1702 if (fIsInternalClient
)
1705 // deactivate client ASAP
1706 if (fClient
!= nullptr)
1707 jackbridge_deactivate(fClient
);
1709 // clear engine data
1710 CarlaEngine::close();
1713 if (fClient
!= nullptr)
1715 jackbridge_client_close(fClient
);
1719 fClientName
.clear();
1720 fUsedGroups
.clear();
1722 fUsedConnections
.clear();
1723 fPostPonedEvents
.clear();
1725 // clear rack/patchbay stuff
1726 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
||
1727 pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
1729 carla_zeroPointers(fRackPorts
, kRackPortCount
);
1730 pData
->graph
.destroy();
1737 bool hasIdleOnMainThread() const noexcept override
1739 #ifndef BUILD_BRIDGE
1740 return !fIsInternalClient
;
1746 bool isRunning() const noexcept override
1749 return (fClient
!= nullptr || fIsRunning
);
1751 return (fClient
!= nullptr);
1755 bool isOffline() const noexcept override
1760 EngineType
getType() const noexcept override
1762 return kEngineTypeJack
;
1765 const char* getCurrentDriverName() const noexcept override
1770 #ifndef BUILD_BRIDGE
1771 float getDSPLoad() const noexcept override
1773 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, 0.0f
);
1775 return jackbridge_cpu_load(fClient
);
1778 void callback(const bool sendHost
, const bool sendOsc
,
1779 const EngineCallbackOpcode action
, const uint pluginId
,
1780 const int value1
, const int value2
, const int value3
,
1781 const float valuef
, const char* const valueStr
) noexcept override
1783 if (action
== ENGINE_CALLBACK_PROJECT_LOAD_FINISHED
)
1785 if (fTimebaseMaster
)
1787 // project finished loading, need to set bpm here, so we force an update of timebase master
1788 transportRelocate(pData
->timeInfo
.frame
);
1792 CarlaEngine::callback(sendHost
, sendOsc
, action
, pluginId
, value1
, value2
, value3
, valuef
, valueStr
);
1795 void idle() noexcept override
1797 LinkedList
<PostPonedJackEvent
> events
;
1798 const PostPonedJackEvent nullEvent
= {};
1801 const CarlaMutexLocker
cml(fPostPonedEventsMutex
);
1803 if (fPostPonedEvents
.count() > 0)
1804 fPostPonedEvents
.moveTo(events
);
1807 for (LinkedList
<PostPonedJackEvent
>::Itenerator it
= events
.begin2(); it
.valid(); it
.next())
1809 const PostPonedJackEvent
& ev(it
.getValue(nullEvent
));
1810 CARLA_SAFE_ASSERT_CONTINUE(ev
.type
!= PostPonedJackEvent::kTypeNull
);
1814 case PostPonedJackEvent::kTypeNull
:
1816 case PostPonedJackEvent::kTypeClientUnregister
:
1817 handleJackClientUnregistrationCallback(ev
.clientUnregister
.name
);
1819 case PostPonedJackEvent::kTypePortRegister
:
1820 handleJackPortRegistrationCallback(ev
.portRegister
.fullName
,
1821 ev
.portRegister
.shortName
,
1822 ev
.portRegister
.hints
);
1824 case PostPonedJackEvent::kTypePortUnregister
:
1825 handleJackPortUnregistrationCallback(ev
.portUnregister
.fullName
);
1827 case PostPonedJackEvent::kTypePortConnect
:
1828 handleJackPortConnectCallback(ev
.portConnect
.portNameA
,
1829 ev
.portConnect
.portNameB
);
1831 case PostPonedJackEvent::kTypePortDisconnect
:
1832 handleJackPortDisconnectCallback(ev
.portDisconnect
.portNameA
,
1833 ev
.portDisconnect
.portNameB
);
1835 case PostPonedJackEvent::kTypePortRename
:
1836 handleJackPortRenameCallback(ev
.portRename
.oldFullName
,
1837 ev
.portRename
.newFullName
,
1838 ev
.portRename
.newShortName
);
1840 case PostPonedJackEvent::kTypeClientPositionChange
:
1841 handleJackClientPositionChangeCallback(ev
.clientPositionChange
.uuid
);
1848 CarlaEngine::idle();
1852 bool setBufferSizeAndSampleRate(const uint bufferSize
, const double sampleRate
) override
1854 CARLA_SAFE_ASSERT_RETURN(carla_isEqual(pData
->sampleRate
, sampleRate
), false);
1855 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
1858 return jackbridge_set_buffer_size(fClient
, bufferSize
);
1859 } CARLA_SAFE_EXCEPTION_RETURN("setBufferSizeAndSampleRate", false);
1862 EngineTimeInfo
getTimeInfo() const noexcept override
1864 if (pData
->options
.transportMode
!= ENGINE_TRANSPORT_MODE_JACK
)
1865 return CarlaEngine::getTimeInfo();
1866 if (pData
->options
.processMode
!= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
1867 return CarlaEngine::getTimeInfo();
1869 jack_position_t jpos
;
1875 EngineTimeInfo timeInfo
;
1876 const bool playing
= jackbridge_transport_query(fClient
, &jpos
) == JackTransportRolling
;
1878 if (jpos
.unique_1
!= jpos
.unique_2
)
1880 timeInfo
.playing
= false;
1883 timeInfo
.bbt
.valid
= false;
1887 timeInfo
.playing
= playing
;
1888 timeInfo
.frame
= jpos
.frame
;
1889 timeInfo
.usecs
= jpos
.usecs
;
1891 if (jpos
.valid
& JackPositionBBT
)
1893 timeInfo
.bbt
.valid
= true;
1894 timeInfo
.bbt
.bar
= jpos
.bar
;
1895 timeInfo
.bbt
.beat
= jpos
.beat
;
1896 #ifdef JACK_TICK_DOUBLE
1897 if (jpos
.valid
& JackTickDouble
)
1898 timeInfo
.bbt
.tick
= jpos
.tick_double
;
1901 timeInfo
.bbt
.tick
= jpos
.tick
;
1902 timeInfo
.bbt
.barStartTick
= jpos
.bar_start_tick
;
1903 timeInfo
.bbt
.beatsPerBar
= jpos
.beats_per_bar
;
1904 timeInfo
.bbt
.beatType
= jpos
.beat_type
;
1905 timeInfo
.bbt
.ticksPerBeat
= jpos
.ticks_per_beat
;
1906 timeInfo
.bbt
.beatsPerMinute
= jpos
.beats_per_minute
;
1910 timeInfo
.bbt
.valid
= false;
1916 #ifndef BUILD_BRIDGE
1917 void setOption(const EngineOption option
, const int value
, const char* const valueStr
) noexcept override
1919 if (option
== ENGINE_OPTION_TRANSPORT_MODE
&& fClient
!= nullptr)
1921 CARLA_SAFE_ASSERT_INT_RETURN(value
>= ENGINE_TRANSPORT_MODE_DISABLED
&&
1922 value
<= ENGINE_TRANSPORT_MODE_JACK
, value
,);
1924 if (value
== ENGINE_TRANSPORT_MODE_JACK
)
1926 fTimebaseMaster
= jackbridge_set_timebase_callback(fClient
, true, carla_jack_timebase_callback
, this);
1930 // jack transport cannot be disabled in multi-client
1931 callback(true, true,
1932 ENGINE_CALLBACK_TRANSPORT_MODE_CHANGED
, 0,
1933 ENGINE_TRANSPORT_MODE_JACK
,
1935 pData
->options
.transportExtra
);
1936 CARLA_SAFE_ASSERT_RETURN(pData
->options
.processMode
!= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
,);
1938 jackbridge_release_timebase(fClient
);
1939 fTimebaseMaster
= false;
1942 else if (option
== ENGINE_OPTION_CLIENT_NAME_PREFIX
)
1944 fClientNamePrefix
= valueStr
;
1946 if (fClientNamePrefix
.isNotEmpty())
1948 if (! fClientNamePrefix
.contains('.'))
1949 fClientNamePrefix
+= ".0";
1950 if (! fClientNamePrefix
.endsWith('/'))
1951 fClientNamePrefix
+= "/";
1955 CarlaEngine::setOption(option
, value
, valueStr
);
1959 CarlaEngineClient
* addClient(CarlaPluginPtr plugin
) override
1961 jack_client_t
* client
= nullptr;
1963 #ifndef BUILD_BRIDGE
1964 CARLA_CUSTOM_SAFE_ASSERT_RETURN("Not connected to JACK", fClient
!= nullptr, nullptr);
1966 CarlaPluginPtr
* pluginReserve
= nullptr;
1968 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
1972 else if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
1975 #ifndef BUILD_BRIDGE
1976 if (fClientNamePrefix
.isNotEmpty())
1978 client
= jackbridge_client_open(fClientNamePrefix
+ plugin
->getName(), JackNoStartServer
, nullptr);
1983 client
= jackbridge_client_open(plugin
->getName(), JackNoStartServer
, nullptr);
1985 CARLA_CUSTOM_SAFE_ASSERT_RETURN("Failure to open client", client
!= nullptr, nullptr);
1987 jackbridge_set_thread_init_callback(client
, carla_jack_thread_init_callback
, nullptr);
1989 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
1991 if (char* const uuidstr
= jackbridge_client_get_uuid(client
))
1995 if (jackbridge_uuid_parse(uuidstr
, &uuid
))
1998 std::snprintf(strBufId
, 23, "%u", plugin
->getId());
1999 strBufId
[23] = '\0';
2001 #ifndef BUILD_BRIDGE
2002 jackbridge_set_property(client
, uuid
,
2003 URI_MAIN_CLIENT_NAME
,
2007 jackbridge_set_property(client
, uuid
,
2013 if (const char* const pluginIcon
= plugin
->getIconName())
2014 jackbridge_set_property(client
, uuid
,
2020 jackbridge_free(uuidstr
);
2023 #ifndef BUILD_BRIDGE
2024 pluginReserve
= new CarlaPluginPtr(plugin
);
2026 jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback_plugin, pluginReserve);
2027 jackbridge_set_sample_rate_callback(fClient, carla_jack_srate_callback_plugin, pluginReserve);
2029 // jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, pluginReserve);
2030 jackbridge_set_process_callback(client
, carla_jack_process_callback_plugin
, pluginReserve
);
2031 jackbridge_on_shutdown(client
, carla_jack_shutdown_callback_plugin
, pluginReserve
);
2034 pData
->bufferSize
= jackbridge_get_buffer_size(client
);
2035 pData
->sampleRate
= jackbridge_get_sample_rate(client
);
2036 pData
->initTime(nullptr);
2038 jackbridge_set_buffer_size_callback(client
, carla_jack_bufsize_callback
, this);
2039 jackbridge_set_sample_rate_callback(client
, carla_jack_srate_callback
, this);
2040 jackbridge_set_freewheel_callback(client
, carla_jack_freewheel_callback
, this);
2041 // jackbridge_set_latency_callback(client, carla_jack_latency_callback, this);
2042 jackbridge_set_process_callback(client
, carla_jack_process_callback
, this);
2043 jackbridge_on_shutdown(client
, carla_jack_shutdown_callback
, this);
2045 fClientName
= jackbridge_get_client_name(client
);
2049 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
2050 carla_debug("new CarlaEngineJackClient");
2051 CarlaEngineJackClient
* const jclient
= new CarlaEngineJackClient(*this,
2053 fThreadSafeMetadataMutex
,
2054 plugin
, fClientName
, client
);
2055 # ifndef BUILD_BRIDGE
2056 if (pluginReserve
!= nullptr)
2057 jclient
->reservePluginPtr(pluginReserve
);
2062 return new CarlaEngineJackClient(*this, fThreadSafeMetadataMutex
, fClientName
, client
);
2066 #ifndef BUILD_BRIDGE
2067 bool removePlugin(const uint id
) override
2069 if (! CarlaEngine::removePlugin(id
))
2072 if (pData
->options
.processMode
!= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
2075 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
2077 for (uint i
=id
; i
< pData
->curPluginCount
; ++i
)
2079 const CarlaPluginPtr plugin
= pData
->plugins
[i
].plugin
;
2080 CARLA_SAFE_ASSERT_BREAK(plugin
.get() != nullptr);
2082 CarlaEngineJackClient
* const client
= dynamic_cast<CarlaEngineJackClient
*>(plugin
->getEngineClient());
2083 CARLA_SAFE_ASSERT_BREAK(client
!= nullptr);
2085 client
->setNewPluginId(i
);
2091 bool switchPlugins(const uint idA
, const uint idB
) noexcept override
2093 if (! CarlaEngine::switchPlugins(idA
, idB
))
2096 if (pData
->options
.processMode
!= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
2099 CarlaPluginPtr newPluginA
= pData
->plugins
[idA
].plugin
;
2100 CARLA_SAFE_ASSERT_RETURN(newPluginA
.get() != nullptr, true);
2102 CarlaPluginPtr newPluginB
= pData
->plugins
[idB
].plugin
;
2103 CARLA_SAFE_ASSERT_RETURN(newPluginB
.get() != nullptr, true);
2105 CarlaEngineJackClient
* const clientA
= dynamic_cast<CarlaEngineJackClient
*>(newPluginA
->getEngineClient());
2106 CARLA_SAFE_ASSERT_RETURN(clientA
!= nullptr, true);
2108 CarlaEngineJackClient
* const clientB
= dynamic_cast<CarlaEngineJackClient
*>(newPluginB
->getEngineClient());
2109 CARLA_SAFE_ASSERT_RETURN(clientB
!= nullptr, true);
2112 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
2113 clientA
->setNewPluginId(idA
);
2114 clientB
->setNewPluginId(idB
);
2120 bool renamePlugin(const uint id
, const char* const newName
) override
2122 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
||
2123 pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
2125 return CarlaEngine::renamePlugin(id
, newName
);
2128 CARLA_SAFE_ASSERT_RETURN(pData
->plugins
!= nullptr, false);
2129 CARLA_SAFE_ASSERT_RETURN(pData
->curPluginCount
!= 0, false);
2130 CARLA_SAFE_ASSERT_RETURN(id
< pData
->curPluginCount
, false);
2131 CARLA_SAFE_ASSERT_RETURN(newName
!= nullptr && newName
[0] != '\0', false);
2133 CarlaPluginPtr plugin
= pData
->plugins
[id
].plugin
;
2134 CARLA_SAFE_ASSERT_RETURN_ERR(plugin
.get() != nullptr, "Could not find plugin to rename");
2135 CARLA_SAFE_ASSERT_RETURN_ERR(plugin
->getId() == id
, "Invalid engine internal data");
2137 // before we stop the engine thread we might need to get the plugin data
2138 const bool needsReinit
= (pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
);
2139 const CarlaStateSave
* saveStatePtr
= nullptr;
2143 const CarlaStateSave
& saveState(plugin
->getStateSave());
2144 saveStatePtr
= &saveState
;
2147 CarlaString uniqueName
;
2150 const char* const tmpName
= getUniquePluginName(newName
);
2151 uniqueName
= tmpName
;
2153 } CARLA_SAFE_EXCEPTION("JACK renamePlugin getUniquePluginName");
2155 if (uniqueName
.isEmpty())
2157 setLastError("Failed to request new unique plugin name");
2161 const ScopedRunnerStopper
srs(this);
2163 // rename on client client mode, just rename the ports
2164 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
2166 CarlaEngineJackClient
* const client((CarlaEngineJackClient
*)plugin
->getEngineClient());
2168 if (! client
->renameInSingleClient(uniqueName
))
2170 setLastError("Failed to rename some JACK ports, does your JACK version support proper port renaming?");
2174 // rename in multiple client mode
2175 else if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
2177 CarlaEngineJackClient
* const client((CarlaEngineJackClient
*)plugin
->getEngineClient());
2179 // we should not be able to do this, jack really needs to allow client rename
2180 if (jack_client_t
* const jackClient
= jackbridge_client_open(fClientNamePrefix
+ uniqueName
,
2181 JackNoStartServer
, nullptr))
2183 // get new client name
2184 fClientName
= jackbridge_get_client_name(jackClient
);
2186 if (fClientNamePrefix
.isNotEmpty())
2187 uniqueName
= fClientName
.buffer() + fClientNamePrefix
.length();
2189 uniqueName
= fClientName
;
2192 client
->closeForRename(jackClient
, fClientName
);
2195 plugin
->setEnabled(false);
2197 // set new client data
2198 CarlaPluginPtr
* const pluginReserve
= new CarlaPluginPtr(plugin
);
2199 client
->reservePluginPtr(pluginReserve
);
2200 // jackbridge_set_latency_callback(jackClient, carla_jack_latency_callback_plugin, pluginReserve);
2201 jackbridge_set_process_callback(jackClient
, carla_jack_process_callback_plugin
, pluginReserve
);
2202 jackbridge_on_shutdown(jackClient
, carla_jack_shutdown_callback_plugin
, pluginReserve
);
2204 // NOTE: jack1 locks up here
2205 if (jackbridge_get_version_string() != nullptr)
2206 jackbridge_set_thread_init_callback(jackClient
, carla_jack_thread_init_callback
, nullptr);
2208 /* The following code is because of a tricky situation.
2209 We cannot lock or do jack operations during jack callbacks on jack1. jack2 events are asynchronous.
2210 When we close the client jack will trigger unregister-port callbacks, which we handle on a separate thread ASAP.
2211 But before that happens we already registered a new client with the same ports (the "renamed" one),
2212 and at this point the port we receive during that callback is actually the new one from the new client..
2213 JACK2 seems to be reusing ports to save space, which is understandable.
2214 Anyway, this means we have to remove all our port-related data before the new client ports are created.
2215 (we also stop the separate jack-events thread to avoid any race conditions while modying our port data) */
2217 if (fIsInternalClient
)
2220 LinkedList
<PortNameToId
> ports
;
2221 LinkedList
<ConnectionToId
> conns
;
2224 const CarlaMutexLocker
cml1(fUsedGroups
.mutex
);
2226 if (const uint groupId
= fUsedGroups
.getGroupId(plugin
->getName()))
2228 const CarlaMutexLocker
cml2(fUsedPorts
.mutex
);
2230 for (LinkedList
<PortNameToId
>::Itenerator it
= fUsedPorts
.list
.begin2(); it
.valid(); it
.next())
2232 const PortNameToId
& portNameToId(it
.getValue(kPortNameToIdFallback
));
2233 CARLA_SAFE_ASSERT_CONTINUE(portNameToId
.group
!= 0);
2235 if (portNameToId
.group
!= groupId
)
2238 ports
.append(portNameToId
);
2239 fUsedPorts
.list
.remove(it
);
2242 const CarlaMutexLocker
cml3(fUsedConnections
.mutex
);
2244 for (LinkedList
<ConnectionToId
>::Itenerator it
= fUsedConnections
.list
.begin2(); it
.valid(); it
.next())
2246 const ConnectionToId
& connectionToId
= it
.getValue(kConnectionToIdFallback
);
2247 CARLA_SAFE_ASSERT_CONTINUE(connectionToId
.id
!= 0);
2249 if (connectionToId
.groupA
!= groupId
&& connectionToId
.groupB
!= groupId
)
2252 conns
.append(connectionToId
);
2253 fUsedConnections
.list
.remove(it
);
2258 for (LinkedList
<ConnectionToId
>::Itenerator it
= conns
.begin2(); it
.valid(); it
.next())
2260 const ConnectionToId
& connectionToId
= it
.getValue(kConnectionToIdFallback
);
2261 CARLA_SAFE_ASSERT_CONTINUE(connectionToId
.id
!= 0);
2263 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
2264 ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED
,
2266 0, 0, 0, 0.0f
, nullptr);
2269 for (LinkedList
<PortNameToId
>::Itenerator it
= ports
.begin2(); it
.valid(); it
.next())
2271 const PortNameToId
& portNameToId(it
.getValue(kPortNameToIdFallback
));
2272 CARLA_SAFE_ASSERT_CONTINUE(portNameToId
.group
!= 0);
2274 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
2275 ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED
,
2277 static_cast<int>(portNameToId
.port
),
2278 0, 0, 0.0f
, nullptr);
2284 if (fIsInternalClient
)
2289 setLastError("Failed to create new JACK client");
2295 plugin
->setName(uniqueName
);
2299 // reload plugin to recreate its ports
2301 plugin
->loadStateSave(*saveStatePtr
);
2302 plugin
->setEnabled(true);
2305 callback(true, true, ENGINE_CALLBACK_PLUGIN_RENAMED
, id
, 0, 0, 0, 0.0f
, uniqueName
);
2309 // -------------------------------------------------------------------
2312 bool patchbayConnect(const bool external
,
2313 const uint groupA
, const uint portA
, const uint groupB
, const uint portB
) override
2315 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
2317 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2318 return CarlaEngine::patchbayConnect(false, groupA
, portA
, groupB
, portB
);
2320 const CarlaMutexLocker
cml(fUsedPorts
.mutex
);
2322 const char* const fullPortNameA
= fUsedPorts
.getFullPortName(groupA
, portA
);
2323 CARLA_SAFE_ASSERT_RETURN(fullPortNameA
!= nullptr && fullPortNameA
[0] != '\0', false);
2325 const char* const fullPortNameB
= fUsedPorts
.getFullPortName(groupB
, portB
);
2326 CARLA_SAFE_ASSERT_RETURN(fullPortNameB
!= nullptr && fullPortNameB
[0] != '\0', false);
2328 if (! jackbridge_connect(fClient
, fullPortNameA
, fullPortNameB
))
2330 setLastError("JACK operation failed");
2337 bool patchbayDisconnect(const bool external
, const uint connectionId
) override
2339 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
2341 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2342 return CarlaEngine::patchbayDisconnect(false, connectionId
);
2344 ConnectionToId connectionToId
= { 0, 0, 0, 0, 0 };
2347 const CarlaMutexLocker
cml(fUsedConnections
.mutex
);
2349 for (LinkedList
<ConnectionToId
>::Itenerator it
= fUsedConnections
.list
.begin2(); it
.valid(); it
.next())
2351 connectionToId
= it
.getValue(kConnectionToIdFallback
);
2352 CARLA_SAFE_ASSERT_CONTINUE(connectionToId
.id
!= 0);
2354 if (connectionToId
.id
== connectionId
)
2359 if (connectionToId
.id
== 0 || connectionToId
.id
!= connectionId
)
2361 setLastError("Failed to find the requested connection");
2365 const CarlaMutexLocker
cml(fUsedPorts
.mutex
);
2367 const char* const fullPortNameA
= fUsedPorts
.getFullPortName(connectionToId
.groupA
, connectionToId
.portA
);
2368 CARLA_SAFE_ASSERT_RETURN(fullPortNameA
!= nullptr && fullPortNameA
[0] != '\0', false);
2370 const char* const fullPortNameB
= fUsedPorts
.getFullPortName(connectionToId
.groupB
, connectionToId
.portB
);
2371 CARLA_SAFE_ASSERT_RETURN(fullPortNameB
!= nullptr && fullPortNameB
[0] != '\0', false);
2373 if (! jackbridge_disconnect(fClient
, fullPortNameA
, fullPortNameB
))
2375 setLastError("JACK operation failed");
2382 bool patchbaySetGroupPos(const bool sendHost
, const bool sendOSC
, const bool external
,
2383 const uint groupId
, const int x1
, const int y1
, const int x2
, const int y2
) override
2385 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
2386 CARLA_SAFE_ASSERT_RETURN(! pData
->loadingProject
, false);
2387 carla_debug("CarlaEngineJack::patchbaySetGroupPos(%u, %i, %i, %i, %i)", groupId
, x1
, y1
, x2
, y2
);
2389 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2390 return CarlaEngine::patchbaySetGroupPos(sendHost
, sendOSC
, false, groupId
, x1
, y1
, x2
, y2
);
2392 const char* groupName
;
2395 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
2397 groupName
= fUsedGroups
.getGroupName(groupId
);
2398 CARLA_SAFE_ASSERT_RETURN(groupName
!= nullptr && groupName
[0] != '\0', false);
2404 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
2408 char* const uuidstr
= jackbridge_get_uuid_for_client_name(fClient
, groupName
);
2409 CARLA_SAFE_ASSERT_RETURN(uuidstr
!= nullptr && uuidstr
[0] != '\0', false);
2411 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
2412 jackbridge_free(uuidstr
);
2414 /* if parsing fails, meta-data is not available..
2415 this could be because JACK version is old, or perhaps this is an internal client */
2420 fLastPatchbaySetGroupPos
.set(x1
, y1
, x2
, y2
);
2422 char valueStr
[STR_MAX
];
2423 std::snprintf(valueStr
, STR_MAX
-1, "%i:%i:%i:%i", x1
, y1
, x2
, y2
);
2424 valueStr
[STR_MAX
-1] = '\0';
2426 ok
= jackbridge_set_property(fClient
, uuid
, URI_POSITION
, valueStr
, URI_TYPE_STRING
);
2429 callback(sendHost
, sendOSC
,
2430 ENGINE_CALLBACK_PATCHBAY_CLIENT_POSITION_CHANGED
,
2431 groupId
, x1
, y1
, x2
, static_cast<float>(y2
),
2437 bool patchbayRefresh(const bool sendHost
, const bool sendOSC
, const bool external
) override
2439 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
2440 carla_debug("patchbayRefresh(%s, %s, %s)", bool2str(sendHost
), bool2str(sendOSC
), bool2str(external
));
2442 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
2446 fExternalPatchbayHost
= external
;
2447 pData
->graph
.setUsingExternalHost(external
);
2451 fExternalPatchbayOsc
= external
;
2452 pData
->graph
.setUsingExternalOSC(external
);
2456 CarlaEngine::patchbayRefresh(sendHost
, sendOSC
, false);
2459 initJackPatchbay(sendHost
, sendOSC
, jackbridge_get_client_name(fClient
),
2460 pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& !external
);
2464 // -------------------------------------------------------------------
2467 void transportPlay() noexcept override
2469 if (pData
->options
.transportMode
!= ENGINE_TRANSPORT_MODE_JACK
)
2470 return CarlaEngine::transportPlay();
2472 if (fClient
!= nullptr)
2474 if (! pData
->timeInfo
.bbt
.valid
)
2476 // old timebase master no longer active, make ourselves master again
2477 pData
->time
.setNeedsReset();
2478 fTimebaseMaster
= jackbridge_set_timebase_callback(fClient
, true, carla_jack_timebase_callback
, this);
2482 jackbridge_transport_start(fClient
);
2487 void transportPause() noexcept override
2489 if (pData
->options
.transportMode
!= ENGINE_TRANSPORT_MODE_JACK
)
2490 return CarlaEngine::transportPause();
2492 if (fClient
!= nullptr)
2495 jackbridge_transport_stop(fClient
);
2500 void transportBPM(const double bpm
) noexcept override
2502 if (pData
->options
.transportMode
!= ENGINE_TRANSPORT_MODE_JACK
|| fTimebaseMaster
)
2503 return CarlaEngine::transportBPM(bpm
);
2505 if (fClient
== nullptr)
2508 jack_position_t jpos
;
2513 jackbridge_transport_query(fClient
, &jpos
);
2515 if (jpos
.unique_1
== jpos
.unique_2
&& (jpos
.valid
& JackPositionBBT
) != 0)
2517 carla_stdout("NOTE: Changing BPM without being JACK timebase master");
2518 jpos
.beats_per_minute
= bpm
;
2521 jackbridge_transport_reposition(fClient
, &jpos
);
2526 void transportRelocate(const uint64_t frame
) noexcept override
2528 if (pData
->options
.transportMode
!= ENGINE_TRANSPORT_MODE_JACK
)
2529 return CarlaEngine::transportRelocate(frame
);
2531 if (fClient
!= nullptr)
2534 jackbridge_transport_locate(fClient
, static_cast<jack_nframes_t
>(frame
));
2539 // -------------------------------------------------------------------
2542 const char* const* getPatchbayConnections(const bool external
) const override
2544 CARLA_CUSTOM_SAFE_ASSERT_RETURN("Not connected to JACK, will not save patchbay connections",
2545 fClient
!= nullptr, nullptr);
2546 carla_debug("CarlaEngineJack::getPatchbayConnections(%s)", bool2str(external
));
2548 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2549 return CarlaEngine::getPatchbayConnections(external
);
2551 CarlaStringList connList
;
2553 if (const char** const ports
= jackbridge_get_ports(fClient
, nullptr, nullptr, JackPortIsOutput
))
2555 for (int i
=0; ports
[i
] != nullptr; ++i
)
2557 const jack_port_t
* const jackPort(jackbridge_port_by_name(fClient
, ports
[i
]));
2558 const char* const fullPortName(ports
[i
]);
2560 CARLA_SAFE_ASSERT_CONTINUE(jackPort
!= nullptr);
2562 if (const char** const connections
= jackbridge_port_get_all_connections(fClient
, jackPort
))
2564 for (int j
=0; connections
[j
] != nullptr; ++j
)
2566 connList
.append(fullPortName
);
2567 connList
.append(connections
[j
]);
2570 jackbridge_free(connections
);
2574 jackbridge_free(ports
);
2577 if (connList
.count() == 0)
2580 fRetConns
= connList
.toCharStringListPtr();
2585 const PatchbayPosition
* getPatchbayPositions(const bool external
, uint
& count
) const override
2587 CARLA_CUSTOM_SAFE_ASSERT_RETURN("Not connected to JACK, will not save patchbay positions",
2588 fClient
!= nullptr, nullptr);
2589 carla_debug("CarlaEngineJack::getPatchbayPositions(%s)", bool2str(external
));
2591 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2592 return CarlaEngine::getPatchbayPositions(external
, count
);
2594 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
2595 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
2597 if (const std::size_t maxCount
= fUsedGroups
.list
.count())
2599 PatchbayPosition
* ret
;
2602 ret
= new CarlaEngine::PatchbayPosition
[maxCount
];
2603 } CARLA_SAFE_EXCEPTION_RETURN("new CarlaEngine::PatchbayPosition", nullptr);
2607 GroupNameToId groupNameToId
;
2609 for (LinkedList
<GroupNameToId
>::Itenerator it
= fUsedGroups
.list
.begin2(); it
.valid(); it
.next())
2611 groupNameToId
= it
.getValue(kGroupNameToIdFallback
);
2612 CARLA_SAFE_ASSERT_CONTINUE(groupNameToId
.group
!= 0);
2616 char* const uuidstr
= jackbridge_get_uuid_for_client_name(fClient
, groupNameToId
.name
);
2618 if (uuidstr
== nullptr || uuidstr
[0] == '\0')
2621 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
2622 jackbridge_free(uuidstr
);
2624 /* if parsing fails, meta-data is not available..
2625 this could be because JACK version is old, or perhaps this is an internal client */
2630 char* value
= nullptr;
2631 char* type
= nullptr;
2633 if (jackbridge_get_property(uuid
, URI_POSITION
, &value
, &type
)
2636 && std::strcmp(type
, URI_TYPE_STRING
) == 0)
2638 CarlaEngine::PatchbayPosition
& ppos(ret
[count
++]);
2640 ppos
.name
= carla_strdup_safe(groupNameToId
.name
);
2641 ppos
.dealloc
= true;
2644 if (char* sep1
= std::strstr(value
, ":"))
2647 ppos
.x1
= std::atoi(value
);
2649 if (char* sep2
= std::strstr(sep1
, ":"))
2652 ppos
.y1
= std::atoi(sep1
);
2654 if (char* sep3
= std::strstr(sep2
, ":"))
2657 ppos
.x2
= std::atoi(sep2
);
2658 ppos
.y2
= std::atoi(sep3
);
2663 jackbridge_free(value
);
2664 jackbridge_free(type
);
2665 value
= type
= nullptr;
2667 const bool clientBelongsToUs
= (jackbridge_get_property(uuid
, URI_MAIN_CLIENT_NAME
, &value
, &type
)
2670 && std::strcmp(type
, URI_TYPE_STRING
) == 0
2671 && fClientName
== value
);
2672 jackbridge_free(value
);
2673 jackbridge_free(type
);
2674 value
= type
= nullptr;
2676 if (! clientBelongsToUs
)
2679 if (jackbridge_get_property(uuid
, URI_PLUGIN_ID
, &value
, &type
)
2682 && std::strcmp(type
, URI_TYPE_INTEGER
) == 0)
2684 ppos
.pluginId
= std::atoi(value
);
2687 jackbridge_free(value
);
2688 jackbridge_free(type
);
2698 void restorePatchbayConnection(const bool external
,
2699 const char* const connSource
, const char* const connTarget
) override
2701 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr,);
2702 CARLA_SAFE_ASSERT_RETURN(connSource
!= nullptr && connSource
[0] != '\0',);
2703 CARLA_SAFE_ASSERT_RETURN(connTarget
!= nullptr && connTarget
[0] != '\0',);
2704 carla_debug("CarlaEngineJack::restorePatchbayConnection(%s, \"%s\", \"%s\")",
2705 bool2str(external
), connSource
, connTarget
);
2707 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2708 return CarlaEngine::restorePatchbayConnection(external
, connSource
, connTarget
);
2710 if (const jack_port_t
* const port
= jackbridge_port_by_name(fClient
, connSource
))
2712 if (jackbridge_port_by_name(fClient
, connTarget
) == nullptr)
2715 if (! jackbridge_port_connected_to(port
, connTarget
))
2716 jackbridge_connect(fClient
, connSource
, connTarget
);
2720 bool restorePatchbayGroupPosition(const bool external
, PatchbayPosition
& ppos
) override
2722 CARLA_SAFE_ASSERT_RETURN(fClient
!= nullptr, false);
2723 carla_debug("CarlaEngineJack::restorePatchbayGroupPosition(%s, {%i, %i, %i, %i, %i, \"%s\"})",
2724 bool2str(external
), ppos
.pluginId
, ppos
.x1
, ppos
.y1
, ppos
.x2
, ppos
.y2
, ppos
.name
);
2726 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
&& ! external
)
2727 return CarlaEngine::restorePatchbayGroupPosition(external
, ppos
);
2730 const char* const orig_name
= ppos
.name
;
2732 /* NOTE: When loading a project, it might take a bit to receive plugins' jack client registration callbacks.
2733 * We try to wait a little for it, but not too much.
2735 if (ppos
.pluginId
>= 0)
2737 // strip client name prefix if already in place
2738 if (const char* const rname2
= std::strstr(ppos
.name
, "."))
2739 if (const char* const rname3
= std::strstr(rname2
+ 1, "/"))
2740 ppos
.name
= rname3
+ 1;
2742 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
2744 if (fClientNamePrefix
.isNotEmpty())
2746 char* nname
= (char*)std::malloc(fClientNamePrefix
.length() + std::strlen(ppos
.name
) + 1);
2747 std::strcpy(nname
, fClientNamePrefix
.buffer());
2748 std::strcat(nname
, ppos
.name
);
2751 ppos
.dealloc
= true;
2754 for (int i
=20; --i
>=0;)
2757 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
2759 if (fUsedGroups
.list
.count() == 0)
2762 groupId
= fUsedGroups
.getGroupId(ppos
.name
);
2769 callback(true, true, ENGINE_CALLBACK_IDLE
, 0, 0, 0, 0, 0.0f
, nullptr);
2775 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
2777 if (fUsedGroups
.list
.count() != 0)
2778 groupId
= fUsedGroups
.getGroupId(ppos
.name
);
2783 if (ppos
.pluginId
< 0 || pData
->options
.processMode
== ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
2784 carla_stdout("Previously saved client '%s' not found", ppos
.name
);
2790 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
2794 char* const uuidstr
= jackbridge_get_uuid_for_client_name(fClient
, ppos
.name
);
2795 CARLA_SAFE_ASSERT_BREAK(uuidstr
!= nullptr && uuidstr
[0] != '\0');
2797 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
2798 jackbridge_free(uuidstr
);
2799 CARLA_CUSTOM_SAFE_ASSERT_ONCE_BREAK("JACK meta-data support unavailable", parsed
);
2802 char valueStr
[STR_MAX
];
2803 std::snprintf(valueStr
, STR_MAX
-1, "%i:%i:%i:%i", ppos
.x1
, ppos
.y1
, ppos
.x2
, ppos
.y2
);
2804 valueStr
[STR_MAX
-1] = '\0';
2806 jackbridge_set_property(fClient
, uuid
, URI_POSITION
, valueStr
, URI_TYPE_STRING
);
2810 callback(true, true,
2811 ENGINE_CALLBACK_PATCHBAY_CLIENT_POSITION_CHANGED
,
2812 groupId
, ppos
.x1
, ppos
.y1
, ppos
.x2
, static_cast<float>(ppos
.y2
),
2816 return ppos
.name
!= orig_name
;
2820 // -------------------------------------------------------------------
2823 void handleJackBufferSizeCallback(const uint32_t newBufferSize
)
2825 if (pData
->bufferSize
== newBufferSize
)
2828 #ifndef BUILD_BRIDGE
2829 const CarlaMutexLocker
cml(fPatchbayProcThreadProtectionMutex
);
2832 pData
->bufferSize
= newBufferSize
;
2833 bufferSizeChanged(newBufferSize
);
2836 void handleJackSampleRateCallback(const double newSampleRate
)
2838 if (carla_isEqual(pData
->sampleRate
, newSampleRate
))
2841 #ifndef BUILD_BRIDGE
2842 const CarlaMutexLocker
cml(fPatchbayProcThreadProtectionMutex
);
2845 pData
->sampleRate
= newSampleRate
;
2846 sampleRateChanged(newSampleRate
);
2849 void handleJackFreewheelCallback(const bool isFreewheel
)
2851 if (fFreewheel
== isFreewheel
)
2854 #ifndef BUILD_BRIDGE
2855 const CarlaMutexLocker
cml(fPatchbayProcThreadProtectionMutex
);
2858 fFreewheel
= isFreewheel
;
2859 offlineModeChanged(isFreewheel
);
2862 void handleJackProcessCallback(const uint32_t nframes
)
2864 const PendingRtEventsRunner
prt(this, nframes
);
2866 CARLA_SAFE_ASSERT_INT2_RETURN(nframes
== pData
->bufferSize
, nframes
, pData
->bufferSize
,);
2869 CarlaPluginPtr plugin
= pData
->plugins
[0].plugin
;
2871 if (plugin
.get() != nullptr && plugin
->isEnabled() && plugin
->tryLock(fFreewheel
))
2873 plugin
->initBuffers();
2874 processPlugin(plugin
, nframes
);
2878 if (pData
->options
.transportMode
== ENGINE_TRANSPORT_MODE_JACK
&& !fTimebaseMaster
)
2880 jack_position_t jpos
;
2886 EngineTimeInfo timeInfo
;
2887 const bool playing
= jackbridge_transport_query(fClient
, &jpos
) == JackTransportRolling
;
2889 if (jpos
.unique_1
!= jpos
.unique_2
)
2891 timeInfo
.playing
= false;
2894 timeInfo
.bbt
.valid
= false;
2898 timeInfo
.playing
= playing
;
2899 timeInfo
.frame
= jpos
.frame
;
2900 timeInfo
.usecs
= jpos
.usecs
;
2902 if (jpos
.valid
& JackPositionBBT
)
2904 timeInfo
.bbt
.valid
= true;
2905 timeInfo
.bbt
.bar
= jpos
.bar
;
2906 timeInfo
.bbt
.beat
= jpos
.beat
;
2907 #ifdef JACK_TICK_DOUBLE
2908 if (jpos
.valid
& JackTickDouble
)
2909 timeInfo
.bbt
.tick
= jpos
.tick_double
;
2912 timeInfo
.bbt
.tick
= jpos
.tick
;
2913 timeInfo
.bbt
.barStartTick
= jpos
.bar_start_tick
;
2914 timeInfo
.bbt
.beatsPerBar
= jpos
.beats_per_bar
;
2915 timeInfo
.bbt
.beatType
= jpos
.beat_type
;
2916 timeInfo
.bbt
.ticksPerBeat
= jpos
.ticks_per_beat
;
2917 timeInfo
.bbt
.beatsPerMinute
= jpos
.beats_per_minute
;
2921 timeInfo
.bbt
.valid
= false;
2925 pData
->timeInfo
= timeInfo
;
2928 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
)
2930 if (pData
->aboutToClose
)
2932 if (float* const audioOut1
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut1
], nframes
))
2933 carla_zeroFloats(audioOut1
, nframes
);
2935 if (float* const audioOut2
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut2
], nframes
))
2936 carla_zeroFloats(audioOut2
, nframes
);
2938 else if (pData
->curPluginCount
== 0)
2940 float* const audioIn1
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioIn1
], nframes
);
2941 float* const audioIn2
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioIn2
], nframes
);
2942 float* const audioOut1
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut1
], nframes
);
2943 float* const audioOut2
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut2
], nframes
);
2946 CARLA_SAFE_ASSERT_RETURN(audioIn1
!= nullptr,);
2947 CARLA_SAFE_ASSERT_RETURN(audioIn2
!= nullptr,);
2948 CARLA_SAFE_ASSERT_RETURN(audioOut1
!= nullptr,);
2949 CARLA_SAFE_ASSERT_RETURN(audioOut2
!= nullptr,);
2952 carla_copyFloats(audioOut1
, audioIn1
, nframes
);
2953 carla_copyFloats(audioOut2
, audioIn2
, nframes
);
2955 // TODO pass-through MIDI as well
2956 if (void* const eventOut
= jackbridge_port_get_buffer(fRackPorts
[kRackPortEventOut
], nframes
))
2957 jackbridge_midi_clear_buffer(eventOut
);
2963 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
2965 for (uint i
=0; i
< pData
->curPluginCount
; ++i
)
2967 if (CarlaPluginPtr plugin
= pData
->plugins
[i
].plugin
)
2969 if (plugin
->isEnabled() && plugin
->tryLock(fFreewheel
))
2971 plugin
->initBuffers();
2972 processPlugin(plugin
, nframes
);
2978 else if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
||
2979 pData
->options
.processMode
== ENGINE_PROCESS_MODE_PATCHBAY
)
2981 CARLA_SAFE_ASSERT_RETURN(pData
->events
.in
!= nullptr,);
2982 CARLA_SAFE_ASSERT_RETURN(pData
->events
.out
!= nullptr,);
2984 // get buffers from jack
2985 float* const audioIn1
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioIn1
], nframes
);
2986 float* const audioIn2
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioIn2
], nframes
);
2987 float* const audioOut1
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut1
], nframes
);
2988 float* const audioOut2
= (float*)jackbridge_port_get_buffer(fRackPorts
[kRackPortAudioOut2
], nframes
);
2989 void* const eventIn
= jackbridge_port_get_buffer(fRackPorts
[kRackPortEventIn
], nframes
);
2990 void* const eventOut
= jackbridge_port_get_buffer(fRackPorts
[kRackPortEventOut
], nframes
);
2993 CARLA_SAFE_ASSERT_RETURN(audioIn1
!= nullptr,);
2994 CARLA_SAFE_ASSERT_RETURN(audioIn2
!= nullptr,);
2995 CARLA_SAFE_ASSERT_RETURN(audioOut1
!= nullptr,);
2996 CARLA_SAFE_ASSERT_RETURN(audioOut2
!= nullptr,);
2998 // create audio buffers
2999 const float* inBuf
[2] = { audioIn1
, audioIn2
};
3000 /**/ float* outBuf
[2] = { audioOut1
, audioOut2
};
3002 // initialize events
3003 carla_zeroStructs(pData
->events
.in
, kMaxEngineEventInternalCount
);
3004 carla_zeroStructs(pData
->events
.out
, kMaxEngineEventInternalCount
);
3006 if (eventIn
!= nullptr)
3008 ushort engineEventIndex
= 0;
3010 jack_midi_event_t jackEvent
;
3011 const uint32_t jackEventCount(jackbridge_midi_get_event_count(eventIn
));
3013 for (uint32_t jackEventIndex
=0; jackEventIndex
< jackEventCount
; ++jackEventIndex
)
3015 if (! jackbridge_midi_event_get(&jackEvent
, eventIn
, jackEventIndex
))
3018 CARLA_SAFE_ASSERT_CONTINUE(jackEvent
.size
< 0xFF /* uint8_t max */);
3020 EngineEvent
& engineEvent(pData
->events
.in
[engineEventIndex
++]);
3022 engineEvent
.time
= jackEvent
.time
;
3023 engineEvent
.fillFromMidiData(static_cast<uint8_t>(jackEvent
.size
), jackEvent
.buffer
, 0);
3025 if (engineEventIndex
>= kMaxEngineEventInternalCount
)
3030 if (pData
->options
.processMode
== ENGINE_PROCESS_MODE_CONTINUOUS_RACK
)
3032 pData
->graph
.processRack(pData
, inBuf
, outBuf
, nframes
);
3036 const CarlaMutexLocker
cml(fPatchbayProcThreadProtectionMutex
);
3037 pData
->graph
.process(pData
, inBuf
, outBuf
, nframes
);
3041 if (eventOut
!= nullptr)
3043 jackbridge_midi_clear_buffer(eventOut
);
3046 uint8_t mdata
[3] = { 0, 0, 0 };
3047 uint8_t mdataTmp
[EngineMidiEvent::kDataSize
];
3048 const uint8_t* mdataPtr
;
3050 for (ushort i
=0; i
< kMaxEngineEventInternalCount
; ++i
)
3052 const EngineEvent
& engineEvent(pData
->events
.out
[i
]);
3054 /**/ if (engineEvent
.type
== kEngineEventTypeNull
)
3058 else if (engineEvent
.type
== kEngineEventTypeControl
)
3060 const EngineControlEvent
& ctrlEvent(engineEvent
.ctrl
);
3062 size
= ctrlEvent
.convertToMidiData(engineEvent
.channel
, mdata
);
3065 else if (engineEvent
.type
== kEngineEventTypeMidi
)
3067 const EngineMidiEvent
& midiEvent(engineEvent
.midi
);
3069 size
= midiEvent
.size
;
3070 CARLA_SAFE_ASSERT_CONTINUE(size
> 0);
3072 if (size
> EngineMidiEvent::kDataSize
)
3074 CARLA_SAFE_ASSERT_CONTINUE(midiEvent
.dataExt
!= nullptr);
3075 mdataPtr
= midiEvent
.dataExt
;
3080 mdataTmp
[0] = static_cast<uint8_t>(midiEvent
.data
[0] | (engineEvent
.channel
& MIDI_CHANNEL_BIT
));
3085 carla_copy
<uint8_t>(mdataTmp
+1, midiEvent
.data
+1, size
-1U);
3089 mdataPtr
= mdataTmp
;
3098 jackbridge_midi_event_write(eventOut
, engineEvent
.time
, mdataPtr
, size
);
3103 if (pData
->options
.transportMode
== ENGINE_TRANSPORT_MODE_JACK
)
3105 if (fTimebaseMaster
)
3107 const bool playing
= jackbridge_transport_query(fClient
, nullptr) == JackTransportRolling
;
3109 if (fTimebaseRolling
!= playing
)
3111 fTimebaseRolling
= playing
;
3112 pData
->timeInfo
.playing
= playing
;
3115 // Check if we are no longer timebase master
3116 if (playing
&& fTimebaseUsecs
!= 0 && fTimebaseUsecs
== pData
->timeInfo
.usecs
)
3118 carla_debug("No longer timerbase master");
3119 fTimebaseMaster
= false;
3123 fTimebaseUsecs
= pData
->timeInfo
.usecs
;
3125 #endif // ! BUILD_BRIDGE
3128 void handleJackLatencyCallback(const jack_latency_callback_mode_t
/*mode*/)
3133 #ifndef BUILD_BRIDGE
3134 void handleJackTimebaseCallback(jack_nframes_t nframes
, jack_position_t
* const pos
, const int new_pos
)
3137 pData
->time
.setNeedsReset();
3139 pData
->timeInfo
.playing
= fTimebaseRolling
;
3140 pData
->timeInfo
.frame
= pos
->frame
;
3141 pData
->timeInfo
.usecs
= pos
->usecs
;
3142 pData
->time
.fillJackTimeInfo(pos
, nframes
);
3145 void handleJackClientUnregistrationCallback(const char* const name
)
3147 CARLA_SAFE_ASSERT_RETURN(name
!= nullptr && name
[0] != '\0',);
3152 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
3153 groupId
= fUsedGroups
.getGroupId(name
);
3155 // clients might have been registered without ports
3156 if (groupId
== 0) return;
3158 GroupNameToId groupNameToId
;
3159 groupNameToId
.setData(groupId
, name
);
3161 fUsedGroups
.list
.removeOne(groupNameToId
);
3164 // ignore callback if on internal patchbay mode
3165 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3166 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3168 if (! fExternalPatchbayHost
) return;
3171 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3172 ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED
,
3174 0, 0, 0, 0.0f
, nullptr);
3177 void handleJackClientPositionChangeCallback(const jack_uuid_t uuid
)
3179 // ignore this if on internal patchbay mode
3180 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3181 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3183 if (! fExternalPatchbayHost
) return;
3186 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
3188 char uuidstr
[JACK_UUID_STRING_SIZE
] = {};
3189 jackbridge_uuid_unparse(uuid
, uuidstr
);
3191 if (char* const clientName
= jackbridge_get_client_name_by_uuid(fClient
, uuidstr
))
3193 CARLA_SAFE_ASSERT_RETURN(clientName
!= nullptr && clientName
[0] != '\0',);
3198 const CarlaMutexLocker
cml(fUsedGroups
.mutex
);
3199 groupId
= fUsedGroups
.getGroupId(clientName
);
3202 jackbridge_free(clientName
);
3203 CARLA_SAFE_ASSERT_RETURN(groupId
!= 0,);
3205 char* value
= nullptr;
3206 char* type
= nullptr;
3208 if (jackbridge_get_property(uuid
, URI_POSITION
, &value
, &type
)
3211 && std::strcmp(type
, URI_TYPE_STRING
) == 0)
3213 if (char* sep1
= std::strstr(value
, ":"))
3215 LastPatchbaySetGroupPos pos
;
3217 pos
.x1
= std::atoi(value
);
3219 if (char* sep2
= std::strstr(sep1
, ":"))
3222 pos
.y1
= std::atoi(sep1
);
3224 if (char* sep3
= std::strstr(sep2
, ":"))
3227 pos
.x2
= std::atoi(sep2
);
3228 pos
.y2
= std::atoi(sep3
);
3231 if (fLastPatchbaySetGroupPos
!= pos
)
3233 fLastPatchbaySetGroupPos
.clear();
3235 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3236 ENGINE_CALLBACK_PATCHBAY_CLIENT_POSITION_CHANGED
,
3237 groupId
, pos
.x1
, pos
.y1
, pos
.x2
, static_cast<float>(pos
.y2
),
3243 jackbridge_free(value
);
3244 jackbridge_free(type
);
3249 void handleJackPortRegistrationCallback(const char* const portName
,
3250 const char* const shortPortName
,
3251 const CarlaJackPortHints
& jackPortHints
)
3254 CarlaString
groupName(portName
);
3255 groupName
.truncate(groupName
.rfind(shortPortName
, &groupFound
)-1);
3256 CARLA_SAFE_ASSERT_RETURN(groupFound
,);
3259 GroupToIdData groupData
;
3260 PortToIdData portData
;
3263 const CarlaMutexLocker
cml1(fUsedGroups
.mutex
);
3265 groupData
.id
= fUsedGroups
.getGroupId(groupName
);
3267 if (groupData
.id
== 0)
3269 groupData
.id
= ++fUsedGroups
.lastId
;
3271 GroupNameToId groupNameToId
;
3272 groupNameToId
.setData(groupData
.id
, groupName
);
3275 PatchbayIcon icon
= jackPortHints
.isHardware
? PATCHBAY_ICON_HARDWARE
: PATCHBAY_ICON_APPLICATION
;
3277 findPluginIdAndIcon(groupName
, pluginId
, icon
);
3279 fUsedGroups
.list
.append(groupNameToId
);
3282 groupData
.icon
= icon
;
3283 groupData
.pluginId
= pluginId
;
3284 std::strncpy(groupData
.strVal
, groupName
, STR_MAX
-1);
3285 groupData
.strVal
[STR_MAX
-1] = '\0';
3289 // ignore the rest if on internal patchbay mode
3290 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3291 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3293 if (! fExternalPatchbayHost
) return;
3297 uint canvasPortFlags
= 0x0;
3298 canvasPortFlags
|= jackPortHints
.isInput
? PATCHBAY_PORT_IS_INPUT
: 0x0;
3300 /**/ if (jackPortHints
.isCV
)
3301 canvasPortFlags
|= PATCHBAY_PORT_TYPE_CV
;
3302 else if (jackPortHints
.isOSC
)
3303 canvasPortFlags
|= PATCHBAY_PORT_TYPE_OSC
;
3304 else if (jackPortHints
.isAudio
)
3305 canvasPortFlags
|= PATCHBAY_PORT_TYPE_AUDIO
;
3306 else if (jackPortHints
.isMIDI
)
3307 canvasPortFlags
|= PATCHBAY_PORT_TYPE_MIDI
;
3309 const CarlaMutexLocker
cml2(fUsedPorts
.mutex
);
3311 portData
.group
= groupData
.id
;
3312 portData
.port
= ++fUsedPorts
.lastId
;
3313 portData
.flags
= canvasPortFlags
;
3314 std::strncpy(portData
.strVal
, shortPortName
, STR_MAX
-1);
3315 portData
.strVal
[STR_MAX
-1] = '\0';
3317 PortNameToId portNameToId
;
3318 portNameToId
.setData(portData
.group
, portData
.port
, shortPortName
, portName
);
3319 fUsedPorts
.list
.append(portNameToId
);
3324 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3325 ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED
,
3333 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3334 ENGINE_CALLBACK_PATCHBAY_PORT_ADDED
,
3336 static_cast<int>(portData
.port
),
3337 static_cast<int>(portData
.flags
),
3342 void handleJackPortUnregistrationCallback(const char* const portName
)
3344 // ignore this if on internal patchbay mode
3345 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3346 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3348 if (! fExternalPatchbayHost
) return;
3351 uint groupId
, portId
;
3354 const CarlaMutexLocker
cml(fUsedPorts
.mutex
);
3356 const PortNameToId
& portNameToId(fUsedPorts
.getPortNameToId(portName
));
3358 /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request.
3359 See the comment on CarlaEngineJack::renamePlugin() for more information. */
3360 if (portNameToId
.group
<= 0 || portNameToId
.port
<= 0) return;
3362 groupId
= portNameToId
.group
;
3363 portId
= portNameToId
.port
;
3365 fUsedPorts
.list
.removeOne(portNameToId
);
3368 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3369 ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED
,
3371 static_cast<int>(portId
),
3372 0, 0, 0.0f
, nullptr);
3375 void handleJackPortConnectCallback(const char* const portNameA
, const char* const portNameB
)
3377 // ignore this if on internal patchbay mode
3378 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3379 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3381 if (! fExternalPatchbayHost
) return;
3384 char strBuf
[STR_MAX
];
3388 const CarlaMutexLocker
cml1(fUsedPorts
.mutex
);
3390 const PortNameToId
& portNameToIdA(fUsedPorts
.getPortNameToId(portNameA
));
3391 const PortNameToId
& portNameToIdB(fUsedPorts
.getPortNameToId(portNameB
));
3393 /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request.
3394 See the comment on CarlaEngineJack::renamePlugin() for more information. */
3395 if (portNameToIdA
.group
<= 0 || portNameToIdA
.port
<= 0) return;
3396 if (portNameToIdB
.group
<= 0 || portNameToIdB
.port
<= 0) return;
3398 const CarlaMutexLocker
cml2(fUsedConnections
.mutex
);
3400 std::snprintf(strBuf
, STR_MAX
-1, "%i:%i:%i:%i",
3401 portNameToIdA
.group
, portNameToIdA
.port
,
3402 portNameToIdB
.group
, portNameToIdB
.port
);
3403 strBuf
[STR_MAX
-1] = '\0';
3405 connectionId
= ++fUsedConnections
.lastId
;
3407 ConnectionToId connectionToId
;
3408 connectionToId
.setData(connectionId
,
3409 portNameToIdA
.group
, portNameToIdA
.port
,
3410 portNameToIdB
.group
, portNameToIdB
.port
);
3412 fUsedConnections
.list
.append(connectionToId
);
3415 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3416 ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED
,
3422 void handleJackPortDisconnectCallback(const char* const portNameA
, const char* const portNameB
)
3424 // ignore this if on internal patchbay mode
3425 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3426 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3428 if (! fExternalPatchbayHost
) return;
3431 uint connectionId
= 0;
3434 const CarlaMutexLocker
cml1(fUsedPorts
.mutex
);
3436 const PortNameToId
& portNameToIdA(fUsedPorts
.getPortNameToId(portNameA
));
3437 const PortNameToId
& portNameToIdB(fUsedPorts
.getPortNameToId(portNameB
));
3439 /* NOTE: Due to JACK2 async behaviour the port we get here might be the same of a previous rename-plugin request.
3440 See the comment on CarlaEngineJack::renamePlugin() for more information. */
3441 if (portNameToIdA
.group
<= 0 || portNameToIdA
.port
<= 0) return;
3442 if (portNameToIdB
.group
<= 0 || portNameToIdB
.port
<= 0) return;
3444 const CarlaMutexLocker
cml2(fUsedConnections
.mutex
);
3446 for (LinkedList
<ConnectionToId
>::Itenerator it
= fUsedConnections
.list
.begin2(); it
.valid(); it
.next())
3448 const ConnectionToId
& connectionToId
= it
.getValue(kConnectionToIdFallback
);
3449 CARLA_SAFE_ASSERT_CONTINUE(connectionToId
.id
!= 0);
3451 if (connectionToId
.groupA
== portNameToIdA
.group
&& connectionToId
.portA
== portNameToIdA
.port
&&
3452 connectionToId
.groupB
== portNameToIdB
.group
&& connectionToId
.portB
== portNameToIdB
.port
)
3454 connectionId
= connectionToId
.id
;
3455 fUsedConnections
.list
.remove(it
);
3461 if (connectionId
!= 0) {
3462 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3463 ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED
,
3465 0, 0, 0, 0.0f
, nullptr);
3469 void handleJackPortRenameCallback(const char* const oldFullName
,
3470 const char* const newFullName
,
3471 const char* const newShortName
)
3473 // ignore this if on internal patchbay mode
3474 #if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
3475 if (! (fExternalPatchbayHost
|| (fExternalPatchbayOsc
&& pData
->osc
.isControlRegisteredForTCP()))) return;
3477 if (! fExternalPatchbayHost
) return;
3480 CARLA_SAFE_ASSERT_RETURN(oldFullName
!= nullptr && oldFullName
[0] != '\0',);
3481 CARLA_SAFE_ASSERT_RETURN(newFullName
!= nullptr && newFullName
[0] != '\0',);
3484 CarlaString
groupName(newFullName
);
3485 groupName
.truncate(groupName
.rfind(newShortName
, &found
)-1);
3486 CARLA_SAFE_ASSERT_RETURN(found
,);
3488 uint groupId
, portId
= 0;
3489 char portName
[STR_MAX
];
3493 const CarlaMutexLocker
cml1(fUsedGroups
.mutex
);
3495 groupId
= fUsedGroups
.getGroupId(groupName
);
3496 CARLA_SAFE_ASSERT_RETURN(groupId
!= 0,);
3498 const CarlaMutexLocker
cml2(fUsedPorts
.mutex
);
3500 for (LinkedList
<PortNameToId
>::Itenerator it
= fUsedPorts
.list
.begin2(); it
.valid(); it
.next())
3502 PortNameToId
& portNameToId(it
.getValue(kPortNameToIdFallbackNC
));
3503 CARLA_SAFE_ASSERT_CONTINUE(portNameToId
.group
!= 0);
3505 if (std::strncmp(portNameToId
.fullName
, oldFullName
, STR_MAX
) == 0)
3507 CARLA_SAFE_ASSERT_CONTINUE(portNameToId
.group
== groupId
);
3510 portId
= portNameToId
.port
;
3511 std::strncpy(portName
, newShortName
, STR_MAX
-1);
3512 portName
[STR_MAX
-1] = '\0';
3514 portNameToId
.rename(newShortName
, newFullName
);
3522 callback(fExternalPatchbayHost
, fExternalPatchbayOsc
,
3523 ENGINE_CALLBACK_PATCHBAY_PORT_CHANGED
,
3525 static_cast<int>(portId
),
3532 void handleJackShutdownCallback()
3534 #ifndef BUILD_BRIDGE
3535 if (fIsInternalClient
)
3540 const PendingRtEventsRunner
prt(this, pData
->bufferSize
);
3542 for (uint i
=0; i
< pData
->curPluginCount
; ++i
)
3544 if (const CarlaPluginPtr plugin
= pData
->plugins
[i
].plugin
)
3546 plugin
->tryLock(true);
3548 if (CarlaEngineJackClient
* const client
= (CarlaEngineJackClient
*)plugin
->getEngineClient())
3549 client
->invalidate();
3556 pData
->runner
.stopRunner();
3562 carla_zeroPointers(fRackPorts
, kRackPortCount
);
3565 callback(true, true, ENGINE_CALLBACK_ERROR
, 0, 0, 0, 0, 0.0f
,
3566 "Carla has been killed by JACK, or JACK has stopped.\n"
3567 "You can still save if you want, but you will lose patchbay connections and positions.");
3570 // -------------------------------------------------------------------
3572 void handlePluginJackShutdownCallback(const CarlaPluginPtr plugin
)
3574 CarlaEngineJackClient
* const engineClient((CarlaEngineJackClient
*)plugin
->getEngineClient());
3575 CARLA_SAFE_ASSERT_RETURN(engineClient
!= nullptr,);
3577 plugin
->tryLock(true);
3578 engineClient
->invalidate();
3581 callback(true, true, ENGINE_CALLBACK_PLUGIN_UNAVAILABLE
, plugin
->getId(), 0, 0, 0, 0.0f
, "Killed by JACK");
3584 // -------------------------------------------------------------------
3587 jack_client_t
* fClient
;
3588 bool fExternalPatchbayHost
;
3589 bool fExternalPatchbayOsc
;
3592 CarlaString fClientName
;
3593 CarlaRecursiveMutex fThreadSafeMetadataMutex
;
3595 // -------------------------------------------------------------------
3600 CarlaString fClientNamePrefix
;
3603 kRackPortAudioIn1
= 0,
3604 kRackPortAudioIn2
= 1,
3605 kRackPortAudioOut1
= 2,
3606 kRackPortAudioOut2
= 3,
3607 kRackPortEventIn
= 4,
3608 kRackPortEventOut
= 5,
3612 jack_port_t
* fRackPorts
[kRackPortCount
];
3614 bool fTimebaseMaster
;
3615 bool fTimebaseRolling
;
3616 uint64_t fTimebaseUsecs
;
3618 PatchbayGroupList fUsedGroups
;
3619 PatchbayPortList fUsedPorts
;
3620 PatchbayConnectionList fUsedConnections
;
3621 CarlaMutex fPatchbayProcThreadProtectionMutex
;
3623 mutable CharStringListPtr fRetConns
;
3625 void findPluginIdAndIcon(const char* const clientName
, int& pluginId
, PatchbayIcon
& icon
) const noexcept
3627 carla_debug("CarlaEngineJack::findPluginIdAndIcon(\"%s\", ...)", clientName
);
3629 // TODO - this currently only works in multi-client mode
3630 if (pData
->options
.processMode
!= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
)
3633 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
3637 char* const uuidstr
= jackbridge_get_uuid_for_client_name(fClient
, clientName
);
3638 CARLA_SAFE_ASSERT_RETURN(uuidstr
!= nullptr && uuidstr
[0] != '\0',);
3640 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
3641 jackbridge_free(uuidstr
);
3643 /* if parsing fails, meta-data is not available..
3644 this could be because JACK version is old, or perhaps this is an internal client */
3649 bool clientBelongsToUs
;
3652 char* value
= nullptr;
3653 char* type
= nullptr;
3655 if (! jackbridge_get_property(uuid
, URI_MAIN_CLIENT_NAME
, &value
, &type
))
3658 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr && type
[0] != '\0',);
3659 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr && value
[0] != '\0',);
3660 CARLA_SAFE_ASSERT_RETURN(std::strcmp(type
, URI_TYPE_STRING
) == 0,);
3662 clientBelongsToUs
= fClientName
== value
;
3664 jackbridge_free(value
);
3665 jackbridge_free(type
);
3669 char* value
= nullptr;
3670 char* type
= nullptr;
3672 if (! jackbridge_get_property(uuid
, URI_PLUGIN_ID
, &value
, &type
))
3675 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr && type
[0] != '\0',);
3676 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr && value
[0] != '\0',);
3677 CARLA_SAFE_ASSERT_RETURN(std::strcmp(type
, URI_TYPE_INTEGER
) == 0,);
3679 if (clientBelongsToUs
)
3680 pluginId
= std::atoi(value
);
3682 icon
= PATCHBAY_ICON_PLUGIN
;
3684 jackbridge_free(value
);
3685 jackbridge_free(type
);
3689 char* value
= nullptr;
3690 char* type
= nullptr;
3692 if (! jackbridge_get_property(uuid
, URI_PLUGIN_ICON
, &value
, &type
))
3695 CARLA_SAFE_ASSERT_RETURN(type
!= nullptr && type
[0] != '\0',);
3696 CARLA_SAFE_ASSERT_RETURN(value
!= nullptr && value
[0] != '\0',);
3697 CARLA_SAFE_ASSERT_RETURN(std::strcmp(type
, URI_TYPE_STRING
) == 0,);
3699 /**/ if (std::strcmp(value
, "app") == 0)
3700 icon
= PATCHBAY_ICON_APPLICATION
;
3701 else if (std::strcmp(value
, "application") == 0)
3702 icon
= PATCHBAY_ICON_APPLICATION
;
3703 else if (std::strcmp(value
, "plugin") == 0)
3704 icon
= PATCHBAY_ICON_PLUGIN
;
3705 else if (std::strcmp(value
, "hardware") == 0)
3706 icon
= PATCHBAY_ICON_HARDWARE
;
3707 else if (std::strcmp(value
, "carla") == 0)
3708 icon
= PATCHBAY_ICON_CARLA
;
3709 else if (std::strcmp(value
, "distrho") == 0)
3710 icon
= PATCHBAY_ICON_DISTRHO
;
3711 else if (std::strcmp(value
, "file") == 0)
3712 icon
= PATCHBAY_ICON_FILE
;
3714 jackbridge_free(value
);
3715 jackbridge_free(type
);
3719 // prevent recursion on patchbay group position changes
3720 struct LastPatchbaySetGroupPos
{
3723 LastPatchbaySetGroupPos()
3724 : x1(0), y1(0), x2(0), y2(0) {}
3726 void clear() noexcept
3728 x1
= y1
= x2
= y2
= 0;
3731 void set(const int _x1
, const int _y1
, const int _x2
, const int _y2
) noexcept
3739 bool operator!=(const LastPatchbaySetGroupPos
& pos
) const noexcept
3741 return pos
.x1
!= x1
|| pos
.y1
!= y1
|| pos
.x2
!= x2
|| pos
.y2
!= y2
;
3743 } fLastPatchbaySetGroupPos
;
3745 // handy stuff only needed for initJackPatchbay
3746 struct GroupToIdData
{
3750 char strVal
[STR_MAX
];
3752 struct PortToIdData
{
3756 char strVal
[STR_MAX
];
3758 struct ConnectionToIdData
{
3760 char strVal
[STR_MAX
];
3763 void initJackPatchbay(const bool sendHost
, const bool sendOSC
, const char* const ourName
, const bool groupsOnly
)
3765 CARLA_SAFE_ASSERT_RETURN(ourName
!= nullptr && ourName
[0] != '\0',);
3767 fLastPatchbaySetGroupPos
.clear();
3770 CarlaStringList parsedGroups
;
3771 LinkedList
<GroupToIdData
> groupCallbackData
;
3772 LinkedList
<PortToIdData
> portsCallbackData
;
3773 LinkedList
<ConnectionToIdData
> connCallbackData
;
3776 const CarlaMutexLocker
cml1(fUsedGroups
.mutex
);
3777 const CarlaMutexLocker
cml2(fUsedPorts
.mutex
);
3778 const CarlaMutexLocker
cml3(fUsedConnections
.mutex
);
3779 const CarlaMutexLocker
cml4(fPostPonedEventsMutex
);
3781 fUsedGroups
.clear();
3783 fUsedConnections
.clear();
3784 fPostPonedEvents
.clear();
3786 // add our client first
3788 carlaId
= ++fUsedGroups
.lastId
;
3789 parsedGroups
.append(ourName
);
3791 GroupNameToId groupNameToId
;
3792 groupNameToId
.setData(carlaId
, ourName
);
3793 fUsedGroups
.list
.append(groupNameToId
);
3796 // query all jack ports
3798 const char** const ports
= jackbridge_get_ports(fClient
, nullptr, nullptr, 0);
3799 CARLA_SAFE_ASSERT_RETURN(ports
!= nullptr,);
3801 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
3803 for (int i
=0; ports
[i
] != nullptr; ++i
)
3805 const char* const fullPortName(ports
[i
]);
3806 CARLA_SAFE_ASSERT_CONTINUE(fullPortName
!= nullptr && fullPortName
[0] != '\0');
3808 const jack_port_t
* const jackPort(jackbridge_port_by_name(fClient
, fullPortName
));
3809 CARLA_SAFE_ASSERT_CONTINUE(jackPort
!= nullptr);
3811 const char* const shortPortName(jackbridge_port_short_name(jackPort
));
3812 CARLA_SAFE_ASSERT_CONTINUE(shortPortName
!= nullptr && shortPortName
[0] != '\0');
3814 const CarlaJackPortHints
jackPortHints(CarlaJackPortHints::fromPort(jackPort
));
3819 CarlaString
groupName(fullPortName
);
3820 groupName
.truncate(groupName
.rfind(shortPortName
, &found
)-1);
3822 CARLA_SAFE_ASSERT_CONTINUE(found
);
3824 if (parsedGroups
.contains(groupName
))
3826 groupId
= fUsedGroups
.getGroupId(groupName
);
3827 CARLA_SAFE_ASSERT_CONTINUE(groupId
> 0);
3831 groupId
= ++fUsedGroups
.lastId
;
3832 parsedGroups
.append(groupName
);
3834 GroupNameToId groupNameToId
;
3835 groupNameToId
.setData(groupId
, groupName
);
3838 PatchbayIcon icon
= jackPortHints
.isHardware
? PATCHBAY_ICON_HARDWARE
: PATCHBAY_ICON_APPLICATION
;
3840 findPluginIdAndIcon(groupName
, pluginId
, icon
);
3842 fUsedGroups
.list
.append(groupNameToId
);
3846 GroupToIdData groupData
;
3847 groupData
.id
= groupId
;
3848 groupData
.icon
= icon
;
3849 groupData
.pluginId
= pluginId
;
3850 std::strncpy(groupData
.strVal
, groupName
, STR_MAX
-1);
3851 groupData
.strVal
[STR_MAX
-1] = '\0';
3852 groupCallbackData
.append(groupData
);
3859 uint canvasPortFlags
= 0x0;
3860 canvasPortFlags
|= jackPortHints
.isInput
? PATCHBAY_PORT_IS_INPUT
: 0x0;
3862 /**/ if (jackPortHints
.isCV
)
3863 canvasPortFlags
|= PATCHBAY_PORT_TYPE_CV
;
3864 else if (jackPortHints
.isOSC
)
3865 canvasPortFlags
|= PATCHBAY_PORT_TYPE_OSC
;
3866 else if (jackPortHints
.isAudio
)
3867 canvasPortFlags
|= PATCHBAY_PORT_TYPE_AUDIO
;
3868 else if (jackPortHints
.isMIDI
)
3869 canvasPortFlags
|= PATCHBAY_PORT_TYPE_MIDI
;
3871 id
= ++fUsedPorts
.lastId
;
3873 PortNameToId portNameToId
;
3874 portNameToId
.setData(groupId
, id
, shortPortName
, fullPortName
);
3875 fUsedPorts
.list
.append(portNameToId
);
3877 PortToIdData portData
;
3878 portData
.group
= groupId
;
3880 portData
.flags
= canvasPortFlags
;
3881 std::strncpy(portData
.strVal
, shortPortName
, STR_MAX
-1);
3882 portData
.strVal
[STR_MAX
-1] = '\0';
3883 portsCallbackData
.append(portData
);
3886 jackbridge_free(ports
);
3892 // query connections, after all ports are in place
3893 if (const char** const ports
= jackbridge_get_ports(fClient
, nullptr, nullptr, JackPortIsOutput
))
3895 for (int i
=0; ports
[i
] != nullptr; ++i
)
3897 const char* const fullPortName(ports
[i
]);
3898 CARLA_SAFE_ASSERT_CONTINUE(fullPortName
!= nullptr && fullPortName
[0] != '\0');
3900 const jack_port_t
* const jackPort(jackbridge_port_by_name(fClient
, fullPortName
));
3901 CARLA_SAFE_ASSERT_CONTINUE(jackPort
!= nullptr);
3903 const PortNameToId
& thisPort(fUsedPorts
.getPortNameToId(fullPortName
));
3905 CARLA_SAFE_ASSERT_CONTINUE(thisPort
.group
> 0);
3906 CARLA_SAFE_ASSERT_CONTINUE(thisPort
.port
> 0);
3908 if (const char** const connections
= jackbridge_port_get_all_connections(fClient
, jackPort
))
3910 for (int j
=0; connections
[j
] != nullptr; ++j
)
3912 const char* const connection(connections
[j
]);
3913 CARLA_SAFE_ASSERT_CONTINUE(connection
!= nullptr && connection
[0] != '\0');
3915 const PortNameToId
& targetPort(fUsedPorts
.getPortNameToId(connection
));
3917 CARLA_SAFE_ASSERT_CONTINUE(targetPort
.group
> 0);
3918 CARLA_SAFE_ASSERT_CONTINUE(targetPort
.port
> 0);
3920 id
= ++fUsedConnections
.lastId
;
3922 ConnectionToId connectionToId
;
3923 connectionToId
.setData(id
, thisPort
.group
, thisPort
.port
, targetPort
.group
, targetPort
.port
);
3924 fUsedConnections
.list
.append(connectionToId
);
3926 ConnectionToIdData connData
;
3928 std::snprintf(connData
.strVal
, STR_MAX
-1, "%i:%i:%i:%i",
3929 thisPort
.group
, thisPort
.port
, targetPort
.group
, targetPort
.port
);
3930 connData
.strVal
[STR_MAX
-1] = '\0';
3931 connCallbackData
.append(connData
);
3934 jackbridge_free(connections
);
3938 jackbridge_free(ports
);
3942 const GroupToIdData groupFallback
= { 0, PATCHBAY_ICON_PLUGIN
, -1, { '\0' } };
3943 const PortToIdData portFallback
= { 0, 0, 0, { '\0' } };
3944 const ConnectionToIdData connFallback
= { 0, { '\0' } };
3946 callback(sendHost
, sendOSC
,
3947 ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED
,
3949 PATCHBAY_ICON_CARLA
,
3950 MAIN_CARLA_PLUGIN_ID
,
3955 const CarlaRecursiveMutexLocker
crml(fThreadSafeMetadataMutex
);
3957 for (LinkedList
<GroupToIdData
>::Itenerator it
= groupCallbackData
.begin2(); it
.valid(); it
.next())
3959 const GroupToIdData
& group(it
.getValue(groupFallback
));
3961 callback(sendHost
, sendOSC
,
3962 ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED
,
3971 char* const uuidstr
= jackbridge_get_uuid_for_client_name(fClient
, group
.strVal
);
3972 CARLA_SAFE_ASSERT_CONTINUE(uuidstr
!= nullptr && uuidstr
[0] != '\0');
3974 const bool parsed
= jackbridge_uuid_parse(uuidstr
, &uuid
);
3975 jackbridge_free(uuidstr
);
3977 /* if parsing fails, meta-data is not available..
3978 this could be because JACK version is old, or perhaps this is an internal client */
3983 char* value
= nullptr;
3984 char* type
= nullptr;
3986 if (jackbridge_get_property(uuid
, URI_POSITION
, &value
, &type
)
3989 && std::strcmp(type
, URI_TYPE_STRING
) == 0)
3991 if (char* sep1
= std::strstr(value
, ":"))
3993 int x1
, y1
= 0, x2
= 0, y2
= 0;
3995 x1
= std::atoi(value
);
3997 if (char* sep2
= std::strstr(sep1
, ":"))
4000 y1
= std::atoi(sep1
);
4002 if (char* sep3
= std::strstr(sep2
, ":"))
4005 x2
= std::atoi(sep2
);
4006 y2
= std::atoi(sep3
);
4010 jackbridge_free(value
);
4011 jackbridge_free(type
);
4013 callback(sendHost
, sendOSC
,
4014 ENGINE_CALLBACK_PATCHBAY_CLIENT_POSITION_CHANGED
,
4015 group
.id
, x1
, y1
, x2
, static_cast<float>(y2
),
4022 for (LinkedList
<PortToIdData
>::Itenerator it
= portsCallbackData
.begin2(); it
.valid(); it
.next())
4024 const PortToIdData
& port(it
.getValue(portFallback
));
4026 callback(sendHost
, sendOSC
,
4027 ENGINE_CALLBACK_PATCHBAY_PORT_ADDED
,
4029 static_cast<int>(port
.port
),
4030 static_cast<int>(port
.flags
),
4035 for (LinkedList
<ConnectionToIdData
>::Itenerator it
= connCallbackData
.begin2(); it
.valid(); it
.next())
4037 const ConnectionToIdData
& conn(it
.getValue(connFallback
));
4039 callback(sendHost
, sendOSC
,
4040 ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED
,
4046 groupCallbackData
.clear();
4047 portsCallbackData
.clear();
4048 connCallbackData
.clear();
4052 // -------------------------------------------------------------------
4054 void processPlugin(CarlaPluginPtr
& plugin
, const uint32_t nframes
)
4056 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4057 CarlaEngineJackClient
* const client
= (CarlaEngineJackClient
*)plugin
->getEngineClient();
4058 CarlaEngineJackCVSourcePorts
& cvSourcePorts(client
->getCVSourcePorts());
4060 const CarlaRecursiveMutexTryLocker
crmtl(cvSourcePorts
.getMutex(), fFreewheel
);
4061 // const CarlaRecursiveMutexLocker crml(cvSourcePorts.getMutex());
4065 const uint32_t audioInCount = client->getPortCount(kEnginePortTypeAudio, true);
4066 const uint32_t audioOutCount = client->getPortCount(kEnginePortTypeAudio, false);
4067 const uint32_t cvInCount = client->getPortCount(kEnginePortTypeCV, true);
4068 const uint32_t cvOutCount = client->getPortCount(kEnginePortTypeCV, false);
4071 const uint32_t audioInCount
= plugin
->getAudioInCount();
4072 const uint32_t audioOutCount
= plugin
->getAudioOutCount();
4073 const uint32_t cvInCount
= plugin
->getCVInCount();
4074 const uint32_t cvOutCount
= plugin
->getCVOutCount();
4075 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4076 const uint32_t cvsInCount
= crmtl
.wasLocked() ? cvSourcePorts
.getPortCount() : 0;
4078 const uint32_t cvsInCount
= 0;
4081 const float* audioIn
[audioInCount
];
4082 /* */ float* audioOut
[audioOutCount
];
4083 const float* cvIn
[cvInCount
+cvsInCount
];
4084 /* */ float* cvOut
[cvOutCount
];
4086 for (uint32_t i
=0; i
< audioInCount
; ++i
)
4088 if (CarlaEngineAudioPort
* const port
= plugin
->getAudioInPort(i
))
4089 audioIn
[i
] = port
->getBuffer();
4091 audioIn
[i
] = nullptr;
4094 for (uint32_t i
=0; i
< audioOutCount
; ++i
)
4096 if (CarlaEngineAudioPort
* const port
= plugin
->getAudioOutPort(i
))
4097 audioOut
[i
] = port
->getBuffer();
4099 audioOut
[i
] = nullptr;
4102 for (uint32_t i
=0; i
< cvInCount
; ++i
)
4104 if (CarlaEngineCVPort
* const port
= plugin
->getCVInPort(i
))
4105 cvIn
[i
] = port
->getBuffer();
4110 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
4111 for (uint32_t i
=cvInCount
, j
=0; j
< cvsInCount
; ++i
, ++j
)
4113 if (CarlaEngineCVPort
* const port
= cvSourcePorts
.getPort(j
))
4116 cvIn
[i
] = port
->getBuffer();
4125 for (uint32_t i
=0; i
< cvOutCount
; ++i
)
4127 if (CarlaEngineCVPort
* const port
= plugin
->getCVOutPort(i
))
4128 cvOut
[i
] = port
->getBuffer();
4133 float inPeaks
[2] = { 0.0f
};
4134 float outPeaks
[2] = { 0.0f
};
4136 for (uint32_t i
=0; i
< audioInCount
&& i
< 2; ++i
)
4138 for (uint32_t j
=0; j
< nframes
; ++j
)
4140 const float absV(std::abs(audioIn
[i
][j
]));
4142 if (absV
> inPeaks
[i
])
4147 plugin
->process(audioIn
, audioOut
, cvIn
, cvOut
, nframes
);
4149 for (uint32_t i
=0; i
< audioOutCount
&& i
< 2; ++i
)
4151 for (uint32_t j
=0; j
< nframes
; ++j
)
4153 const float absV(std::abs(audioOut
[i
][j
]));
4155 if (absV
> outPeaks
[i
])
4160 setPluginPeaksRT(plugin
->getId(), inPeaks
, outPeaks
);
4163 #ifndef BUILD_BRIDGE
4164 // -------------------------------------------------------------------
4166 struct PostPonedJackEvent
{
4169 kTypeClientUnregister
,
4170 kTypeClientPositionChange
,
4172 kTypePortUnregister
,
4174 kTypePortDisconnect
,
4182 char name
[STR_MAX
+1];
4185 char name
[STR_MAX
+1];
4189 } clientPositionChange
;
4191 char shortName
[STR_MAX
+1];
4192 char fullName
[STR_MAX
+1];
4193 CarlaJackPortHints hints
;
4196 char fullName
[STR_MAX
+1];
4199 char oldFullName
[STR_MAX
+1];
4200 char newFullName
[STR_MAX
+1];
4201 char newShortName
[STR_MAX
+1];
4204 char portNameA
[STR_MAX
+1];
4205 char portNameB
[STR_MAX
+1];
4208 char portNameA
[STR_MAX
+1];
4209 char portNameB
[STR_MAX
+1];
4214 LinkedList
<PostPonedJackEvent
> fPostPonedEvents
;
4215 CarlaMutex fPostPonedEventsMutex
;
4217 bool fIsInternalClient
;
4219 void postponeJackCallback(PostPonedJackEvent
& ev
)
4221 const CarlaMutexLocker
cml(fPostPonedEventsMutex
);
4222 fPostPonedEvents
.append(ev
);
4227 for (; ! shouldThreadExit();)
4229 if (fIsInternalClient
)
4232 if (fClient
== nullptr)
4238 #endif // BUILD_BRIDGE
4240 // -------------------------------------------------------------------
4242 // disable -Wattributes warnings
4243 #if defined(__clang__)
4244 # pragma clang diagnostic push
4245 # pragma clang diagnostic ignored "-Wattributes"
4246 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4247 # pragma GCC diagnostic push
4248 # pragma GCC diagnostic ignored "-Wattributes"
4251 #define handlePtr ((CarlaEngineJack*)arg)
4253 static void JACKBRIDGE_API
carla_jack_thread_init_callback(void*)
4255 #ifdef __SSE2_MATH__
4256 // Set FTZ and DAZ flags
4257 _mm_setcsr(_mm_getcsr() | 0x8040);
4261 static int JACKBRIDGE_API
carla_jack_bufsize_callback(jack_nframes_t newBufferSize
, void* arg
)
4263 handlePtr
->handleJackBufferSizeCallback(newBufferSize
);
4267 static int JACKBRIDGE_API
carla_jack_srate_callback(jack_nframes_t newSampleRate
, void* arg
)
4269 handlePtr
->handleJackSampleRateCallback(newSampleRate
);
4273 static void JACKBRIDGE_API
carla_jack_freewheel_callback(int starting
, void* arg
)
4275 handlePtr
->handleJackFreewheelCallback(bool(starting
));
4278 static void JACKBRIDGE_API
carla_jack_latency_callback(jack_latency_callback_mode_t mode
, void* arg
)
4280 handlePtr
->handleJackLatencyCallback(mode
);
4283 static int JACKBRIDGE_API
carla_jack_process_callback(jack_nframes_t nframes
, void* arg
) __attribute__((annotate("realtime")))
4285 handlePtr
->handleJackProcessCallback(nframes
);
4289 #ifndef BUILD_BRIDGE
4290 static void JACKBRIDGE_API
carla_jack_timebase_callback(jack_transport_state_t
, jack_nframes_t nframes
, jack_position_t
* pos
, int new_pos
, void* arg
) __attribute__((annotate("realtime")))
4292 handlePtr
->handleJackTimebaseCallback(nframes
, pos
, new_pos
);
4295 static void JACKBRIDGE_API
carla_jack_client_registration_callback(const char* name
, int reg
, void* arg
)
4300 PostPonedJackEvent ev
;
4301 carla_zeroStruct(ev
);
4302 ev
.type
= PostPonedJackEvent::kTypeClientUnregister
;
4303 std::strncpy(ev
.clientUnregister
.name
, name
, STR_MAX
);
4304 handlePtr
->postponeJackCallback(ev
);
4307 static void JACKBRIDGE_API
carla_jack_port_registration_callback(jack_port_id_t port_id
, int reg
, void* arg
)
4309 const jack_port_t
* const port
= jackbridge_port_by_id(handlePtr
->fClient
, port_id
);
4310 CARLA_SAFE_ASSERT_RETURN(port
!= nullptr,);
4312 const char* const fullName
= jackbridge_port_name(port
);
4313 CARLA_SAFE_ASSERT_RETURN(fullName
!= nullptr && fullName
[0] != '\0',);
4315 PostPonedJackEvent ev
;
4316 carla_zeroStruct(ev
);
4320 const char* const shortName
= jackbridge_port_short_name(port
);
4321 CARLA_SAFE_ASSERT_RETURN(shortName
!= nullptr && shortName
[0] != '\0',);
4323 ev
.type
= PostPonedJackEvent::kTypePortRegister
;
4324 std::strncpy(ev
.portRegister
.fullName
, fullName
, STR_MAX
);
4325 std::strncpy(ev
.portRegister
.shortName
, shortName
, STR_MAX
);
4327 const CarlaRecursiveMutexLocker
crml(handlePtr
->fThreadSafeMetadataMutex
);
4328 ev
.portRegister
.hints
= CarlaJackPortHints::fromPort(port
);
4332 ev
.type
= PostPonedJackEvent::kTypePortUnregister
;
4333 std::strncpy(ev
.portUnregister
.fullName
, fullName
, STR_MAX
);
4336 handlePtr
->postponeJackCallback(ev
);
4339 static void JACKBRIDGE_API
carla_jack_port_connect_callback(jack_port_id_t a
, jack_port_id_t b
, int connect
, void* arg
)
4341 const jack_port_t
* const portA
= jackbridge_port_by_id(handlePtr
->fClient
, a
);
4342 CARLA_SAFE_ASSERT_RETURN(portA
!= nullptr,);
4344 const jack_port_t
* const portB
= jackbridge_port_by_id(handlePtr
->fClient
, b
);
4345 CARLA_SAFE_ASSERT_RETURN(portB
!= nullptr,);
4347 const char* const fullNameA
= jackbridge_port_name(portA
);
4348 CARLA_SAFE_ASSERT_RETURN(fullNameA
!= nullptr && fullNameA
[0] != '\0',);
4350 const char* const fullNameB
= jackbridge_port_name(portB
);
4351 CARLA_SAFE_ASSERT_RETURN(fullNameB
!= nullptr && fullNameB
[0] != '\0',);
4353 PostPonedJackEvent ev
;
4354 carla_zeroStruct(ev
);
4358 ev
.type
= PostPonedJackEvent::kTypePortConnect
;
4359 std::strncpy(ev
.portConnect
.portNameA
, fullNameA
, STR_MAX
);
4360 std::strncpy(ev
.portConnect
.portNameB
, fullNameB
, STR_MAX
);
4364 ev
.type
= PostPonedJackEvent::kTypePortDisconnect
;
4365 std::strncpy(ev
.portDisconnect
.portNameA
, fullNameA
, STR_MAX
);
4366 std::strncpy(ev
.portDisconnect
.portNameB
, fullNameB
, STR_MAX
);
4369 handlePtr
->postponeJackCallback(ev
);
4372 static void JACKBRIDGE_API
carla_jack_port_rename_callback(jack_port_id_t port_id
, const char* oldName
, const char* newName
, void* arg
)
4374 const jack_port_t
* const port
= jackbridge_port_by_id(handlePtr
->fClient
, port_id
);
4375 CARLA_SAFE_ASSERT_RETURN(port
!= nullptr,);
4377 const char* const shortName
= jackbridge_port_short_name(port
);
4378 CARLA_SAFE_ASSERT_RETURN(shortName
!= nullptr && shortName
[0] != '\0',);
4380 PostPonedJackEvent ev
;
4381 carla_zeroStruct(ev
);
4382 ev
.type
= PostPonedJackEvent::kTypePortRename
;
4383 std::strncpy(ev
.portRename
.oldFullName
, oldName
, STR_MAX
);
4384 std::strncpy(ev
.portRename
.newFullName
, newName
, STR_MAX
);
4385 std::strncpy(ev
.portRename
.newShortName
, shortName
, STR_MAX
);
4386 handlePtr
->postponeJackCallback(ev
);
4389 static void carla_jack_property_change_callback(jack_uuid_t subject
, const char* key
, jack_property_change_t change
, void* arg
)
4391 if (change
!= PropertyChanged
)
4393 if (std::strcmp(key
, URI_POSITION
) != 0)
4396 PostPonedJackEvent ev
;
4397 carla_zeroStruct(ev
);
4398 ev
.type
= PostPonedJackEvent::kTypeClientPositionChange
;
4399 ev
.clientPositionChange
.uuid
= subject
;
4400 handlePtr
->postponeJackCallback(ev
);
4403 static int JACKBRIDGE_API
carla_jack_xrun_callback(void* arg
)
4405 ++(handlePtr
->pData
->xruns
);
4410 static void JACKBRIDGE_API
carla_jack_shutdown_callback(void* arg
)
4412 handlePtr
->handleJackShutdownCallback();
4417 // -------------------------------------------------------------------
4419 #ifndef BUILD_BRIDGE
4420 static int JACKBRIDGE_API
carla_jack_process_callback_plugin(jack_nframes_t nframes
, void* arg
) __attribute__((annotate("realtime")))
4422 CarlaPluginPtr
* const pluginPtr
= static_cast<CarlaPluginPtr
*>(arg
);
4423 CARLA_SAFE_ASSERT_RETURN(pluginPtr
!= nullptr, 0);
4425 CarlaPluginPtr plugin
= *pluginPtr
;
4426 CARLA_SAFE_ASSERT_RETURN(plugin
.get() != nullptr && plugin
->isEnabled(), 0);
4428 CarlaEngineJack
* const engine((CarlaEngineJack
*)plugin
->getEngine());
4429 CARLA_SAFE_ASSERT_RETURN(engine
!= nullptr, 0);
4431 if (plugin
->tryLock(engine
->fFreewheel
))
4433 plugin
->initBuffers();
4434 engine
->processPlugin(plugin
, nframes
);
4442 static int JACKBRIDGE_API carla_jack_bufsize_callback_plugin(jack_nframes_t nframes, void* arg)
4444 CarlaPlugin* const plugin((CarlaPlugin*)arg);
4445 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr && plugin->isEnabled(), 0);
4447 plugin->bufferSizeChanged(nframes);
4451 static int JACKBRIDGE_API carla_jack_srate_callback_plugin(jack_nframes_t nframes, void* arg)
4453 CarlaPlugin* const plugin((CarlaPlugin*)arg);
4454 CARLA_SAFE_ASSERT_RETURN(plugin != nullptr && plugin->isEnabled(), 0);
4456 plugin->sampleRateChanged(nframes);
4461 static void JACKBRIDGE_API
carla_jack_latency_callback_plugin(jack_latency_callback_mode_t
/*mode*/, void* /*arg*/)
4466 static void JACKBRIDGE_API
carla_jack_shutdown_callback_plugin(void* arg
)
4468 CarlaPluginPtr
* const pluginPtr
= static_cast<CarlaPluginPtr
*>(arg
);
4469 CARLA_SAFE_ASSERT_RETURN(pluginPtr
!= nullptr,);
4471 CarlaPluginPtr plugin
= *pluginPtr
;
4472 CARLA_SAFE_ASSERT_RETURN(plugin
.get() != nullptr,);
4474 CarlaEngineJack
* const engine((CarlaEngineJack
*)plugin
->getEngine());
4475 CARLA_SAFE_ASSERT_RETURN(engine
!= nullptr,);
4477 engine
->handlePluginJackShutdownCallback(plugin
);
4481 // enable -Wattributes again
4482 #if defined(__clang__)
4483 # pragma clang diagnostic pop
4484 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
4485 # pragma GCC diagnostic pop
4488 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack
)
4491 // -----------------------------------------------------------------------
4493 namespace EngineInit
{
4495 CarlaEngine
* newJack()
4497 carla_debug("EngineInit::newJack()");
4498 return new CarlaEngineJack();
4503 // -----------------------------------------------------------------------
4505 CARLA_BACKEND_END_NAMESPACE
4507 #if defined(JACKBRIDGE_DIRECT) && !defined(BUILD_BRIDGE)
4508 // -----------------------------------------------------------------------
4509 // internal jack client
4512 int jack_initialize(jack_client_t
*client
, const char *load_init
);
4515 void jack_finish(void *arg
);
4517 #ifdef CARLA_OS_UNIX
4518 # include "ThreadSafeFFTW.hpp"
4521 // -----------------------------------------------------------------------
4524 int jack_initialize(jack_client_t
* const client
, const char* const load_init
)
4526 CARLA_BACKEND_USE_NAMESPACE
4528 #ifdef CARLA_OS_UNIX
4529 static const ThreadSafeFFTW sThreadSafeFFTW
;
4532 EngineProcessMode mode
;
4533 if (load_init
!= nullptr && std::strcmp(load_init
, "rack") == 0)
4534 mode
= ENGINE_PROCESS_MODE_CONTINUOUS_RACK
;
4536 mode
= ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS
;
4539 CarlaJUCE::initialiseJuce_GUI();
4542 CarlaEngineJack
* const engine
= new CarlaEngineJack();
4544 engine
->setOption(ENGINE_OPTION_FORCE_STEREO
, 1, nullptr);
4545 engine
->setOption(ENGINE_OPTION_AUDIO_DRIVER
, 0, "JACK");
4546 engine
->setOption(ENGINE_OPTION_AUDIO_DEVICE
, 0, "Auto-Connect ON");
4547 engine
->setOption(ENGINE_OPTION_OSC_ENABLED
, 1, nullptr);
4548 engine
->setOption(ENGINE_OPTION_OSC_PORT_TCP
, 22752, nullptr);
4549 engine
->setOption(ENGINE_OPTION_OSC_PORT_UDP
, 22752, nullptr);
4551 engine
->setOption(ENGINE_OPTION_PROCESS_MODE
, mode
, nullptr);
4552 engine
->setOption(ENGINE_OPTION_TRANSPORT_MODE
, ENGINE_TRANSPORT_MODE_JACK
, nullptr);
4554 #ifdef __MOD_DEVICES__
4555 engine
->setOption(ENGINE_OPTION_FILE_PATH
, FILE_AUDIO
, "/data/user-files/Audio Loops:/data/user-files/Audio Tracks");
4556 engine
->setOption(ENGINE_OPTION_FILE_PATH
, FILE_MIDI
, "/data/user-files/MIDI Songs");
4560 engine
->setOption(ENGINE_OPTION_PATH_BINARIES
, 0, "/usr/lib/carla");
4561 engine
->setOption(ENGINE_OPTION_PATH_RESOURCES
, 0, "/usr/share/resources");
4563 if (engine
->initInternal(client
))
4568 CarlaJUCE::shutdownJuce_GUI();
4574 void jack_finish(void *arg
)
4576 CARLA_BACKEND_USE_NAMESPACE
4578 CarlaEngineJack
* const engine
= (CarlaEngineJack
*)arg
;;
4579 CARLA_SAFE_ASSERT_RETURN(engine
!= nullptr,);
4581 engine
->setAboutToClose();
4582 engine
->removeAllPlugins();
4587 CarlaJUCE::shutdownJuce_GUI();
4591 // -----------------------------------------------------------------------
4592 #endif // defined(JACKBRIDGE_DIRECT) && !defined(BUILD_BRIDGE)