Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1967 lines
64KB

  1. /*
  2. * Carla JACK Engine
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaEngineInternal.hpp"
  18. #include "CarlaBackendUtils.hpp"
  19. #include "jackbridge/JackBridge.hpp"
  20. #include <cmath>
  21. #include <QtCore/QStringList>
  22. #define URI_CANVAS_ICON "http://kxstudio.sf.net/ns/canvas/icon"
  23. CARLA_BACKEND_START_NAMESPACE
  24. #if 0
  25. } // Fix editor indentation
  26. #endif
  27. class CarlaEngineJack;
  28. // -----------------------------------------------------------------------
  29. // Fallback data
  30. static const EngineEvent kFallbackJackEngineEvent = { kEngineEventTypeNull, 0, 0, { kEngineControlEventTypeNull, 0, 0.0f } };
  31. // -----------------------------------------------------------------------
  32. // Carla Engine JACK-Audio port
  33. class CarlaEngineJackAudioPort : public CarlaEngineAudioPort
  34. {
  35. public:
  36. CarlaEngineJackAudioPort(const CarlaEngine& engine, const bool isInput, jack_client_t* const client, jack_port_t* const port)
  37. : CarlaEngineAudioPort(engine, isInput),
  38. fClient(client),
  39. fPort(port)
  40. {
  41. carla_debug("CarlaEngineJackAudioPort::CarlaEngineJackAudioPort(%s, %p, %p)", bool2str(isInput), client, port);
  42. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  43. {
  44. CARLA_ASSERT(client != nullptr && port != nullptr);
  45. }
  46. else
  47. {
  48. CARLA_ASSERT(client == nullptr && port == nullptr);
  49. }
  50. }
  51. ~CarlaEngineJackAudioPort() override
  52. {
  53. carla_debug("CarlaEngineJackAudioPort::~CarlaEngineJackAudioPort()");
  54. if (fClient != nullptr && fPort != nullptr)
  55. {
  56. jackbridge_port_unregister(fClient, fPort);
  57. fClient = nullptr;
  58. fPort = nullptr;
  59. }
  60. }
  61. void initBuffer() override
  62. {
  63. if (fPort == nullptr)
  64. return CarlaEngineAudioPort::initBuffer();
  65. const uint32_t bufferSize(fEngine.getBufferSize());
  66. fBuffer = (float*)jackbridge_port_get_buffer(fPort, bufferSize);
  67. if (! fIsInput)
  68. FLOAT_CLEAR(fBuffer, bufferSize);
  69. }
  70. private:
  71. jack_client_t* fClient;
  72. jack_port_t* fPort;
  73. friend class CarlaEngineJack;
  74. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort)
  75. };
  76. // -----------------------------------------------------------------------
  77. // Carla Engine JACK-CV port
  78. class CarlaEngineJackCVPort : public CarlaEngineCVPort
  79. {
  80. public:
  81. CarlaEngineJackCVPort(const CarlaEngine& engine, const bool isInput, jack_client_t* const client, jack_port_t* const port)
  82. : CarlaEngineCVPort(engine, isInput),
  83. fClient(client),
  84. fPort(port)
  85. {
  86. carla_debug("CarlaEngineJackCVPort::CarlaEngineJackCVPort(%s, %p, %p)", bool2str(isInput), client, port);
  87. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  88. {
  89. CARLA_ASSERT(client != nullptr && port != nullptr);
  90. }
  91. else
  92. {
  93. CARLA_ASSERT(client == nullptr && port == nullptr);
  94. }
  95. }
  96. ~CarlaEngineJackCVPort() override
  97. {
  98. carla_debug("CarlaEngineJackCVPort::~CarlaEngineJackCVPort()");
  99. if (fClient != nullptr && fPort != nullptr)
  100. {
  101. jackbridge_port_unregister(fClient, fPort);
  102. fClient = nullptr;
  103. fPort = nullptr;
  104. }
  105. }
  106. void initBuffer() override
  107. {
  108. if (fPort == nullptr)
  109. return CarlaEngineCVPort::initBuffer();
  110. const uint32_t bufferSize(fEngine.getBufferSize());
  111. fBuffer = (float*)jackbridge_port_get_buffer(fPort, bufferSize);
  112. if (! fIsInput)
  113. FLOAT_CLEAR(fBuffer, bufferSize);
  114. }
  115. private:
  116. jack_client_t* fClient;
  117. jack_port_t* fPort;
  118. friend class CarlaEngineJack;
  119. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackCVPort)
  120. };
  121. // -----------------------------------------------------------------------
  122. // Carla Engine JACK-Event port
  123. class CarlaEngineJackEventPort : public CarlaEngineEventPort
  124. {
  125. public:
  126. CarlaEngineJackEventPort(const CarlaEngine& engine, const bool isInput, jack_client_t* const client, jack_port_t* const port)
  127. : CarlaEngineEventPort(engine, isInput),
  128. fClient(client),
  129. fPort(port),
  130. fJackBuffer(nullptr)
  131. {
  132. carla_debug("CarlaEngineJackEventPort::CarlaEngineJackEventPort(%s, %p, %p)", bool2str(isInput), client, port);
  133. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  134. {
  135. CARLA_ASSERT(client != nullptr && port != nullptr);
  136. }
  137. else
  138. {
  139. CARLA_ASSERT(client == nullptr && port == nullptr);
  140. }
  141. }
  142. ~CarlaEngineJackEventPort() override
  143. {
  144. carla_debug("CarlaEngineJackEventPort::~CarlaEngineJackEventPort()");
  145. if (fClient != nullptr && fPort != nullptr)
  146. {
  147. jackbridge_port_unregister(fClient, fPort);
  148. fClient = nullptr;
  149. fPort = nullptr;
  150. }
  151. }
  152. void initBuffer() override
  153. {
  154. if (fPort == nullptr)
  155. return CarlaEngineEventPort::initBuffer();
  156. fJackBuffer = jackbridge_port_get_buffer(fPort, fEngine.getBufferSize());
  157. if (! fIsInput)
  158. jackbridge_midi_clear_buffer(fJackBuffer);
  159. }
  160. uint32_t getEventCount() const override
  161. {
  162. if (fPort == nullptr)
  163. return CarlaEngineEventPort::getEventCount();
  164. CARLA_SAFE_ASSERT_RETURN(fIsInput, 0);
  165. CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, 0);
  166. return jackbridge_midi_get_event_count(fJackBuffer);
  167. }
  168. const EngineEvent& getEvent(const uint32_t index) override
  169. {
  170. if (fPort == nullptr)
  171. return CarlaEngineEventPort::getEvent(index);
  172. CARLA_SAFE_ASSERT_RETURN(fIsInput, kFallbackJackEngineEvent);
  173. CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, kFallbackJackEngineEvent);
  174. return getEventUnchecked(index);
  175. }
  176. const EngineEvent& getEventUnchecked(const uint32_t index) override
  177. {
  178. jack_midi_event_t jackEvent;
  179. if (! jackbridge_midi_event_get(&jackEvent, fJackBuffer, index))
  180. return kFallbackJackEngineEvent;
  181. CARLA_SAFE_ASSERT_RETURN(jackEvent.size <= 0xFF /* uint8_t max */, kFallbackJackEngineEvent);
  182. fRetEvent.time = jackEvent.time;
  183. fRetEvent.fillFromMidiData(static_cast<uint8_t>(jackEvent.size), jackEvent.buffer);
  184. return fRetEvent;
  185. }
  186. bool writeControlEvent(const uint32_t time, const uint8_t channel, const EngineControlEventType type, const uint16_t param, const float value) override
  187. {
  188. if (fPort == nullptr)
  189. return CarlaEngineEventPort::writeControlEvent(time, channel, type, param, value);
  190. CARLA_SAFE_ASSERT_RETURN(! fIsInput, false);
  191. CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, false);
  192. CARLA_SAFE_ASSERT_RETURN(type != kEngineControlEventTypeNull, false);
  193. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  194. CARLA_SAFE_ASSERT_RETURN(param < 0x5F, false);
  195. CARLA_SAFE_ASSERT(value >= 0.0f && value <= 1.0f);
  196. if (type == kEngineControlEventTypeParameter) {
  197. CARLA_SAFE_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(param));
  198. }
  199. uint8_t size = 0;
  200. uint8_t data[3] = { 0, 0, 0 };
  201. EngineControlEvent ctrlEvent = { type, param, carla_fixValue<float>(0.0f, 1.0f, value) };
  202. ctrlEvent.dumpToMidiData(channel, size, data);
  203. if (size == 0)
  204. return false;
  205. return jackbridge_midi_event_write(fJackBuffer, time, data, size);
  206. }
  207. bool writeMidiEvent(const uint32_t time, const uint8_t channel, const uint8_t port, const uint8_t size, const uint8_t* const data) override
  208. {
  209. if (fPort == nullptr)
  210. return CarlaEngineEventPort::writeMidiEvent(time, channel, port, size, data);
  211. CARLA_SAFE_ASSERT_RETURN(! fIsInput, false);
  212. CARLA_SAFE_ASSERT_RETURN(fJackBuffer != nullptr, false);
  213. CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false);
  214. CARLA_SAFE_ASSERT_RETURN(size > 0, false);
  215. CARLA_SAFE_ASSERT_RETURN(data != nullptr, false);
  216. jack_midi_data_t jdata[size];
  217. jdata[0] = static_cast<jack_midi_data_t>(MIDI_GET_STATUS_FROM_DATA(data) + channel);
  218. for (uint8_t i=1; i < size; ++i)
  219. jdata[i] = data[i];
  220. return jackbridge_midi_event_write(fJackBuffer, time, jdata, size);
  221. }
  222. private:
  223. jack_client_t* fClient;
  224. jack_port_t* fPort;
  225. void* fJackBuffer;
  226. EngineEvent fRetEvent;
  227. friend class CarlaEngineJack;
  228. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackEventPort)
  229. };
  230. // -----------------------------------------------------------------------
  231. // Jack Engine client
  232. class CarlaEngineJackClient : public CarlaEngineClient
  233. {
  234. public:
  235. CarlaEngineJackClient(const CarlaEngine& engine, jack_client_t* const client)
  236. : CarlaEngineClient(engine),
  237. fClient(client),
  238. fUseClient(engine.getProccessMode() == ENGINE_PROCESS_MODE_SINGLE_CLIENT || engine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  239. {
  240. carla_debug("CarlaEngineJackClient::CarlaEngineJackClient(%p)", client);
  241. if (fUseClient)
  242. {
  243. CARLA_ASSERT(fClient != nullptr);
  244. }
  245. else
  246. {
  247. CARLA_ASSERT(fClient == nullptr);
  248. }
  249. }
  250. ~CarlaEngineJackClient() override
  251. {
  252. carla_debug("CarlaEngineClient::~CarlaEngineClient()");
  253. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS && fClient != nullptr)
  254. jackbridge_client_close(fClient);
  255. }
  256. void activate() override
  257. {
  258. carla_debug("CarlaEngineJackClient::activate()");
  259. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  260. {
  261. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr && ! fActive,);
  262. jackbridge_activate(fClient);
  263. }
  264. CarlaEngineClient::activate();
  265. }
  266. void deactivate() override
  267. {
  268. carla_debug("CarlaEngineJackClient::deactivate()");
  269. if (fEngine.getProccessMode() == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  270. {
  271. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr && fActive,);
  272. jackbridge_deactivate(fClient);
  273. }
  274. CarlaEngineClient::deactivate();
  275. }
  276. bool isOk() const noexcept override
  277. {
  278. if (fUseClient)
  279. return (fClient != nullptr);
  280. return CarlaEngineClient::isOk();
  281. }
  282. #if 0
  283. void setLatency(const uint32_t samples) noexcept override
  284. {
  285. CarlaEngineClient::setLatency(samples);
  286. if (fUseClient && fClient != nullptr)
  287. {
  288. // try etc
  289. jackbridge_recompute_total_latencies(fClient);
  290. }
  291. }
  292. #endif
  293. CarlaEnginePort* addPort(const EnginePortType portType, const char* const name, const bool isInput) override
  294. {
  295. carla_debug("CarlaEngineJackClient::addPort(%s, \"%s\", %s)", EnginePortType2Str(portType), name, bool2str(isInput));
  296. jack_port_t* port = nullptr;
  297. // Create JACK port first, if needed
  298. if (fUseClient && fClient != nullptr)
  299. {
  300. switch (portType)
  301. {
  302. case kEnginePortTypeNull:
  303. break;
  304. case kEnginePortTypeAudio:
  305. port = jackbridge_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0);
  306. break;
  307. case kEnginePortTypeCV:
  308. port = jackbridge_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsControlVoltage | (isInput ? JackPortIsInput : JackPortIsOutput), 0);
  309. break;
  310. case kEnginePortTypeEvent:
  311. port = jackbridge_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0);
  312. break;
  313. }
  314. }
  315. // Create Engine port
  316. switch (portType)
  317. {
  318. case kEnginePortTypeNull:
  319. break;
  320. case kEnginePortTypeAudio:
  321. return new CarlaEngineJackAudioPort(fEngine, isInput, fClient, port);
  322. case kEnginePortTypeCV:
  323. return new CarlaEngineJackCVPort(fEngine, isInput, fClient, port);
  324. case kEnginePortTypeEvent:
  325. return new CarlaEngineJackEventPort(fEngine, isInput, fClient, port);
  326. }
  327. carla_stderr("CarlaEngineJackClient::addPort(%s, \"%s\", %s) - invalid type", EnginePortType2Str(portType), name, bool2str(isInput));
  328. return nullptr;
  329. }
  330. private:
  331. jack_client_t* fClient;
  332. const bool fUseClient;
  333. friend class CarlaEngineJack;
  334. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient)
  335. };
  336. // -----------------------------------------------------------------------
  337. // Jack Engine
  338. class CarlaEngineJack : public CarlaEngine
  339. {
  340. public:
  341. CarlaEngineJack()
  342. : CarlaEngine(),
  343. fClient(nullptr),
  344. fTransportState(JackTransportStopped),
  345. fFreewheel(false),
  346. #ifdef BUILD_BRIDGE
  347. fIsRunning(false)
  348. #else
  349. fLastGroupId(0),
  350. fLastPortId(0),
  351. fLastConnectionId(0)
  352. #endif
  353. {
  354. carla_debug("CarlaEngineJack::CarlaEngineJack()");
  355. #ifdef BUILD_BRIDGE
  356. pData->options.processMode = ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS;
  357. #else
  358. carla_fill<jack_port_t*>(fRackPorts, kRackPortCount, nullptr);
  359. #endif
  360. // FIXME: Always enable JACK transport for now
  361. pData->options.transportMode = ENGINE_TRANSPORT_MODE_JACK;
  362. carla_zeroStruct<jack_position_t>(fTransportPos);
  363. }
  364. ~CarlaEngineJack() override
  365. {
  366. carla_debug("CarlaEngineJack::~CarlaEngineJack()");
  367. CARLA_ASSERT(fClient == nullptr);
  368. #ifndef BUILD_BRIDGE
  369. fUsedGroupNames.clear();
  370. fUsedPortNames.clear();
  371. fUsedConnections.clear();
  372. //fGroupIconsChanged.clear();
  373. #endif
  374. }
  375. // -------------------------------------------------------------------
  376. // Maximum values
  377. unsigned int getMaxClientNameSize() const noexcept override
  378. {
  379. if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT || pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  380. {
  381. unsigned int ret = 0;
  382. try {
  383. ret = static_cast<unsigned int>(jackbridge_client_name_size());
  384. }
  385. catch (...) {}
  386. return ret;
  387. }
  388. return CarlaEngine::getMaxClientNameSize();
  389. }
  390. unsigned int getMaxPortNameSize() const noexcept override
  391. {
  392. if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT || pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  393. {
  394. unsigned int ret = 0;
  395. try {
  396. ret = static_cast<unsigned int>(jackbridge_port_name_size());
  397. }
  398. catch (...) {}
  399. return ret;
  400. }
  401. return CarlaEngine::getMaxPortNameSize();
  402. }
  403. // -------------------------------------------------------------------
  404. // Virtual, per-engine type calls
  405. bool init(const char* const clientName) override
  406. {
  407. carla_debug("CarlaEngineJack::init(\"%s\")", clientName);
  408. fFreewheel = false;
  409. fTransportState = JackTransportStopped;
  410. carla_zeroStruct<jack_position_t>(fTransportPos);
  411. #ifdef BUILD_BRIDGE
  412. if (pData->bufferSize == 0 || pData->sampleRate == 0.0)
  413. {
  414. // open temp client to get initial buffer-size and sample-rate values
  415. if (jack_client_t* tmpClient = jackbridge_client_open(clientName, JackNullOption, nullptr))
  416. {
  417. pData->bufferSize = jackbridge_get_buffer_size(tmpClient);
  418. pData->sampleRate = jackbridge_get_sample_rate(tmpClient);
  419. jackbridge_client_close(tmpClient);
  420. }
  421. }
  422. fIsRunning = true;
  423. return CarlaEngine::init(clientName);
  424. #else
  425. fLastGroupId = 0;
  426. fLastPortId = 0;
  427. fLastConnectionId = 0;
  428. fUsedGroupNames.clear();
  429. fUsedPortNames.clear();
  430. fUsedConnections.clear();
  431. //fGroupIconsChanged.clear();
  432. fClient = jackbridge_client_open(clientName, JackNullOption, nullptr);
  433. if (fClient != nullptr)
  434. {
  435. pData->bufferSize = jackbridge_get_buffer_size(fClient);
  436. pData->sampleRate = jackbridge_get_sample_rate(fClient);
  437. //jackbridge_custom_publish_data(fClient, URI_CANVAS_ICON, "carla", 6);
  438. //jackbridge_custom_set_data_appearance_callback(fClient, carla_jack_custom_appearance_callback, this);
  439. jackbridge_set_buffer_size_callback(fClient, carla_jack_bufsize_callback, this);
  440. jackbridge_set_sample_rate_callback(fClient, carla_jack_srate_callback, this);
  441. jackbridge_set_freewheel_callback(fClient, carla_jack_freewheel_callback, this);
  442. //jackbridge_set_latency_callback(fClient, carla_jack_latency_callback, this);
  443. jackbridge_set_process_callback(fClient, carla_jack_process_callback, this);
  444. jackbridge_on_shutdown(fClient, carla_jack_shutdown_callback, this);
  445. const char* const jackClientName(jackbridge_get_client_name(fClient));
  446. initJackPatchbay(jackClientName);
  447. jackbridge_set_client_registration_callback(fClient, carla_jack_client_registration_callback, this);
  448. jackbridge_set_port_registration_callback(fClient, carla_jack_port_registration_callback, this);
  449. jackbridge_set_port_connect_callback(fClient, carla_jack_port_connect_callback, this);
  450. jackbridge_set_port_rename_callback(fClient, carla_jack_port_rename_callback, this);
  451. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  452. {
  453. fRackPorts[kRackPortAudioIn1] = jackbridge_port_register(fClient, "audio-in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
  454. fRackPorts[kRackPortAudioIn2] = jackbridge_port_register(fClient, "audio-in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
  455. fRackPorts[kRackPortAudioOut1] = jackbridge_port_register(fClient, "audio-out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  456. fRackPorts[kRackPortAudioOut2] = jackbridge_port_register(fClient, "audio-out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
  457. fRackPorts[kRackPortEventIn] = jackbridge_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
  458. fRackPorts[kRackPortEventOut] = jackbridge_port_register(fClient, "events-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
  459. }
  460. if (jackbridge_activate(fClient))
  461. {
  462. CarlaEngine::init(jackClientName);
  463. return true;
  464. }
  465. else
  466. {
  467. setLastError("Failed to activate the JACK client");
  468. jackbridge_client_close(fClient);
  469. fClient = nullptr;
  470. }
  471. }
  472. else
  473. setLastError("Failed to create new JACK client");
  474. return false;
  475. #endif
  476. }
  477. bool close() override
  478. {
  479. carla_debug("CarlaEngineJack::close()");
  480. CarlaEngine::close();
  481. #ifdef BUILD_BRIDGE
  482. fClient = nullptr;
  483. fIsRunning = false;
  484. return true;
  485. #else
  486. if (jackbridge_deactivate(fClient))
  487. {
  488. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  489. {
  490. jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn1]);
  491. jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioIn2]);
  492. jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut1]);
  493. jackbridge_port_unregister(fClient, fRackPorts[kRackPortAudioOut2]);
  494. jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventIn]);
  495. jackbridge_port_unregister(fClient, fRackPorts[kRackPortEventOut]);
  496. carla_fill<jack_port_t*>(fRackPorts, kRackPortCount, nullptr);
  497. }
  498. if (jackbridge_client_close(fClient))
  499. {
  500. fClient = nullptr;
  501. return true;
  502. }
  503. else
  504. setLastError("Failed to close the JACK client");
  505. }
  506. else
  507. setLastError("Failed to deactivate the JACK client");
  508. fClient = nullptr;
  509. fUsedGroupNames.clear();
  510. fUsedPortNames.clear();
  511. fUsedConnections.clear();
  512. //fGroupIconsChanged.clear();
  513. return false;
  514. #endif
  515. }
  516. #if 0 //ndef BUILD_BRIDGE
  517. void idle() override
  518. {
  519. CarlaEngine::idle();
  520. if (fGroupIconsChanged.count() == 0)
  521. return;
  522. static bool checkIcons = false;
  523. if (! checkIcons)
  524. {
  525. checkIcons = true; // check them next time
  526. return;
  527. }
  528. checkIcons = false;
  529. void* data;
  530. size_t dataSize;
  531. List<int> groupIconsCopy;
  532. fGroupIconsChanged.spliceAppend(groupIconsCopy, true);
  533. for (List<int>::Itenerator it = groupIconsCopy.begin(); it.valid(); it.next())
  534. {
  535. const int& groupId(*it);
  536. const char* const groupName(getGroupName(groupId));
  537. data = nullptr;
  538. dataSize = 0;
  539. if (jackbridge_custom_get_data(fClient, groupName, URI_CANVAS_ICON, &data, &dataSize) && data != nullptr && dataSize != 0)
  540. {
  541. const char* const icon((const char*)data);
  542. CARLA_ASSERT(std::strlen(icon)+1 == dataSize);
  543. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ICON_CHANGED, 0, groupId, 0, 0.0f, icon);
  544. jackbridge_free(data);
  545. }
  546. }
  547. groupIconsCopy.clear();
  548. }
  549. #endif
  550. bool isRunning() const noexcept override
  551. {
  552. #ifdef BUILD_BRIDGE
  553. return (fClient != nullptr || fIsRunning);
  554. #else
  555. return (fClient != nullptr);
  556. #endif
  557. }
  558. bool isOffline() const noexcept override
  559. {
  560. return fFreewheel;
  561. }
  562. EngineType getType() const noexcept override
  563. {
  564. return kEngineTypeJack;
  565. }
  566. const char* getCurrentDriverName() const noexcept override
  567. {
  568. return "JACK";
  569. }
  570. CarlaEngineClient* addClient(CarlaPlugin* const plugin) override
  571. {
  572. //const char* const iconName(plugin->getIconName());
  573. jack_client_t* client = nullptr;
  574. #ifdef BUILD_BRIDGE
  575. client = fClient = jackbridge_client_open(plugin->getName(), JackNullOption, nullptr);
  576. CARLA_SAFE_ASSERT_RETURN(client != nullptr, nullptr);
  577. pData->bufferSize = jackbridge_get_buffer_size(client);
  578. pData->sampleRate = jackbridge_get_sample_rate(client);
  579. //jackbridge_custom_publish_data(client, URI_CANVAS_ICON, iconName, std::strlen(iconName)+1);
  580. jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this);
  581. jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this);
  582. jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this);
  583. //jackbridge_set_latency_callback(client, carla_jack_latency_callback, this);
  584. jackbridge_set_process_callback(client, carla_jack_process_callback, this);
  585. jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this);
  586. #else
  587. if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  588. {
  589. client = fClient;
  590. }
  591. else if (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  592. {
  593. client = jackbridge_client_open(plugin->getName(), JackNullOption, nullptr);
  594. CARLA_SAFE_ASSERT_RETURN(client != nullptr, nullptr);
  595. //jackbridge_custom_publish_data(client, URI_CANVAS_ICON, iconName, std::strlen(iconName)+1);
  596. //jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin);
  597. jackbridge_set_process_callback(client, carla_jack_process_callback_plugin, plugin);
  598. }
  599. #endif
  600. return new CarlaEngineJackClient(*this, client);
  601. }
  602. #ifndef BUILD_BRIDGE
  603. const char* renamePlugin(const unsigned int id, const char* const newName) override
  604. {
  605. CARLA_SAFE_ASSERT_RETURN(pData->curPluginCount > 0, nullptr);
  606. CARLA_SAFE_ASSERT_RETURN(id < pData->curPluginCount, nullptr);
  607. CARLA_SAFE_ASSERT_RETURN(pData->plugins != nullptr, nullptr);
  608. CARLA_SAFE_ASSERT_RETURN(newName != nullptr && newName[0] != '\0', nullptr);
  609. CarlaPlugin* const plugin(pData->plugins[id].plugin);
  610. if (plugin == nullptr)
  611. {
  612. carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id);
  613. return nullptr;
  614. }
  615. CARLA_SAFE_ASSERT(plugin->getId() == id);
  616. bool needsReinit = (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT);
  617. const char* name = getUniquePluginName(newName);
  618. // TODO - use rename port if single-client and JACK2
  619. // JACK client rename
  620. if (pData->options.processMode == ENGINE_PROCESS_MODE_MULTIPLE_CLIENTS)
  621. {
  622. CarlaEngineJackClient* const client((CarlaEngineJackClient*)plugin->getEngineClient());
  623. #if 0
  624. if (bridge.client_rename_ptr != nullptr)
  625. {
  626. name = bridge.client_rename_ptr(client->fClient, name);
  627. }
  628. else
  629. #endif
  630. {
  631. // we should not be able to do this, jack really needs to allow client rename
  632. needsReinit = true;
  633. if (jack_client_t* const jclient = jackbridge_client_open(name, JackNullOption, nullptr))
  634. {
  635. //const char* const iconName(plugin->getIconName());
  636. //jackbridge_custom_publish_data(jclient, URI_CANVAS_ICON, iconName, std::strlen(iconName)+1);
  637. // close old client
  638. plugin->setEnabled(false);
  639. if (client->isActive())
  640. client->deactivate();
  641. plugin->clearBuffers();
  642. jackbridge_client_close(client->fClient);
  643. // set new client data
  644. name = jackbridge_get_client_name(jclient);
  645. jackbridge_set_process_callback(jclient, carla_jack_process_callback_plugin, plugin);
  646. //jackbridge_set_latency_callback(jclient, carla_jack_latency_callback_plugin, plugin);
  647. client->fClient = jclient;
  648. }
  649. }
  650. }
  651. if (name == nullptr)
  652. return nullptr;
  653. // Rename
  654. plugin->setName(name);
  655. if (needsReinit)
  656. {
  657. // reload plugin to recreate its ports
  658. const SaveState& saveState(plugin->getSaveState());
  659. plugin->reload();
  660. plugin->loadSaveState(saveState);
  661. }
  662. return name;
  663. }
  664. // -------------------------------------------------------------------
  665. // Patchbay
  666. bool patchbayConnect(int portA, int portB) override
  667. {
  668. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false);
  669. if (fClient == nullptr)
  670. {
  671. setLastError("Invalid JACK client");
  672. return false;
  673. }
  674. char portNameA[STR_MAX+1];
  675. char portNameB[STR_MAX+1];
  676. getFullPortName(portA, portNameA);
  677. getFullPortName(portB, portNameB);
  678. if (! jackbridge_connect(fClient, portNameA, portNameB))
  679. {
  680. setLastError("JACK operation failed");
  681. return false;
  682. }
  683. return true;
  684. }
  685. bool patchbayDisconnect(int connectionId) override
  686. {
  687. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false);
  688. for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.begin(); it.valid(); it.next())
  689. {
  690. const ConnectionToId& connectionToId(it.getValue());
  691. if (connectionToId.id == connectionId)
  692. {
  693. char portNameOut[STR_MAX+1];
  694. char portNameIn[STR_MAX+1];
  695. getFullPortName(connectionToId.portOut, portNameOut);
  696. getFullPortName(connectionToId.portIn, portNameIn);
  697. if (! jackbridge_disconnect(fClient, portNameOut, portNameIn))
  698. {
  699. setLastError("JACK operation failed");
  700. return false;
  701. }
  702. return true;
  703. }
  704. }
  705. setLastError("Failed to find the requested connection");
  706. return false;
  707. }
  708. bool patchbayRefresh() override
  709. {
  710. CARLA_SAFE_ASSERT_RETURN(fClient != nullptr, false);
  711. fLastGroupId = 0;
  712. fLastPortId = 0;
  713. fLastConnectionId = 0;
  714. fUsedGroupNames.clear();
  715. fUsedPortNames.clear();
  716. fUsedConnections.clear();
  717. //fGroupIconsChanged.clear();
  718. initJackPatchbay(jackbridge_get_client_name(fClient));
  719. return true;
  720. }
  721. // -------------------------------------------------------------------
  722. // Transport
  723. void transportPlay() override
  724. {
  725. if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  726. CarlaEngine::transportPlay();
  727. else if (fClient != nullptr)
  728. jackbridge_transport_start(fClient);
  729. }
  730. void transportPause() override
  731. {
  732. if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  733. CarlaEngine::transportPause();
  734. else if (fClient != nullptr)
  735. jackbridge_transport_stop(fClient);
  736. }
  737. void transportRelocate(const uint64_t frame) override
  738. {
  739. if (pData->options.transportMode == ENGINE_TRANSPORT_MODE_INTERNAL)
  740. CarlaEngine::transportRelocate(frame);
  741. else if (fClient != nullptr)
  742. jackbridge_transport_locate(fClient, static_cast<jack_nframes_t>(frame));
  743. }
  744. #endif
  745. // -------------------------------------------------------------------
  746. protected:
  747. void handleJackBufferSizeCallback(const uint32_t newBufferSize)
  748. {
  749. if (pData->bufferSize == newBufferSize)
  750. return;
  751. pData->bufferSize = newBufferSize;
  752. bufferSizeChanged(newBufferSize);
  753. }
  754. void handleJackSampleRateCallback(const double newSampleRate)
  755. {
  756. if (pData->sampleRate == newSampleRate)
  757. return;
  758. pData->sampleRate = newSampleRate;
  759. sampleRateChanged(newSampleRate);
  760. }
  761. void handleJackFreewheelCallback(const bool isFreewheel)
  762. {
  763. if (fFreewheel == isFreewheel)
  764. return;
  765. fFreewheel = isFreewheel;
  766. offlineModeChanged(isFreewheel);
  767. }
  768. void saveTransportInfo()
  769. {
  770. if (pData->options.transportMode != ENGINE_TRANSPORT_MODE_JACK)
  771. return;
  772. fTransportPos.unique_1 = fTransportPos.unique_2 + 1; // invalidate
  773. fTransportState = jackbridge_transport_query(fClient, &fTransportPos);
  774. pData->timeInfo.playing = (fTransportState == JackTransportRolling);
  775. if (fTransportPos.unique_1 == fTransportPos.unique_2)
  776. {
  777. pData->timeInfo.frame = fTransportPos.frame;
  778. pData->timeInfo.usecs = fTransportPos.usecs;
  779. if (fTransportPos.valid & JackPositionBBT)
  780. {
  781. pData->timeInfo.valid = EngineTimeInfo::kValidBBT;
  782. pData->timeInfo.bbt.bar = fTransportPos.bar;
  783. pData->timeInfo.bbt.beat = fTransportPos.beat;
  784. pData->timeInfo.bbt.tick = fTransportPos.tick;
  785. pData->timeInfo.bbt.barStartTick = fTransportPos.bar_start_tick;
  786. pData->timeInfo.bbt.beatsPerBar = fTransportPos.beats_per_bar;
  787. pData->timeInfo.bbt.beatType = fTransportPos.beat_type;
  788. pData->timeInfo.bbt.ticksPerBeat = fTransportPos.ticks_per_beat;
  789. pData->timeInfo.bbt.beatsPerMinute = fTransportPos.beats_per_minute;
  790. }
  791. else
  792. pData->timeInfo.valid = 0x0;
  793. }
  794. else
  795. {
  796. pData->timeInfo.frame = 0;
  797. pData->timeInfo.valid = 0x0;
  798. }
  799. }
  800. void handleJackProcessCallback(const uint32_t nframes)
  801. {
  802. saveTransportInfo();
  803. if (pData->curPluginCount == 0)
  804. {
  805. #ifndef BUILD_BRIDGE
  806. // pass-through
  807. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  808. {
  809. float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes);
  810. float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes);
  811. float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut1], nframes);
  812. float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut2], nframes);
  813. void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes);
  814. FLOAT_COPY(audioOut1, audioIn1, nframes);
  815. FLOAT_COPY(audioOut2, audioIn2, nframes);
  816. jackbridge_midi_clear_buffer(eventOut);
  817. }
  818. #endif
  819. return runPendingRtEvents();
  820. }
  821. #ifdef BUILD_BRIDGE
  822. CarlaPlugin* const plugin(pData->plugins[0].plugin);
  823. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(fFreewheel))
  824. {
  825. plugin->initBuffers();
  826. processPlugin(plugin, nframes);
  827. plugin->unlock();
  828. }
  829. return runPendingRtEvents();
  830. #else
  831. if (pData->options.processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  832. {
  833. for (unsigned int i=0; i < pData->curPluginCount; ++i)
  834. {
  835. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  836. if (plugin != nullptr && plugin->isEnabled() && plugin->tryLock(fFreewheel))
  837. {
  838. plugin->initBuffers();
  839. processPlugin(plugin, nframes);
  840. plugin->unlock();
  841. }
  842. }
  843. return runPendingRtEvents();
  844. }
  845. if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
  846. {
  847. // get buffers from jack
  848. float* const audioIn1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn1], nframes);
  849. float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioIn2], nframes);
  850. float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut1], nframes);
  851. float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[kRackPortAudioOut2], nframes);
  852. void* const eventIn = jackbridge_port_get_buffer(fRackPorts[kRackPortEventIn], nframes);
  853. void* const eventOut = jackbridge_port_get_buffer(fRackPorts[kRackPortEventOut], nframes);
  854. // assert buffers
  855. CARLA_ASSERT(audioIn1 != nullptr);
  856. CARLA_ASSERT(audioIn2 != nullptr);
  857. CARLA_ASSERT(audioOut1 != nullptr);
  858. CARLA_ASSERT(audioOut2 != nullptr);
  859. CARLA_ASSERT(eventIn != nullptr);
  860. CARLA_ASSERT(eventOut != nullptr);
  861. // create audio buffers
  862. float* inBuf[2] = { audioIn1, audioIn2 };
  863. float* outBuf[2] = { audioOut1, audioOut2 };
  864. // initialize input events
  865. carla_zeroStruct<EngineEvent>(pData->bufEvents.in, kEngineMaxInternalEventCount);
  866. {
  867. uint32_t engineEventIndex = 0;
  868. jack_midi_event_t jackEvent;
  869. const uint32_t jackEventCount(jackbridge_midi_get_event_count(eventIn));
  870. for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; ++jackEventIndex)
  871. {
  872. if (! jackbridge_midi_event_get(&jackEvent, eventIn, jackEventIndex))
  873. continue;
  874. CARLA_SAFE_ASSERT_CONTINUE(jackEvent.size <= 0xFF /* uint8_t max */);
  875. EngineEvent& engineEvent(pData->bufEvents.in[engineEventIndex++]);
  876. engineEvent.time = jackEvent.time;
  877. engineEvent.fillFromMidiData(static_cast<uint8_t>(jackEvent.size), jackEvent.buffer);
  878. if (engineEventIndex >= kEngineMaxInternalEventCount)
  879. break;
  880. }
  881. }
  882. // process rack
  883. pData->processRack(inBuf, outBuf, nframes, fFreewheel);
  884. // output control
  885. {
  886. jackbridge_midi_clear_buffer(eventOut);
  887. for (unsigned short i=0; i < kEngineMaxInternalEventCount; ++i)
  888. {
  889. const EngineEvent& engineEvent(pData->bufEvents.out[i]);
  890. uint8_t size = 0;
  891. uint8_t data[3] = { 0, 0, 0 };
  892. const uint8_t* dataPtr = data;
  893. switch (engineEvent.type)
  894. {
  895. case kEngineEventTypeNull:
  896. break;
  897. case kEngineEventTypeControl:
  898. {
  899. const EngineControlEvent& ctrlEvent(engineEvent.ctrl);
  900. ctrlEvent.dumpToMidiData(engineEvent.channel, size, data);
  901. break;
  902. }
  903. case kEngineEventTypeMidi:
  904. {
  905. const EngineMidiEvent& midiEvent(engineEvent.midi);
  906. size = midiEvent.size;
  907. if (size > EngineMidiEvent::kDataSize && midiEvent.dataExt != nullptr)
  908. dataPtr = midiEvent.dataExt;
  909. else
  910. dataPtr = midiEvent.dataExt;
  911. break;
  912. }
  913. }
  914. if (size > 0)
  915. jackbridge_midi_event_write(eventOut, engineEvent.time, dataPtr, size);
  916. }
  917. }
  918. return runPendingRtEvents();
  919. }
  920. #endif // ! BUILD_BRIDGE
  921. runPendingRtEvents();
  922. }
  923. #if 0
  924. void handleJackLatencyCallback(const jack_latency_callback_mode_t mode)
  925. {
  926. if (pData->options.processMode != ENGINE_PROCESS_MODE_SINGLE_CLIENT)
  927. return;
  928. for (unsigned int i=0; i < pData->curPluginCount; ++i)
  929. {
  930. CarlaPlugin* const plugin(pData->plugins[i].plugin);
  931. if (plugin != nullptr && plugin->isEnabled())
  932. latencyPlugin(plugin, mode);
  933. }
  934. }
  935. #endif
  936. #ifndef BUILD_BRIDGE
  937. # if 0
  938. void handleCustomAppearanceCallback(const char* client_name, const char* key, jack_custom_change_t change)
  939. {
  940. if ((change == JackCustomAdded || change == JackCustomReplaced) && std::strcmp(key, URI_CANVAS_ICON) == 0)
  941. {
  942. const int groupId (getGroupId(client_name));
  943. if (groupId == -1)
  944. return;
  945. fGroupIconsChanged.append(groupId);
  946. }
  947. }
  948. # endif
  949. void handleJackClientRegistrationCallback(const char* const name, const bool reg)
  950. {
  951. // do nothing on client registration, wait for first port
  952. if (reg) return;
  953. const int id(getGroupId(name)); // also checks name nullness
  954. if (id == -1)
  955. return;
  956. GroupNameToId groupNameId(id, name);
  957. fUsedGroupNames.removeAll(groupNameId);
  958. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_REMOVED, id, 0, 0, 0.0f, nullptr);
  959. }
  960. void handleJackPortRegistrationCallback(const jack_port_id_t port, const bool reg)
  961. {
  962. jack_port_t* const jackPort(jackbridge_port_by_id(fClient, port));
  963. const char* const portName(jackbridge_port_short_name(jackPort));
  964. const char* const fullPortName(jackbridge_port_name(jackPort));
  965. CARLA_SAFE_ASSERT_RETURN(jackPort != nullptr,);
  966. CARLA_SAFE_ASSERT_RETURN(portName != nullptr,);
  967. CARLA_SAFE_ASSERT_RETURN(fullPortName != nullptr,);
  968. CarlaString groupName(fullPortName);
  969. groupName.truncate(groupName.rfind(portName)-1);
  970. int groupId = getGroupId(groupName);
  971. if (reg)
  972. {
  973. const int jackPortFlags(jackbridge_port_flags(jackPort));
  974. if (groupId == -1)
  975. {
  976. groupId = fLastGroupId++;
  977. GroupNameToId groupNameToId(groupId, groupName);
  978. fUsedGroupNames.append(groupNameToId);
  979. if (jackPortFlags & JackPortIsPhysical)
  980. {
  981. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, PATCHBAY_ICON_HARDWARE, 0, 0.0f, groupName);
  982. // hardware
  983. }
  984. else
  985. {
  986. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, 0, 0, 0.0f, groupName);
  987. //fGroupIconsChanged.append(groupId);
  988. // "application"
  989. }
  990. }
  991. bool portIsInput = (jackPortFlags & JackPortIsInput);
  992. bool portIsAudio = (std::strcmp(jackbridge_port_type(jackPort), JACK_DEFAULT_AUDIO_TYPE) == 0);
  993. bool portIsCV = (jackPortFlags & JackPortIsControlVoltage);
  994. unsigned int canvasPortFlags = 0x0;
  995. canvasPortFlags |= portIsInput ? PATCHBAY_PORT_IS_INPUT : 0x0;
  996. canvasPortFlags |= portIsAudio ? PATCHBAY_PORT_TYPE_AUDIO : PATCHBAY_PORT_TYPE_MIDI;
  997. if (portIsAudio && portIsCV)
  998. canvasPortFlags |= PATCHBAY_PORT_TYPE_CV;
  999. PortNameToId portNameToId(groupId, fLastPortId++, portName, fullPortName);
  1000. fUsedPortNames.append(portNameToId);
  1001. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, portNameToId.portId, canvasPortFlags, 0.0f, portName);
  1002. }
  1003. else
  1004. {
  1005. const int portId(getPortId(fullPortName));
  1006. CARLA_SAFE_ASSERT_RETURN(groupId != -1,);
  1007. CARLA_SAFE_ASSERT_RETURN(portId != -1,);
  1008. PortNameToId portNameId(groupId, portId, portName, fullPortName);
  1009. fUsedPortNames.removeOne(portNameId);
  1010. callback(ENGINE_CALLBACK_PATCHBAY_PORT_REMOVED, groupId, portId, 0, 0.0f, nullptr);
  1011. }
  1012. }
  1013. void handleJackPortConnectCallback(const jack_port_id_t a, const jack_port_id_t b, const bool connect)
  1014. {
  1015. jack_port_t* const jackPortA(jackbridge_port_by_id(fClient, a));
  1016. jack_port_t* const jackPortB(jackbridge_port_by_id(fClient, b));
  1017. const char* const fullPortNameA(jackbridge_port_name(jackPortA));
  1018. const char* const fullPortNameB(jackbridge_port_name(jackPortB));
  1019. CARLA_SAFE_ASSERT_RETURN(jackPortA != nullptr,);
  1020. CARLA_SAFE_ASSERT_RETURN(jackPortB != nullptr,);
  1021. CARLA_SAFE_ASSERT_RETURN(fullPortNameA != nullptr,);
  1022. CARLA_SAFE_ASSERT_RETURN(fullPortNameB != nullptr,);
  1023. const int portIdA(getPortId(fullPortNameA));
  1024. const int portIdB(getPortId(fullPortNameB));
  1025. if (portIdA == -1 || portIdB == -1)
  1026. return;
  1027. if (connect)
  1028. {
  1029. ConnectionToId connectionToId(fLastConnectionId++, portIdA, portIdB);
  1030. fUsedConnections.append(connectionToId);
  1031. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  1032. }
  1033. else
  1034. {
  1035. for (LinkedList<ConnectionToId>::Itenerator it = fUsedConnections.begin(); it.valid(); it.next())
  1036. {
  1037. const ConnectionToId& connectionToId(it.getValue());
  1038. if (connectionToId.portOut == portIdA && connectionToId.portIn == portIdB)
  1039. {
  1040. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_REMOVED, connectionToId.id, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  1041. fUsedConnections.remove(it);
  1042. break;
  1043. }
  1044. }
  1045. }
  1046. }
  1047. void handleJackClientRenameCallback(const char* const oldName, const char* const newName)
  1048. {
  1049. for (LinkedList<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next())
  1050. {
  1051. GroupNameToId& groupNameToId(it.getValue());
  1052. if (std::strcmp(groupNameToId.name, oldName) == 0)
  1053. {
  1054. groupNameToId.rename(newName);
  1055. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_RENAMED, groupNameToId.id, 0, 0, 0.0f, newName);
  1056. break;
  1057. }
  1058. }
  1059. }
  1060. void handleJackPortRenameCallback(const jack_port_id_t port, const char* const oldName, const char* const newName)
  1061. {
  1062. jack_port_t* const jackPort(jackbridge_port_by_id(fClient, port));
  1063. const char* const portName(jackbridge_port_short_name(jackPort));
  1064. CARLA_SAFE_ASSERT_RETURN(jackPort != nullptr,);
  1065. CARLA_SAFE_ASSERT_RETURN(portName != nullptr,);
  1066. CarlaString groupName(newName);
  1067. groupName.truncate(groupName.rfind(portName)-1);
  1068. const int groupId(getGroupId(groupName));
  1069. CARLA_SAFE_ASSERT_RETURN(groupId != -1,);
  1070. for (LinkedList<PortNameToId>::Itenerator it = fUsedPortNames.begin(); it.valid(); it.next())
  1071. {
  1072. PortNameToId& portNameId(it.getValue());
  1073. if (std::strcmp(portNameId.fullName, oldName) == 0)
  1074. {
  1075. CARLA_SAFE_ASSERT(portNameId.groupId == groupId);
  1076. portNameId.rename(portName, newName);
  1077. callback(ENGINE_CALLBACK_PATCHBAY_PORT_RENAMED, groupId, portNameId.portId, 0, 0.0f, newName);
  1078. break;
  1079. }
  1080. }
  1081. }
  1082. #endif
  1083. void handleJackShutdownCallback()
  1084. {
  1085. for (unsigned int i=0; i < pData->curPluginCount; ++i)
  1086. {
  1087. //CarlaPlugin* const plugin(pData->plugins[i].plugin);
  1088. //if (plugin)
  1089. // plugin->x_client = nullptr;
  1090. }
  1091. fClient = nullptr;
  1092. callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr);
  1093. }
  1094. // -------------------------------------------------------------------
  1095. private:
  1096. jack_client_t* fClient;
  1097. jack_position_t fTransportPos;
  1098. jack_transport_state_t fTransportState;
  1099. bool fFreewheel;
  1100. // -------------------------------------------------------------------
  1101. #ifdef BUILD_BRIDGE
  1102. bool fIsRunning;
  1103. #else
  1104. enum RackPorts {
  1105. kRackPortAudioIn1 = 0,
  1106. kRackPortAudioIn2 = 1,
  1107. kRackPortAudioOut1 = 2,
  1108. kRackPortAudioOut2 = 3,
  1109. kRackPortEventIn = 4,
  1110. kRackPortEventOut = 5,
  1111. kRackPortCount = 6
  1112. };
  1113. jack_port_t* fRackPorts[kRackPortCount];
  1114. struct GroupNameToId {
  1115. int id;
  1116. char name[STR_MAX+1];
  1117. GroupNameToId()
  1118. {
  1119. id = -1;
  1120. name[0] = '\0';
  1121. }
  1122. GroupNameToId(const int id, const char name[])
  1123. {
  1124. this->id = id;
  1125. std::strncpy(this->name, name, STR_MAX);
  1126. this->name[STR_MAX] = '\0';
  1127. }
  1128. void rename(const char name[])
  1129. {
  1130. std::strncpy(this->name, name, STR_MAX);
  1131. this->name[STR_MAX] = '\0';
  1132. }
  1133. bool operator==(const GroupNameToId& groupNameId)
  1134. {
  1135. if (groupNameId.id != id)
  1136. return false;
  1137. if (std::strcmp(groupNameId.name, name) != 0)
  1138. return false;
  1139. return true;
  1140. }
  1141. };
  1142. struct PortNameToId {
  1143. int groupId;
  1144. int portId;
  1145. char name[STR_MAX+1];
  1146. char fullName[STR_MAX+1]; // unique
  1147. PortNameToId()
  1148. {
  1149. groupId = -1;
  1150. portId = -1;
  1151. name[0] = '\0';
  1152. fullName[0] = '\0';
  1153. }
  1154. PortNameToId(const int groupId, const int portId, const char name[], const char fullName[])
  1155. {
  1156. this->groupId = groupId;
  1157. this->portId = portId;
  1158. std::strncpy(this->name, name, STR_MAX);
  1159. this->name[STR_MAX] = '\0';
  1160. std::strncpy(this->fullName, fullName, STR_MAX);
  1161. this->fullName[STR_MAX] = '\0';
  1162. }
  1163. void rename(const char name[], const char fullName[])
  1164. {
  1165. std::strncpy(this->name, name, STR_MAX);
  1166. this->name[STR_MAX] = '\0';
  1167. std::strncpy(this->fullName, fullName, STR_MAX);
  1168. this->fullName[STR_MAX] = '\0';
  1169. }
  1170. bool operator==(const PortNameToId& portNameId)
  1171. {
  1172. if (portNameId.groupId != groupId)
  1173. return false;
  1174. if (portNameId.portId != portId)
  1175. return false;
  1176. if (std::strcmp(portNameId.name, name) != 0)
  1177. return false;
  1178. if (std::strcmp(portNameId.fullName, fullName) != 0)
  1179. return false;
  1180. return true;
  1181. }
  1182. };
  1183. struct ConnectionToId {
  1184. int id;
  1185. int portOut;
  1186. int portIn;
  1187. ConnectionToId()
  1188. {
  1189. id = -1;
  1190. portOut = -1;
  1191. portIn = -1;
  1192. }
  1193. ConnectionToId(const int id, const int portOut, const int portIn)
  1194. {
  1195. this->id = id;
  1196. this->portOut = portOut;
  1197. this->portIn = portIn;
  1198. }
  1199. bool operator==(const ConnectionToId& connectionId)
  1200. {
  1201. if (connectionId.id != id)
  1202. return false;
  1203. if (connectionId.portOut != portOut)
  1204. return false;
  1205. if (connectionId.portIn != portIn)
  1206. return false;
  1207. return true;
  1208. }
  1209. };
  1210. int fLastGroupId;
  1211. int fLastPortId;
  1212. int fLastConnectionId;
  1213. LinkedList<GroupNameToId> fUsedGroupNames;
  1214. LinkedList<PortNameToId> fUsedPortNames;
  1215. LinkedList<ConnectionToId> fUsedConnections;
  1216. //LinkedList<int> fGroupIconsChanged;
  1217. int getGroupId(const char* const name)
  1218. {
  1219. CARLA_SAFE_ASSERT_RETURN(name != nullptr, -1);
  1220. for (LinkedList<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next())
  1221. {
  1222. const GroupNameToId& groupNameId(it.getValue());
  1223. if (std::strcmp(groupNameId.name, name) == 0)
  1224. return groupNameId.id;
  1225. }
  1226. return -1;
  1227. }
  1228. const char* getGroupName(const int groupId)
  1229. {
  1230. static const char fallback[1] = { '\0' };
  1231. CARLA_SAFE_ASSERT_RETURN(groupId >= 0, fallback);
  1232. for (LinkedList<GroupNameToId>::Itenerator it = fUsedGroupNames.begin(); it.valid(); it.next())
  1233. {
  1234. const GroupNameToId& groupNameId(it.getValue());
  1235. if (groupNameId.id == groupId)
  1236. return groupNameId.name;
  1237. }
  1238. return fallback;
  1239. }
  1240. int getPortId(const char* const fullName)
  1241. {
  1242. CARLA_SAFE_ASSERT_RETURN(fullName != nullptr, -1);
  1243. for (LinkedList<PortNameToId>::Itenerator it = fUsedPortNames.begin(); it.valid(); it.next())
  1244. {
  1245. const PortNameToId& portNameId(it.getValue());
  1246. if (std::strcmp(portNameId.fullName, fullName) == 0)
  1247. return portNameId.portId;
  1248. }
  1249. return -1;
  1250. }
  1251. void getFullPortName(const int portId, char nameBuf[STR_MAX+1])
  1252. {
  1253. for (LinkedList<PortNameToId>::Itenerator it = fUsedPortNames.begin(); it.valid(); it.next())
  1254. {
  1255. const PortNameToId& portNameId(it.getValue());
  1256. if (portNameId.portId == portId)
  1257. {
  1258. std::strncpy(nameBuf, portNameId.fullName, STR_MAX);
  1259. nameBuf[STR_MAX] = '\0';
  1260. return;
  1261. }
  1262. }
  1263. nameBuf[0] = '\0';
  1264. }
  1265. void initJackPatchbay(const char* const ourName)
  1266. {
  1267. CARLA_SAFE_ASSERT_RETURN(fLastGroupId == 0,);
  1268. CARLA_SAFE_ASSERT_RETURN(fLastPortId == 0,);
  1269. CARLA_SAFE_ASSERT_RETURN(fLastConnectionId == 0,);
  1270. CARLA_SAFE_ASSERT_RETURN(ourName != nullptr,);
  1271. // query initial jack ports
  1272. QStringList parsedGroups;
  1273. // our client
  1274. {
  1275. parsedGroups.append(QString(ourName));
  1276. GroupNameToId groupNameToId(fLastGroupId++, ourName);
  1277. fUsedGroupNames.append(groupNameToId);
  1278. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupNameToId.id, PATCHBAY_ICON_CARLA, 0, 0.0f, ourName);
  1279. }
  1280. if (const char** ports = jackbridge_get_ports(fClient, nullptr, nullptr, 0))
  1281. {
  1282. for (int i=0; ports[i] != nullptr; ++i)
  1283. {
  1284. jack_port_t* const jackPort(jackbridge_port_by_name(fClient, ports[i]));
  1285. const char* const portName(jackbridge_port_short_name(jackPort));
  1286. const char* const fullPortName(ports[i]);
  1287. CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr);
  1288. CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr);
  1289. const int jackPortFlags(jackbridge_port_flags(jackPort));
  1290. int groupId = -1;
  1291. bool found;
  1292. CarlaString groupName(fullPortName);
  1293. groupName.truncate(groupName.rfind(portName, &found)-1);
  1294. CARLA_SAFE_ASSERT(found);
  1295. QString qGroupName((const char*)groupName);
  1296. if (parsedGroups.contains(qGroupName))
  1297. {
  1298. groupId = getGroupId(groupName);
  1299. CARLA_SAFE_ASSERT(groupId != -1);
  1300. }
  1301. else
  1302. {
  1303. groupId = fLastGroupId++;
  1304. parsedGroups.append(qGroupName);
  1305. GroupNameToId groupNameToId(groupId, groupName);
  1306. fUsedGroupNames.append(groupNameToId);
  1307. PatchbayIcon groupIcon = PATCHBAY_ICON_APPLICATION;
  1308. #if 0
  1309. void* data = nullptr;
  1310. size_t dataSize = 0;
  1311. #endif
  1312. if (jackPortFlags & JackPortIsPhysical)
  1313. {
  1314. groupIcon = PATCHBAY_ICON_HARDWARE;
  1315. }
  1316. #if 0
  1317. else if (jackbridge_custom_get_data(fClient, groupName, URI_CANVAS_ICON, &data, &dataSize) && data != nullptr && dataSize != 0)
  1318. {
  1319. const char* const icon((const char*)data);
  1320. CARLA_ASSERT(std::strlen(icon)+1 == dataSize);
  1321. if (std::strcmp(icon, "app") == 0 || std::strcmp(icon, "application") == 0)
  1322. groupIcon = PATCHBAY_ICON_APPLICATION;
  1323. else if (std::strcmp(icon, "hardware") == 0)
  1324. groupIcon = PATCHBAY_ICON_HARDWARE;
  1325. else if (std::strcmp(icon, "carla") == 0)
  1326. groupIcon = PATCHBAY_ICON_CARLA;
  1327. else if (std::strcmp(icon, "distrho") == 0)
  1328. groupIcon = PATCHBAY_ICON_DISTRHO;
  1329. else if (std::strcmp(icon, "file") == 0)
  1330. groupIcon = PATCHBAY_ICON_FILE;
  1331. else if (std::strcmp(icon, "plugin") == 0)
  1332. groupIcon = PATCHBAY_ICON_PLUGIN;
  1333. }
  1334. #endif
  1335. callback(ENGINE_CALLBACK_PATCHBAY_CLIENT_ADDED, groupId, groupIcon, 0, 0.0f, groupName);
  1336. }
  1337. bool portIsInput = (jackPortFlags & JackPortIsInput);
  1338. bool portIsAudio = (std::strcmp(jackbridge_port_type(jackPort), JACK_DEFAULT_AUDIO_TYPE) == 0);
  1339. bool portIsCV = (portIsAudio && (jackPortFlags & JackPortIsControlVoltage) != 0);
  1340. unsigned int canvasPortFlags = 0x0;
  1341. canvasPortFlags |= portIsInput ? PATCHBAY_PORT_IS_INPUT : 0x0;
  1342. canvasPortFlags |= portIsAudio ? PATCHBAY_PORT_TYPE_AUDIO : PATCHBAY_PORT_TYPE_MIDI;
  1343. if (portIsCV)
  1344. canvasPortFlags |= PATCHBAY_PORT_TYPE_CV;
  1345. PortNameToId portNameToId(groupId, fLastPortId++, portName, fullPortName);
  1346. fUsedPortNames.append(portNameToId);
  1347. callback(ENGINE_CALLBACK_PATCHBAY_PORT_ADDED, groupId, portNameToId.portId, canvasPortFlags, 0.0f, portName);
  1348. }
  1349. // query connections, after all ports are in place
  1350. for (int i=0; ports[i] != nullptr; ++i)
  1351. {
  1352. jack_port_t* const jackPort(jackbridge_port_by_name(fClient, ports[i]));
  1353. const char* const fullPortName(ports[i]);
  1354. const int thisPortId(getPortId(fullPortName));
  1355. CARLA_SAFE_ASSERT_CONTINUE(jackPort != nullptr);
  1356. CARLA_SAFE_ASSERT_CONTINUE(thisPortId != -1);
  1357. if (const char** connections = jackbridge_port_get_all_connections(fClient, jackPort))
  1358. {
  1359. for (int j=0; connections[j] != nullptr; ++j)
  1360. {
  1361. const int targetPortId(getPortId(connections[j]));
  1362. ConnectionToId connectionToId(fLastConnectionId++, thisPortId, targetPortId);
  1363. fUsedConnections.append(connectionToId);
  1364. callback(ENGINE_CALLBACK_PATCHBAY_CONNECTION_ADDED, connectionToId.id, connectionToId.portOut, connectionToId.portIn, 0.0f, nullptr);
  1365. }
  1366. jackbridge_free(connections);
  1367. }
  1368. }
  1369. jackbridge_free(ports);
  1370. }
  1371. }
  1372. #endif
  1373. // -------------------------------------
  1374. void processPlugin(CarlaPlugin* const plugin, const uint32_t nframes)
  1375. {
  1376. const uint32_t inCount(plugin->getAudioInCount());
  1377. const uint32_t outCount(plugin->getAudioOutCount());
  1378. float* inBuffer[inCount];
  1379. float* outBuffer[outCount];
  1380. float inPeaks[2] = { 0.0f };
  1381. float outPeaks[2] = { 0.0f };
  1382. for (uint32_t i=0; i < inCount; ++i)
  1383. {
  1384. CarlaEngineAudioPort* const port(plugin->getAudioInPort(i));
  1385. inBuffer[i] = port->getBuffer();
  1386. }
  1387. for (uint32_t i=0; i < outCount; ++i)
  1388. {
  1389. CarlaEngineAudioPort* const port(plugin->getAudioOutPort(i));
  1390. outBuffer[i] = port->getBuffer();
  1391. }
  1392. for (uint32_t i=0; i < inCount && i < 2; ++i)
  1393. {
  1394. for (uint32_t j=0; j < nframes; ++j)
  1395. {
  1396. const float absV(std::abs(inBuffer[i][j]));
  1397. if (absV > inPeaks[i])
  1398. inPeaks[i] = absV;
  1399. }
  1400. }
  1401. plugin->process(inBuffer, outBuffer, nframes);
  1402. for (uint32_t i=0; i < outCount && i < 2; ++i)
  1403. {
  1404. for (uint32_t j=0; j < nframes; ++j)
  1405. {
  1406. const float absV(std::abs(outBuffer[i][j]));
  1407. if (absV > outPeaks[i])
  1408. outPeaks[i] = absV;
  1409. }
  1410. }
  1411. setPluginPeaks(plugin->getId(), inPeaks, outPeaks);
  1412. }
  1413. #if 0
  1414. void latencyPlugin(CarlaPlugin* const plugin, jack_latency_callback_mode_t mode)
  1415. {
  1416. //const uint32_t inCount(plugin->audioInCount());
  1417. //const uint32_t outCount(plugin->audioOutCount());
  1418. const uint32_t latency(plugin->getLatencyInFrames());
  1419. if (latency == 0)
  1420. return;
  1421. //jack_latency_range_t range;
  1422. // TODO
  1423. if (mode == JackCaptureLatency)
  1424. {
  1425. for (uint32_t i=0; i < inCount; ++i)
  1426. {
  1427. uint32_t aOutI = (i >= outCount) ? outCount : i;
  1428. jack_port_t* const portIn = ((CarlaEngineJackAudioPort*)CarlaPluginGetAudioInPort(plugin, i))->kPort;
  1429. jack_port_t* const portOut = ((CarlaEngineJackAudioPort*)CarlaPluginGetAudioOutPort(plugin, aOutI))->kPort;
  1430. jackbridge_port_get_latency_range(portIn, mode, &range);
  1431. range.min += latency;
  1432. range.max += latency;
  1433. jackbridge_port_set_latency_range(portOut, mode, &range);
  1434. }
  1435. }
  1436. else
  1437. {
  1438. for (uint32_t i=0; i < outCount; ++i)
  1439. {
  1440. uint32_t aInI = (i >= inCount) ? inCount : i;
  1441. jack_port_t* const portIn = ((CarlaEngineJackAudioPort*)CarlaPluginGetAudioInPort(plugin, aInI))->kPort;
  1442. jack_port_t* const portOut = ((CarlaEngineJackAudioPort*)CarlaPluginGetAudioOutPort(plugin, i))->kPort;
  1443. jackbridge_port_get_latency_range(portOut, mode, &range);
  1444. range.min += latency;
  1445. range.max += latency;
  1446. jackbridge_port_set_latency_range(portIn, mode, &range);
  1447. }
  1448. }
  1449. }
  1450. #endif
  1451. // -------------------------------------
  1452. #define handlePtr ((CarlaEngineJack*)arg)
  1453. static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg)
  1454. {
  1455. handlePtr->handleJackBufferSizeCallback(newBufferSize);
  1456. return 0;
  1457. }
  1458. static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg)
  1459. {
  1460. handlePtr->handleJackSampleRateCallback(newSampleRate);
  1461. return 0;
  1462. }
  1463. static void carla_jack_freewheel_callback(int starting, void* arg)
  1464. {
  1465. handlePtr->handleJackFreewheelCallback(bool(starting));
  1466. }
  1467. static int carla_jack_process_callback(jack_nframes_t nframes, void* arg)
  1468. {
  1469. handlePtr->handleJackProcessCallback(nframes);
  1470. return 0;
  1471. }
  1472. #if 0
  1473. static void carla_jack_latency_callback(jack_latency_callback_mode_t mode, void* arg)
  1474. {
  1475. handlePtr->handleJackLatencyCallback(mode);
  1476. }
  1477. #endif
  1478. #ifndef BUILD_BRIDGE
  1479. # if 0
  1480. static void carla_jack_custom_appearance_callback(const char* client_name, const char* key, jack_custom_change_t change, void* arg)
  1481. {
  1482. handlePtr->handleCustomAppearanceCallback(client_name, key, change);
  1483. }
  1484. # endif
  1485. static void carla_jack_client_registration_callback(const char* name, int reg, void* arg)
  1486. {
  1487. handlePtr->handleJackClientRegistrationCallback(name, (reg != 0));
  1488. }
  1489. static void carla_jack_port_registration_callback(jack_port_id_t port, int reg, void* arg)
  1490. {
  1491. handlePtr->handleJackPortRegistrationCallback(port, (reg != 0));
  1492. }
  1493. static void carla_jack_port_connect_callback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg)
  1494. {
  1495. handlePtr->handleJackPortConnectCallback(a, b, (connect != 0));
  1496. }
  1497. static int carla_jack_client_rename_callback(const char* oldName, const char* newName, void* arg)
  1498. {
  1499. handlePtr->handleJackClientRenameCallback(oldName, newName);
  1500. return 0;
  1501. }
  1502. static int carla_jack_port_rename_callback(jack_port_id_t port, const char* oldName, const char* newName, void* arg)
  1503. {
  1504. handlePtr->handleJackPortRenameCallback(port, oldName, newName);
  1505. return 0;
  1506. }
  1507. #endif
  1508. static void carla_jack_shutdown_callback(void* arg)
  1509. {
  1510. handlePtr->handleJackShutdownCallback();
  1511. }
  1512. #undef handlePtr
  1513. // -------------------------------------------------------------------
  1514. #ifndef BUILD_BRIDGE
  1515. static int carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg)
  1516. {
  1517. CarlaPlugin* const plugin((CarlaPlugin*)arg);
  1518. if (plugin != nullptr && plugin->isEnabled())
  1519. {
  1520. CarlaEngineJack* const engine((CarlaEngineJack*)plugin->getEngine());
  1521. CARLA_SAFE_ASSERT_RETURN(engine != nullptr,0);
  1522. if (plugin->tryLock(engine->fFreewheel))
  1523. {
  1524. plugin->initBuffers();
  1525. engine->saveTransportInfo();
  1526. engine->processPlugin(plugin, nframes);
  1527. plugin->unlock();
  1528. }
  1529. }
  1530. return 0;
  1531. }
  1532. # if 0
  1533. static void carla_jack_latency_callback_plugin(jack_latency_callback_mode_t mode, void* arg)
  1534. {
  1535. CarlaPlugin* const plugin((CarlaPlugin*)arg);
  1536. if (plugin != nullptr && plugin->isEnabled())
  1537. {
  1538. CarlaEngineJack* const engine((CarlaEngineJack*)plugin->getEngine());
  1539. CARLA_SAFE_ASSERT_RETURN(engine != nullptr,);
  1540. engine->latencyPlugin(plugin, mode);
  1541. }
  1542. }
  1543. # endif
  1544. #endif
  1545. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack)
  1546. };
  1547. // -----------------------------------------------------------------------
  1548. CarlaEngine* CarlaEngine::newJack()
  1549. {
  1550. carla_debug("CarlaEngine::newJack()");
  1551. return new CarlaEngineJack();
  1552. }
  1553. // -----------------------------------------------------------------------
  1554. CARLA_BACKEND_END_NAMESPACE