The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

614 lines
23KB

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