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.

2010 lines
65KB

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