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.

juce_linux_JackAudio.cpp 22KB

10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2013 - Raw Material Software Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. //==============================================================================
  18. static void* juce_libjackHandle = nullptr;
  19. static void* juce_loadJackFunction (const char* const name)
  20. {
  21. if (juce_libjackHandle == nullptr)
  22. return nullptr;
  23. return dlsym (juce_libjackHandle, name);
  24. }
  25. #define JUCE_DECL_JACK_FUNCTION(return_type, fn_name, argument_types, arguments) \
  26. return_type fn_name argument_types \
  27. { \
  28. typedef return_type (*fn_type) argument_types; \
  29. static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name); \
  30. return (fn != nullptr) ? ((*fn) arguments) : (return_type) 0; \
  31. }
  32. #define JUCE_DECL_VOID_JACK_FUNCTION(fn_name, argument_types, arguments) \
  33. void fn_name argument_types \
  34. { \
  35. typedef void (*fn_type) argument_types; \
  36. static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name); \
  37. if (fn != nullptr) (*fn) arguments; \
  38. }
  39. //==============================================================================
  40. JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status, ...), (client_name, options, status));
  41. JUCE_DECL_JACK_FUNCTION (int, jack_client_close, (jack_client_t *client), (client));
  42. JUCE_DECL_JACK_FUNCTION (int, jack_activate, (jack_client_t* client), (client));
  43. JUCE_DECL_JACK_FUNCTION (int, jack_deactivate, (jack_client_t* client), (client));
  44. JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_buffer_size, (jack_client_t* client), (client));
  45. JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_sample_rate, (jack_client_t* client), (client));
  46. JUCE_DECL_VOID_JACK_FUNCTION (jack_on_shutdown, (jack_client_t* client, void (*function)(void* arg), void* arg), (client, function, arg));
  47. JUCE_DECL_JACK_FUNCTION (void* , jack_port_get_buffer, (jack_port_t* port, jack_nframes_t nframes), (port, nframes));
  48. JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_port_get_total_latency, (jack_client_t* client, jack_port_t* port), (client, port));
  49. JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_register, (jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size), (client, port_name, port_type, flags, buffer_size));
  50. JUCE_DECL_VOID_JACK_FUNCTION (jack_set_error_function, (void (*func)(const char*)), (func));
  51. JUCE_DECL_JACK_FUNCTION (int, jack_set_process_callback, (jack_client_t* client, JackProcessCallback process_callback, void* arg), (client, process_callback, arg));
  52. JUCE_DECL_JACK_FUNCTION (const char**, jack_get_ports, (jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags), (client, port_name_pattern, type_name_pattern, flags));
  53. JUCE_DECL_JACK_FUNCTION (int, jack_connect, (jack_client_t* client, const char* source_port, const char* destination_port), (client, source_port, destination_port));
  54. JUCE_DECL_JACK_FUNCTION (const char*, jack_port_name, (const jack_port_t* port), (port));
  55. JUCE_DECL_JACK_FUNCTION (void*, jack_set_port_connect_callback, (jack_client_t* client, JackPortConnectCallback connect_callback, void* arg), (client, connect_callback, arg));
  56. JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_by_id, (jack_client_t* client, jack_port_id_t port_id), (client, port_id));
  57. JUCE_DECL_JACK_FUNCTION (int, jack_port_connected, (const jack_port_t* port), (port));
  58. JUCE_DECL_JACK_FUNCTION (int, jack_port_connected_to, (const jack_port_t* port, const char* port_name), (port, port_name));
  59. #if JUCE_DEBUG
  60. #define JACK_LOGGING_ENABLED 1
  61. #endif
  62. #if JACK_LOGGING_ENABLED
  63. namespace
  64. {
  65. void jack_Log (const String& s)
  66. {
  67. std::cerr << s << std::endl;
  68. }
  69. const char* getJackErrorMessage (const jack_status_t status)
  70. {
  71. if (status & JackServerFailed
  72. || status & JackServerError) return "Unable to connect to JACK server";
  73. if (status & JackVersionError) return "Client's protocol version does not match";
  74. if (status & JackInvalidOption) return "The operation contained an invalid or unsupported option";
  75. if (status & JackNameNotUnique) return "The desired client name was not unique";
  76. if (status & JackNoSuchClient) return "Requested client does not exist";
  77. if (status & JackInitFailure) return "Unable to initialize client";
  78. return nullptr;
  79. }
  80. }
  81. #define JUCE_JACK_LOG_STATUS(x) { if (const char* m = getJackErrorMessage (x)) jack_Log (m); }
  82. #define JUCE_JACK_LOG(x) jack_Log(x)
  83. #else
  84. #define JUCE_JACK_LOG_STATUS(x) {}
  85. #define JUCE_JACK_LOG(x) {}
  86. #endif
  87. //==============================================================================
  88. #ifndef JUCE_JACK_CLIENT_NAME
  89. #define JUCE_JACK_CLIENT_NAME "JUCEJack"
  90. #endif
  91. struct JackPortIterator
  92. {
  93. JackPortIterator (jack_client_t* const client, const bool forInput)
  94. : ports (nullptr), index (-1)
  95. {
  96. if (client != nullptr)
  97. ports = juce::jack_get_ports (client, nullptr, nullptr,
  98. forInput ? JackPortIsOutput : JackPortIsInput);
  99. // (NB: This looks like it's the wrong way round, but it is correct!)
  100. }
  101. ~JackPortIterator()
  102. {
  103. ::free (ports);
  104. }
  105. bool next()
  106. {
  107. if (ports == nullptr || ports [index + 1] == nullptr)
  108. return false;
  109. name = CharPointer_UTF8 (ports[++index]);
  110. clientName = name.upToFirstOccurrenceOf (":", false, false);
  111. return true;
  112. }
  113. const char** ports;
  114. int index;
  115. String name;
  116. String clientName;
  117. };
  118. class JackAudioIODeviceType;
  119. static Array<JackAudioIODeviceType*> activeDeviceTypes;
  120. //==============================================================================
  121. class JackAudioIODevice : public AudioIODevice
  122. {
  123. public:
  124. JackAudioIODevice (const String& deviceName,
  125. const String& inId,
  126. const String& outId)
  127. : AudioIODevice (deviceName, "JACK"),
  128. inputId (inId),
  129. outputId (outId),
  130. deviceIsOpen (false),
  131. callback (nullptr),
  132. totalNumberOfInputChannels (0),
  133. totalNumberOfOutputChannels (0)
  134. {
  135. jassert (deviceName.isNotEmpty());
  136. jack_status_t status;
  137. client = juce::jack_client_open (JUCE_JACK_CLIENT_NAME, JackNoStartServer, &status);
  138. if (client == nullptr)
  139. {
  140. JUCE_JACK_LOG_STATUS (status);
  141. }
  142. else
  143. {
  144. juce::jack_set_error_function (errorCallback);
  145. // open input ports
  146. const StringArray inputChannels (getInputChannelNames());
  147. for (int i = 0; i < inputChannels.size(); ++i)
  148. {
  149. String inputName;
  150. inputName << "in_" << ++totalNumberOfInputChannels;
  151. inputPorts.add (juce::jack_port_register (client, inputName.toUTF8(),
  152. JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0));
  153. }
  154. // open output ports
  155. const StringArray outputChannels (getOutputChannelNames());
  156. for (int i = 0; i < outputChannels.size (); ++i)
  157. {
  158. String outputName;
  159. outputName << "out_" << ++totalNumberOfOutputChannels;
  160. outputPorts.add (juce::jack_port_register (client, outputName.toUTF8(),
  161. JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
  162. }
  163. inChans.calloc (totalNumberOfInputChannels + 2);
  164. outChans.calloc (totalNumberOfOutputChannels + 2);
  165. }
  166. }
  167. ~JackAudioIODevice()
  168. {
  169. close();
  170. if (client != nullptr)
  171. {
  172. juce::jack_client_close (client);
  173. client = nullptr;
  174. }
  175. }
  176. StringArray getChannelNames (bool forInput) const
  177. {
  178. StringArray names;
  179. for (JackPortIterator i (client, forInput); i.next();)
  180. if (i.clientName == getName())
  181. names.add (i.name.fromFirstOccurrenceOf (":", false, false));
  182. return names;
  183. }
  184. StringArray getOutputChannelNames() override { return getChannelNames (false); }
  185. StringArray getInputChannelNames() override { return getChannelNames (true); }
  186. Array<double> getAvailableSampleRates() override
  187. {
  188. Array<double> rates;
  189. if (client != nullptr)
  190. rates.add (juce::jack_get_sample_rate (client));
  191. return rates;
  192. }
  193. Array<int> getAvailableBufferSizes() override
  194. {
  195. Array<int> sizes;
  196. if (client != nullptr)
  197. sizes.add (juce::jack_get_buffer_size (client));
  198. return sizes;
  199. }
  200. int getDefaultBufferSize() override { return getCurrentBufferSizeSamples(); }
  201. int getCurrentBufferSizeSamples() override { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
  202. double getCurrentSampleRate() override { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
  203. String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
  204. double /* sampleRate */, int /* bufferSizeSamples */) override
  205. {
  206. if (client == nullptr)
  207. {
  208. lastError = "No JACK client running";
  209. return lastError;
  210. }
  211. lastError.clear();
  212. close();
  213. juce::jack_set_process_callback (client, processCallback, this);
  214. juce::jack_set_port_connect_callback (client, portConnectCallback, this);
  215. juce::jack_on_shutdown (client, shutdownCallback, this);
  216. juce::jack_activate (client);
  217. deviceIsOpen = true;
  218. if (! inputChannels.isZero())
  219. {
  220. for (JackPortIterator i (client, true); i.next();)
  221. {
  222. if (inputChannels [i.index] && i.clientName == getName())
  223. {
  224. int error = juce::jack_connect (client, i.ports[i.index], juce::jack_port_name ((jack_port_t*) inputPorts[i.index]));
  225. if (error != 0)
  226. JUCE_JACK_LOG ("Cannot connect input port " + String (i.index) + " (" + i.name + "), error " + String (error));
  227. }
  228. }
  229. }
  230. if (! outputChannels.isZero())
  231. {
  232. for (JackPortIterator i (client, false); i.next();)
  233. {
  234. if (outputChannels [i.index] && i.clientName == getName())
  235. {
  236. int error = juce::jack_connect (client, juce::jack_port_name ((jack_port_t*) outputPorts[i.index]), i.ports[i.index]);
  237. if (error != 0)
  238. JUCE_JACK_LOG ("Cannot connect output port " + String (i.index) + " (" + i.name + "), error " + String (error));
  239. }
  240. }
  241. }
  242. return lastError;
  243. }
  244. void close() override
  245. {
  246. stop();
  247. if (client != nullptr)
  248. {
  249. juce::jack_deactivate (client);
  250. juce::jack_set_process_callback (client, processCallback, nullptr);
  251. juce::jack_set_port_connect_callback (client, portConnectCallback, nullptr);
  252. juce::jack_on_shutdown (client, shutdownCallback, nullptr);
  253. }
  254. deviceIsOpen = false;
  255. }
  256. void start (AudioIODeviceCallback* newCallback) override
  257. {
  258. if (deviceIsOpen && newCallback != callback)
  259. {
  260. if (newCallback != nullptr)
  261. newCallback->audioDeviceAboutToStart (this);
  262. AudioIODeviceCallback* const oldCallback = callback;
  263. {
  264. const ScopedLock sl (callbackLock);
  265. callback = newCallback;
  266. }
  267. if (oldCallback != nullptr)
  268. oldCallback->audioDeviceStopped();
  269. }
  270. }
  271. void stop() override
  272. {
  273. start (nullptr);
  274. }
  275. bool isOpen() override { return deviceIsOpen; }
  276. bool isPlaying() override { return callback != nullptr; }
  277. int getCurrentBitDepth() override { return 32; }
  278. String getLastError() override { return lastError; }
  279. BigInteger getActiveOutputChannels() const override { return activeOutputChannels; }
  280. BigInteger getActiveInputChannels() const override { return activeInputChannels; }
  281. int getOutputLatencyInSamples() override
  282. {
  283. int latency = 0;
  284. for (int i = 0; i < outputPorts.size(); i++)
  285. latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) outputPorts [i]));
  286. return latency;
  287. }
  288. int getInputLatencyInSamples() override
  289. {
  290. int latency = 0;
  291. for (int i = 0; i < inputPorts.size(); i++)
  292. latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i]));
  293. return latency;
  294. }
  295. String inputId, outputId;
  296. private:
  297. void process (const int numSamples)
  298. {
  299. int numActiveInChans = 0, numActiveOutChans = 0;
  300. for (int i = 0; i < totalNumberOfInputChannels; ++i)
  301. {
  302. if (activeInputChannels[i])
  303. if (jack_default_audio_sample_t* in
  304. = (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples))
  305. inChans [numActiveInChans++] = (float*) in;
  306. }
  307. for (int i = 0; i < totalNumberOfOutputChannels; ++i)
  308. {
  309. if (activeOutputChannels[i])
  310. if (jack_default_audio_sample_t* out
  311. = (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples))
  312. outChans [numActiveOutChans++] = (float*) out;
  313. }
  314. const ScopedLock sl (callbackLock);
  315. if (callback != nullptr)
  316. {
  317. if ((numActiveInChans + numActiveOutChans) > 0)
  318. callback->audioDeviceIOCallback (const_cast <const float**> (inChans.getData()), numActiveInChans,
  319. outChans, numActiveOutChans, numSamples);
  320. }
  321. else
  322. {
  323. for (int i = 0; i < numActiveOutChans; ++i)
  324. zeromem (outChans[i], sizeof (float) * numSamples);
  325. }
  326. }
  327. static int processCallback (jack_nframes_t nframes, void* callbackArgument)
  328. {
  329. if (callbackArgument != nullptr)
  330. ((JackAudioIODevice*) callbackArgument)->process (nframes);
  331. return 0;
  332. }
  333. void updateActivePorts()
  334. {
  335. BigInteger newOutputChannels, newInputChannels;
  336. for (int i = 0; i < outputPorts.size(); ++i)
  337. if (juce::jack_port_connected ((jack_port_t*) outputPorts.getUnchecked(i)))
  338. newOutputChannels.setBit (i);
  339. for (int i = 0; i < inputPorts.size(); ++i)
  340. if (juce::jack_port_connected ((jack_port_t*) inputPorts.getUnchecked(i)))
  341. newInputChannels.setBit (i);
  342. if (newOutputChannels != activeOutputChannels
  343. || newInputChannels != activeInputChannels)
  344. {
  345. AudioIODeviceCallback* const oldCallback = callback;
  346. stop();
  347. activeOutputChannels = newOutputChannels;
  348. activeInputChannels = newInputChannels;
  349. if (oldCallback != nullptr)
  350. start (oldCallback);
  351. sendDeviceChangedCallback();
  352. }
  353. }
  354. static void portConnectCallback (jack_port_id_t, jack_port_id_t, int, void* arg)
  355. {
  356. if (JackAudioIODevice* device = static_cast <JackAudioIODevice*> (arg))
  357. device->updateActivePorts();
  358. }
  359. static void threadInitCallback (void* /* callbackArgument */)
  360. {
  361. JUCE_JACK_LOG ("JackAudioIODevice::initialise");
  362. }
  363. static void shutdownCallback (void* callbackArgument)
  364. {
  365. JUCE_JACK_LOG ("JackAudioIODevice::shutdown");
  366. if (JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument)
  367. {
  368. device->client = nullptr;
  369. device->close();
  370. }
  371. }
  372. static void errorCallback (const char* msg)
  373. {
  374. JUCE_JACK_LOG ("JackAudioIODevice::errorCallback " + String (msg));
  375. }
  376. static void sendDeviceChangedCallback();
  377. bool deviceIsOpen;
  378. jack_client_t* client;
  379. String lastError;
  380. AudioIODeviceCallback* callback;
  381. CriticalSection callbackLock;
  382. HeapBlock <float*> inChans, outChans;
  383. int totalNumberOfInputChannels;
  384. int totalNumberOfOutputChannels;
  385. Array<void*> inputPorts, outputPorts;
  386. BigInteger activeInputChannels, activeOutputChannels;
  387. };
  388. //==============================================================================
  389. class JackAudioIODeviceType : public AudioIODeviceType
  390. {
  391. public:
  392. JackAudioIODeviceType()
  393. : AudioIODeviceType ("JACK"),
  394. hasScanned (false)
  395. {
  396. activeDeviceTypes.add (this);
  397. }
  398. ~JackAudioIODeviceType()
  399. {
  400. activeDeviceTypes.removeFirstMatchingValue (this);
  401. }
  402. void scanForDevices()
  403. {
  404. hasScanned = true;
  405. inputNames.clear();
  406. inputIds.clear();
  407. outputNames.clear();
  408. outputIds.clear();
  409. if (juce_libjackHandle == nullptr) juce_libjackHandle = dlopen ("libjack.so.0", RTLD_LAZY);
  410. if (juce_libjackHandle == nullptr) juce_libjackHandle = dlopen ("libjack.so", RTLD_LAZY);
  411. if (juce_libjackHandle == nullptr) return;
  412. jack_status_t status;
  413. // open a dummy client
  414. if (jack_client_t* const client = juce::jack_client_open ("JuceJackDummy", JackNoStartServer, &status))
  415. {
  416. // scan for output devices
  417. for (JackPortIterator i (client, false); i.next();)
  418. {
  419. if (i.clientName != (JUCE_JACK_CLIENT_NAME) && ! inputNames.contains (i.clientName))
  420. {
  421. inputNames.add (i.clientName);
  422. inputIds.add (i.ports [i.index]);
  423. }
  424. }
  425. // scan for input devices
  426. for (JackPortIterator i (client, true); i.next();)
  427. {
  428. if (i.clientName != (JUCE_JACK_CLIENT_NAME) && ! outputNames.contains (i.clientName))
  429. {
  430. outputNames.add (i.clientName);
  431. outputIds.add (i.ports [i.index]);
  432. }
  433. }
  434. juce::jack_client_close (client);
  435. }
  436. else
  437. {
  438. JUCE_JACK_LOG_STATUS (status);
  439. }
  440. }
  441. StringArray getDeviceNames (bool wantInputNames) const
  442. {
  443. jassert (hasScanned); // need to call scanForDevices() before doing this
  444. return wantInputNames ? inputNames : outputNames;
  445. }
  446. int getDefaultDeviceIndex (bool /* forInput */) const
  447. {
  448. jassert (hasScanned); // need to call scanForDevices() before doing this
  449. return 0;
  450. }
  451. bool hasSeparateInputsAndOutputs() const { return true; }
  452. int getIndexOfDevice (AudioIODevice* device, bool asInput) const
  453. {
  454. jassert (hasScanned); // need to call scanForDevices() before doing this
  455. if (JackAudioIODevice* d = dynamic_cast <JackAudioIODevice*> (device))
  456. return asInput ? inputIds.indexOf (d->inputId)
  457. : outputIds.indexOf (d->outputId);
  458. return -1;
  459. }
  460. AudioIODevice* createDevice (const String& outputDeviceName,
  461. const String& inputDeviceName)
  462. {
  463. jassert (hasScanned); // need to call scanForDevices() before doing this
  464. const int inputIndex = inputNames.indexOf (inputDeviceName);
  465. const int outputIndex = outputNames.indexOf (outputDeviceName);
  466. if (inputIndex >= 0 || outputIndex >= 0)
  467. return new JackAudioIODevice (outputIndex >= 0 ? outputDeviceName
  468. : inputDeviceName,
  469. inputIds [inputIndex],
  470. outputIds [outputIndex]);
  471. return nullptr;
  472. }
  473. void portConnectionChange() { callDeviceChangeListeners(); }
  474. private:
  475. StringArray inputNames, outputNames, inputIds, outputIds;
  476. bool hasScanned;
  477. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JackAudioIODeviceType)
  478. };
  479. void JackAudioIODevice::sendDeviceChangedCallback()
  480. {
  481. for (int i = activeDeviceTypes.size(); --i >= 0;)
  482. if (JackAudioIODeviceType* d = activeDeviceTypes[i])
  483. d->portConnectionChange();
  484. }
  485. //==============================================================================
  486. AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK()
  487. {
  488. return new JackAudioIODeviceType();
  489. }