jack1 codebase
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.

883 lines
27KB

  1. /* -*- mode: c; c-file-style: "bsd"; -*- */
  2. /*
  3. Copyright © Grame 2003
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. Grame Research Laboratory, 9, rue du Garet 69001 Lyon - France
  16. grame@rd.grame.fr
  17. 02-09-03 : Modify jack port naming : add the name of the used driver
  18. Add the -n option to load a specific driver using it's name
  19. 04-09-03 : Correct bug in -n option management : input and ouput have to be treated separately
  20. 08-09-03 : More robust driver loading code : new portaudio_load_default and portaudio_load_driver functions.
  21. 24-09-03 : Does not tries to load default device if the required one is not found, returns and error.
  22. 14-10-03 : After jack port name size extension, does not use fixed length for CoreAudio driver name anymore
  23. 09-01-04 : Handle different value for channel in and channel out (using -i and -o)
  24. 12-01-04 : Connect port names (inverse "in" and "out")
  25. 13-01-04 : Correct the length of jack port : use JACK_PORT_NAME_SIZE
  26. 22-03-04 : Remove jack_init_time, rename input and ouput ports using "capture" and "playback"
  27. 10-11-04 : S. Letz: Add management of -I option for use with JackPilot.
  28. 17-11-04 : S. Letz: Better debug code.
  29. 03-02-05 : S. Letz: fix several driver detection bugs on OSX.
  30. 06-08-05 : S.Letz: Remove the "-I" parameter, change the semantic of "-n" parameter on OSX : -n (driver name) now correctly uses the PropertyDeviceUID
  31. (persistent accross reboot...) as the identifier for the used coreaudio driver.
  32. */
  33. #include <stdio.h>
  34. #include <errno.h>
  35. #include <string.h>
  36. #include <stdarg.h>
  37. #include <jack/engine.h>
  38. #include "portaudio_driver.h"
  39. #ifdef JACK_USE_MACH_THREADS
  40. #include <CoreAudio/CoreAudio.h>
  41. #include <CoreFoundation/CFString.h>
  42. static OSStatus get_device_name_from_id(AudioDeviceID id, char name[60])
  43. {
  44. UInt32 size = sizeof(char) * 60;
  45. OSStatus stat = AudioDeviceGetProperty(id, 0, false,
  46. kAudioDevicePropertyDeviceName,
  47. &size,
  48. &name[0]);
  49. return stat;
  50. }
  51. static OSStatus get_device_id_from_num(int i, AudioDeviceID * id)
  52. {
  53. OSStatus theStatus;
  54. UInt32 theSize;
  55. int nDevices;
  56. AudioDeviceID *theDeviceList;
  57. theStatus =
  58. AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
  59. &theSize, NULL);
  60. nDevices = theSize / sizeof(AudioDeviceID);
  61. theDeviceList =
  62. (AudioDeviceID *) malloc(nDevices * sizeof(AudioDeviceID));
  63. theStatus =
  64. AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &theSize,
  65. theDeviceList);
  66. *id = theDeviceList[i];
  67. return theStatus;
  68. }
  69. static OSStatus get_device_id_from_uid(char* UID, AudioDeviceID* id)
  70. {
  71. UInt32 size = sizeof(AudioValueTranslation);
  72. CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
  73. AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
  74. if (inIUD == NULL) {
  75. return kAudioHardwareUnspecifiedError;
  76. } else {
  77. OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
  78. CFRelease(inIUD);
  79. return res;
  80. }
  81. }
  82. #else
  83. typedef unsigned int AudioDeviceID;
  84. #endif
  85. #define PRINTDEBUG 1
  86. void PALog(char *fmt, ...)
  87. {
  88. #ifdef PRINTDEBUG
  89. va_list ap;
  90. va_start(ap, fmt);
  91. fprintf(stderr, "JCA: ");
  92. vfprintf(stderr, fmt, ap);
  93. va_end(ap);
  94. #endif
  95. }
  96. static int
  97. paCallback(void *inputBuffer, void *outputBuffer,
  98. unsigned long framesPerBuffer,
  99. PaTimestamp outTime, void *userData)
  100. {
  101. portaudio_driver_t * driver = (portaudio_driver_t*)userData;
  102. driver->inPortAudio = (float*)inputBuffer;
  103. driver->outPortAudio = (float*)outputBuffer;
  104. driver->last_wait_ust = jack_get_microseconds();
  105. return driver->engine->run_cycle(driver->engine, framesPerBuffer, 0);
  106. }
  107. static int
  108. portaudio_driver_attach (portaudio_driver_t *driver, jack_engine_t *engine)
  109. {
  110. jack_port_t *port;
  111. int port_flags;
  112. channel_t chn;
  113. char buf[JACK_PORT_NAME_SIZE];
  114. driver->engine = engine;
  115. driver->engine->set_buffer_size (engine, driver->frames_per_cycle);
  116. driver->engine->set_sample_rate (engine, driver->frame_rate);
  117. port_flags = JackPortIsOutput|JackPortIsPhysical|JackPortIsTerminal;
  118. /*
  119. if (driver->has_hw_monitoring) {
  120. port_flags |= JackPortCanMonitor;
  121. }
  122. */
  123. for (chn = 0; chn < driver->capture_nchannels; chn++) {
  124. //snprintf (buf, sizeof(buf) - 1, "%s:capture%lu", driver->driver_name, chn+1);
  125. snprintf (buf, sizeof(buf) - 1, "%s:out%lu", driver->driver_name, chn+1);
  126. if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) {
  127. jack_error ("portaudio: cannot register port for %s", buf);
  128. break;
  129. }
  130. /* XXX fix this so that it can handle: systemic (external) latency
  131. */
  132. jack_port_set_latency (port, driver->frames_per_cycle);
  133. driver->capture_ports = jack_slist_append (driver->capture_ports, port);
  134. }
  135. port_flags = JackPortIsInput|JackPortIsPhysical|JackPortIsTerminal;
  136. for (chn = 0; chn < driver->playback_nchannels; chn++) {
  137. //snprintf (buf, sizeof(buf) - 1, "%s:playback%lu", driver->driver_name, chn+1);
  138. snprintf (buf, sizeof(buf) - 1, "%s:in%lu", driver->driver_name, chn+1);
  139. if ((port = jack_port_register (driver->client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0)) == NULL) {
  140. jack_error ("portaudio: cannot register port for %s", buf);
  141. break;
  142. }
  143. /* XXX fix this so that it can handle: systemic (external) latency
  144. */
  145. jack_port_set_latency (port, driver->frames_per_cycle);
  146. driver->playback_ports = jack_slist_append (driver->playback_ports, port);
  147. }
  148. jack_activate (driver->client);
  149. return 0;
  150. }
  151. static int
  152. portaudio_driver_detach (portaudio_driver_t *driver, jack_engine_t *engine)
  153. {
  154. JSList *node;
  155. if (driver->engine == 0) {
  156. return -1;
  157. }
  158. for (node = driver->capture_ports; node; node = jack_slist_next (node)) {
  159. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  160. }
  161. jack_slist_free (driver->capture_ports);
  162. driver->capture_ports = 0;
  163. for (node = driver->playback_ports; node; node = jack_slist_next (node)) {
  164. jack_port_unregister (driver->client, ((jack_port_t *) node->data));
  165. }
  166. jack_slist_free (driver->playback_ports);
  167. driver->playback_ports = 0;
  168. driver->engine = 0;
  169. return 0;
  170. }
  171. static int
  172. portaudio_driver_null_cycle (portaudio_driver_t* driver, jack_nframes_t nframes)
  173. {
  174. memset(driver->outPortAudio, 0, (driver->playback_nchannels * nframes * sizeof(float)));
  175. return 0;
  176. }
  177. static int
  178. portaudio_driver_read (portaudio_driver_t *driver, jack_nframes_t nframes)
  179. {
  180. jack_default_audio_sample_t *buf;
  181. channel_t chn;
  182. jack_port_t *port;
  183. JSList *node;
  184. int i;
  185. for (chn = 0, node = driver->capture_ports; node; node = jack_slist_next (node), chn++) {
  186. port = (jack_port_t *)node->data;
  187. if (jack_port_connected (port) && (driver->inPortAudio != NULL)) {
  188. int channels = driver->capture_nchannels;
  189. float* in = driver->inPortAudio;
  190. buf = jack_port_get_buffer (port, nframes);
  191. for (i = 0; i< nframes; i++) buf[i] = in[channels*i+chn];
  192. }
  193. }
  194. driver->engine->transport_cycle_start (driver->engine,
  195. jack_get_microseconds ());
  196. return 0;
  197. }
  198. static int
  199. portaudio_driver_write (portaudio_driver_t *driver, jack_nframes_t nframes)
  200. {
  201. jack_default_audio_sample_t *buf;
  202. channel_t chn;
  203. jack_port_t *port;
  204. JSList *node;
  205. int i,bytes = nframes*sizeof(float);
  206. /* Clear in case of nothing is connected */
  207. memset(driver->outPortAudio, 0, driver->playback_nchannels*bytes);
  208. for (chn = 0, node = driver->playback_ports; node; node = jack_slist_next (node), chn++) {
  209. port = (jack_port_t *)node->data;
  210. if (jack_port_connected (port) && (driver->outPortAudio != NULL)) {
  211. int channels = driver->playback_nchannels;
  212. float* out = driver->outPortAudio;
  213. buf = jack_port_get_buffer (port, nframes);
  214. for (i = 0; i< nframes; i++) out[channels*i+chn] = buf[i];
  215. }
  216. }
  217. return 0;
  218. }
  219. static int
  220. portaudio_driver_audio_start (portaudio_driver_t *driver)
  221. {
  222. PaError err = Pa_StartStream(driver->stream);
  223. return (err != paNoError) ? -1 : 0;
  224. }
  225. static int
  226. portaudio_driver_audio_stop (portaudio_driver_t *driver)
  227. {
  228. PaError err = Pa_StopStream(driver->stream);
  229. return (err != paNoError) ? -1 : 0;
  230. }
  231. static int
  232. portaudio_driver_set_parameters (portaudio_driver_t* driver,
  233. jack_nframes_t nframes,
  234. jack_nframes_t rate)
  235. {
  236. int capturing = driver->capturing;
  237. int playing = driver->playing;
  238. int err = Pa_OpenStream(
  239. &driver->stream,
  240. ((capturing) ? Pa_GetDefaultInputDeviceID() : paNoDevice),
  241. ((capturing) ? driver->capture_nchannels : 0),
  242. paFloat32, /* 32-bit float input */
  243. NULL,
  244. ((playing) ? Pa_GetDefaultOutputDeviceID() : paNoDevice),
  245. ((playing) ? driver->playback_nchannels : 0),
  246. paFloat32, /* 32-bit float output */
  247. NULL,
  248. rate, /* sample rate */
  249. nframes, /* frames per buffer */
  250. 0, /* number of buffers = default min */
  251. paClipOff, /* we won't output out of
  252. * range samples so don't
  253. * bother clipping them */
  254. paCallback,
  255. driver);
  256. if (err == paNoError) {
  257. driver->period_usecs = (((float) driver->frames_per_cycle)
  258. / driver->frame_rate) * 1000000.0f;
  259. driver->frame_rate = rate;
  260. driver->frames_per_cycle = nframes;
  261. /* tell engine about buffer size */
  262. if (driver->engine) {
  263. driver->engine->set_buffer_size (
  264. driver->engine, driver->frames_per_cycle);
  265. }
  266. return 0;
  267. } else {
  268. // JOQ: this driver is dead. How do we terminate it?
  269. Pa_Terminate();
  270. jack_error("Unable to set portaudio parameters");
  271. jack_error("Error number: %d", err);
  272. jack_error("Error message: %s", Pa_GetErrorText(err));
  273. return EIO;
  274. }
  275. }
  276. static int
  277. portaudio_driver_reset_parameters (portaudio_driver_t* driver,
  278. jack_nframes_t nframes,
  279. jack_nframes_t rate)
  280. {
  281. if (!jack_power_of_two(nframes)) {
  282. jack_error("PA: frames must be a power of two "
  283. "(64, 512, 1024, ...)");
  284. return EINVAL;
  285. }
  286. Pa_CloseStream(driver->stream);
  287. return portaudio_driver_set_parameters (driver, nframes, rate);
  288. }
  289. static int
  290. portaudio_driver_bufsize (portaudio_driver_t* driver, jack_nframes_t nframes)
  291. {
  292. int rc;
  293. /* This gets called from the engine server thread, so it must
  294. * be serialized with the driver thread. Stopping the audio
  295. * also stops that thread. */
  296. if (portaudio_driver_audio_stop (driver)) {
  297. jack_error ("PA: cannot stop to set buffer size");
  298. return EIO;
  299. }
  300. rc = portaudio_driver_reset_parameters (driver, nframes,
  301. driver->frame_rate);
  302. if (portaudio_driver_audio_start (driver)) {
  303. jack_error ("PA: cannot restart after setting buffer size");
  304. rc = EIO;
  305. }
  306. return rc;
  307. }
  308. //== instance creation/destruction =============================================
  309. static int portaudio_load_default (portaudio_driver_t *driver,
  310. int numDevices,
  311. int capturing,
  312. int playing,
  313. int* inputDeviceID,
  314. int* outputDeviceID)
  315. {
  316. const PaDeviceInfo *pdi;
  317. int i,j;
  318. int found = 0;
  319. PALog("Look for default driver\n");
  320. *inputDeviceID = Pa_GetDefaultInputDeviceID();
  321. *outputDeviceID = Pa_GetDefaultOutputDeviceID();
  322. for(i=0; i<numDevices; i++)
  323. {
  324. pdi = Pa_GetDeviceInfo(i);
  325. PALog("---------------------------------------------- #%d\n", i);
  326. if (i == Pa_GetDefaultInputDeviceID()) {
  327. driver->capture_nchannels = (capturing) ? pdi->maxInputChannels : 0;
  328. strcpy (driver->driver_name,pdi->name);
  329. found = 1;
  330. }
  331. if (i == Pa_GetDefaultOutputDeviceID()){
  332. driver->playback_nchannels = (playing) ? pdi->maxOutputChannels : 0;
  333. strcpy (driver->driver_name,pdi->name);
  334. found = 1;
  335. }
  336. PALog("\nName = %s\n", pdi->name);
  337. PALog("Max Inputs = %d ", pdi->maxInputChannels);
  338. PALog("Max Outputs = %d\n", pdi->maxOutputChannels);
  339. if( pdi->numSampleRates == -1 ){
  340. PALog("Sample Rate Range = %f to %f\n", pdi->sampleRates[0], pdi->sampleRates[1]);
  341. }else{
  342. PALog("Sample Rates =");
  343. for(j=0; j<pdi->numSampleRates; j++){
  344. PALog(" %8.2f,", pdi->sampleRates[j]);
  345. }
  346. PALog("\n");
  347. }
  348. PALog("Native Sample Formats = ");
  349. if (pdi->nativeSampleFormats & paInt8) PALog("paInt8, ");
  350. if (pdi->nativeSampleFormats & paUInt8) PALog("paUInt8, ");
  351. if (pdi->nativeSampleFormats & paInt16) PALog("paInt16, ");
  352. if (pdi->nativeSampleFormats & paInt32) PALog("paInt32, ");
  353. if (pdi->nativeSampleFormats & paFloat32) PALog("paFloat32, ");
  354. if (pdi->nativeSampleFormats & paInt24) PALog("paInt24, ");
  355. if (pdi->nativeSampleFormats & paPackedInt24) PALog("paPackedInt24, ");
  356. PALog("\n");
  357. }
  358. return found;
  359. }
  360. static int portaudio_load_driver (portaudio_driver_t *driver,
  361. int numDevices,
  362. int capturing,
  363. int playing,
  364. int* inputDeviceID,
  365. int* outputDeviceID,
  366. char* driver_name)
  367. {
  368. const PaDeviceInfo *pdi;
  369. int found = 0;
  370. int i,j;
  371. PALog("Look for %s driver\n",driver_name);
  372. for(i=0; i<numDevices; i++)
  373. {
  374. pdi = Pa_GetDeviceInfo(i);
  375. PALog("---------------------------------------------- #%d\n", i);
  376. // compare the first character
  377. if (strncmp (driver_name, pdi->name,
  378. JACK_DRIVER_PARAM_STRING_MAX) == 0) {
  379. if (pdi->maxInputChannels > 0) {
  380. *inputDeviceID = i;
  381. driver->capture_nchannels =
  382. (capturing) ? pdi->maxInputChannels : 0;
  383. strcpy(driver->driver_name,pdi->name);
  384. PALog("Found input driver = %s\n", driver_name);
  385. found = 1;
  386. }
  387. if (pdi->maxOutputChannels > 0) {
  388. *outputDeviceID = i;
  389. driver->playback_nchannels =
  390. (playing) ? pdi->maxOutputChannels : 0;
  391. strcpy (driver->driver_name,pdi->name);
  392. PALog("Found output driver = %s\n", driver_name);
  393. found = 1;
  394. } else {
  395. PALog("Found driver without input or ouput = %s\n",
  396. driver_name);
  397. }
  398. }
  399. PALog("\nName = %s\n", pdi->name);
  400. PALog("Max Inputs = %d ", pdi->maxInputChannels);
  401. PALog("Max Outputs = %d\n", pdi->maxOutputChannels);
  402. if( pdi->numSampleRates == -1 ){
  403. PALog("Sample Rate Range = %f to %f\n", pdi->sampleRates[0],
  404. pdi->sampleRates[1]);
  405. }else{
  406. PALog("Sample Rates =");
  407. for(j=0; j<pdi->numSampleRates; j++){
  408. PALog(" %8.2f,", pdi->sampleRates[j]);
  409. }
  410. PALog("\n");
  411. }
  412. PALog("Native Sample Formats = ");
  413. if (pdi->nativeSampleFormats & paInt8) PALog("paInt8, ");
  414. if (pdi->nativeSampleFormats & paUInt8) PALog("paUInt8, ");
  415. if (pdi->nativeSampleFormats & paInt16) PALog("paInt16, ");
  416. if (pdi->nativeSampleFormats & paInt32) PALog("paInt32, ");
  417. if (pdi->nativeSampleFormats & paFloat32) PALog("paFloat32, ");
  418. if (pdi->nativeSampleFormats & paInt24) PALog("paInt24, ");
  419. if (pdi->nativeSampleFormats & paPackedInt24) PALog("paPackedInt24, ");
  420. PALog("\n");
  421. }
  422. return found;
  423. }
  424. /** create a new driver instance
  425. */
  426. static jack_driver_t *
  427. portaudio_driver_new (char *name,
  428. jack_client_t* client,
  429. jack_nframes_t frames_per_cycle,
  430. jack_nframes_t rate,
  431. int capturing,
  432. int playing,
  433. int chan_in,
  434. int chan_out,
  435. DitherAlgorithm dither,
  436. char* driver_name)
  437. {
  438. portaudio_driver_t *driver;
  439. PaError err = paNoError;
  440. int numDevices;
  441. int inputDeviceID,outputDeviceID;
  442. int found;
  443. PALog("portaudio driver version : %d\n", kVersion);
  444. PALog("creating portaudio driver ... %" PRIu32 "|%" PRIu32 "\n",
  445. frames_per_cycle, rate);
  446. driver = (portaudio_driver_t *) calloc (1, sizeof (portaudio_driver_t));
  447. jack_driver_init ((jack_driver_t *) driver);
  448. if (!jack_power_of_two(frames_per_cycle)) {
  449. jack_error ("PA: -p must be a power of two.");
  450. goto error;
  451. }
  452. driver->frames_per_cycle = frames_per_cycle;
  453. driver->frame_rate = rate;
  454. driver->capturing = capturing;
  455. driver->playing = playing;
  456. driver->attach = (JackDriverAttachFunction) portaudio_driver_attach;
  457. driver->detach = (JackDriverDetachFunction) portaudio_driver_detach;
  458. driver->read = (JackDriverReadFunction) portaudio_driver_read;
  459. driver->write = (JackDriverReadFunction) portaudio_driver_write;
  460. driver->null_cycle = (JackDriverNullCycleFunction) portaudio_driver_null_cycle;
  461. driver->bufsize = (JackDriverBufSizeFunction) portaudio_driver_bufsize;
  462. driver->start = (JackDriverStartFunction) portaudio_driver_audio_start;
  463. driver->stop = (JackDriverStopFunction) portaudio_driver_audio_stop;
  464. driver->stream = NULL;
  465. #ifdef JACK_USE_MACH_THREADS
  466. AudioDeviceID device_id;
  467. if (driver_name) {
  468. if (get_device_id_from_uid(driver_name, &device_id) != noErr)
  469. goto error;
  470. if (get_device_name_from_id(device_id, driver->driver_name) != noErr)
  471. goto error;
  472. } else {
  473. if (get_device_id_from_num(0, &device_id) != noErr)
  474. goto error;
  475. if (get_device_name_from_id(device_id, driver->driver_name) != noErr)
  476. goto error;
  477. }
  478. #endif
  479. err = Pa_Initialize();
  480. PALog("Pa_Initialize OK \n");
  481. PALog("Driver name required %s\n",driver->driver_name);
  482. numDevices = Pa_CountDevices();
  483. if( numDevices < 0 ){
  484. PALog("ERROR: Pa_CountDevices returned 0x%x\n", numDevices);
  485. err = numDevices;
  486. goto error;
  487. }
  488. PALog("Number of devices = %d\n", numDevices);
  489. if (strcmp(driver->driver_name,"") == 0) {
  490. found = portaudio_load_default(driver,numDevices,capturing,playing,&inputDeviceID,&outputDeviceID);
  491. if (!found) {
  492. PALog("ERROR : default driver has not been found\n");
  493. err = paHostError;
  494. goto error;
  495. }
  496. }else{
  497. found = portaudio_load_driver(driver,numDevices,capturing,playing,&inputDeviceID,&outputDeviceID,driver->driver_name);
  498. if (!found) {
  499. PALog("ERROR : driver %s has not been found \n",driver->driver_name);
  500. err = paHostError;
  501. goto error;
  502. }
  503. }
  504. if (err != paNoError) goto error;
  505. PALog("Pa_GetDefaultOutputDeviceID() %ld\n", (long)Pa_GetDefaultOutputDeviceID());
  506. PALog("Pa_GetDefaultInputDeviceID() %ld\n", (long)Pa_GetDefaultInputDeviceID());
  507. PALog("--------------------------------------------------\n");
  508. PALog("CoreAudio driver %s will be loaded\n", driver->driver_name);
  509. PALog("inputDeviceID %ld\n", (long)inputDeviceID);
  510. PALog("outputDeviceID %ld\n", (long)outputDeviceID);
  511. PALog("driver->capture_nchannels %ld\n", driver->capture_nchannels);
  512. PALog("driver->playback_nchannels %ld\n", driver->playback_nchannels);
  513. PALog("chan_in, chan_out %ld %ld\n", (long)chan_in, (long)chan_out);
  514. if (chan_in > 0)
  515. driver->capture_nchannels = (driver->capture_nchannels < chan_in) ? driver->capture_nchannels : chan_in;
  516. if (chan_out > 0)
  517. driver->playback_nchannels = (driver->playback_nchannels < chan_out) ? driver->playback_nchannels : chan_out;
  518. PALog("driver->capture_nchannels %ld\n", driver->capture_nchannels);
  519. PALog("driver->playback_nchannels %ld\n", driver->playback_nchannels);
  520. err = Pa_OpenStream(&driver->stream,
  521. ((capturing && (driver->capture_nchannels > 0)) ? inputDeviceID : paNoDevice),
  522. ((capturing) ? driver->capture_nchannels : 0),
  523. paFloat32, // 32 bit floating point input
  524. NULL,
  525. ((playing && (driver->playback_nchannels > 0)) ? outputDeviceID : paNoDevice),
  526. ((playing) ? driver->playback_nchannels : 0),
  527. paFloat32, // 32 bit floating point output
  528. NULL,
  529. rate,
  530. frames_per_cycle, // frames per buffer
  531. 0, // number of buffers, if zero then use default minimum
  532. paClipOff, // we won't output out of range samples so don't bother clipping them
  533. paCallback,
  534. driver);
  535. if (err != paNoError) goto error;
  536. driver->client = client;
  537. driver->period_usecs = (((float) driver->frames_per_cycle) / driver->frame_rate) * 1000000.0f;
  538. return((jack_driver_t *) driver);
  539. error:
  540. Pa_Terminate();
  541. jack_error("An error occured while using the portaudio stream");
  542. jack_error("Error number: %d", err);
  543. jack_error("Error message: %s", Pa_GetErrorText(err));
  544. free(driver);
  545. return NULL;
  546. }
  547. /** free all memory allocated by a driver instance
  548. */
  549. static void
  550. portaudio_driver_delete (portaudio_driver_t *driver)
  551. {
  552. /* Close PortAudio stream and terminate */
  553. Pa_CloseStream(driver->stream);
  554. Pa_Terminate();
  555. free(driver);
  556. }
  557. //== driver "plugin" interface =================================================
  558. /* DRIVER "PLUGIN" INTERFACE */
  559. jack_driver_desc_t *
  560. driver_get_descriptor ()
  561. {
  562. jack_driver_desc_t * desc;
  563. unsigned int i;
  564. desc = calloc (1, sizeof (jack_driver_desc_t));
  565. strcpy (desc->name, "portaudio");
  566. desc->nparams = 10;
  567. desc->params = calloc (desc->nparams,
  568. sizeof (jack_driver_param_desc_t));
  569. i = 0;
  570. strcpy (desc->params[i].name, "channel");
  571. desc->params[i].character = 'c';
  572. desc->params[i].type = JackDriverParamInt;
  573. desc->params[i].value.ui = 0;
  574. strcpy (desc->params[i].short_desc, "Maximum number of channels");
  575. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  576. i++;
  577. strcpy (desc->params[i].name, "channelin");
  578. desc->params[i].character = 'i';
  579. desc->params[i].type = JackDriverParamInt;
  580. desc->params[i].value.ui = 0;
  581. strcpy (desc->params[i].short_desc, "Maximum number of input channels");
  582. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  583. i++;
  584. strcpy (desc->params[i].name, "channelout");
  585. desc->params[i].character = 'o';
  586. desc->params[i].type = JackDriverParamInt;
  587. desc->params[i].value.ui = 0;
  588. strcpy (desc->params[i].short_desc, "Maximum number of ouput channels");
  589. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  590. i++;
  591. strcpy (desc->params[i].name, "capture");
  592. desc->params[i].character = 'C';
  593. desc->params[i].type = JackDriverParamBool;
  594. desc->params[i].value.i = TRUE;
  595. strcpy (desc->params[i].short_desc, "Whether or not to capture");
  596. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  597. i++;
  598. strcpy (desc->params[i].name, "playback");
  599. desc->params[i].character = 'P';
  600. desc->params[i].type = JackDriverParamBool;
  601. desc->params[i].value.i = TRUE;
  602. strcpy (desc->params[i].short_desc, "Whether or not to playback");
  603. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  604. i++;
  605. strcpy (desc->params[i].name, "duplex");
  606. desc->params[i].character = 'D';
  607. desc->params[i].type = JackDriverParamBool;
  608. desc->params[i].value.i = TRUE;
  609. strcpy (desc->params[i].short_desc, "Capture and playback");
  610. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  611. i++;
  612. strcpy (desc->params[i].name, "rate");
  613. desc->params[i].character = 'r';
  614. desc->params[i].type = JackDriverParamUInt;
  615. desc->params[i].value.ui = 48000U;
  616. strcpy (desc->params[i].short_desc, "Sample rate");
  617. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  618. i++;
  619. strcpy (desc->params[i].name, "period");
  620. desc->params[i].character = 'p';
  621. desc->params[i].type = JackDriverParamUInt;
  622. desc->params[i].value.ui = 1024U;
  623. strcpy (desc->params[i].short_desc, "Frames per period");
  624. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  625. i++;
  626. strcpy (desc->params[i].name, "name");
  627. desc->params[i].character = 'n';
  628. desc->params[i].type = JackDriverParamString;
  629. desc->params[i].value.ui = 128U;
  630. strcpy (desc->params[i].short_desc, "Driver name");
  631. strcpy (desc->params[i].long_desc, desc->params[i].short_desc);
  632. i++;
  633. strcpy (desc->params[i].name, "dither");
  634. desc->params[i].character = 'z';
  635. desc->params[i].type = JackDriverParamChar;
  636. desc->params[i].value.c = '-';
  637. strcpy (desc->params[i].short_desc, "Dithering mode");
  638. strcpy (desc->params[i].long_desc,
  639. " Dithering Mode:\n"
  640. " r : rectangular\n"
  641. " t : triangular\n"
  642. " s : shaped\n"
  643. " - : no dithering");
  644. return desc;
  645. }
  646. const char driver_client_name[] = "portaudio";
  647. jack_driver_t *
  648. driver_initialize (jack_client_t *client, const JSList * params)
  649. {
  650. jack_nframes_t srate = 48000;
  651. jack_nframes_t frames_per_interrupt = 1024;
  652. AudioDeviceID deviceID = 0;
  653. int capture = FALSE;
  654. int playback = FALSE;
  655. int chan_in = -1;
  656. int chan_out = -1;
  657. DitherAlgorithm dither = None;
  658. const JSList * node;
  659. const jack_driver_param_t * param;
  660. char *name = NULL;
  661. #ifdef JACK_USE_MACH_THREADS
  662. get_device_id_from_num(0,&deviceID); // takes a default value (first device)
  663. #endif
  664. for (node = params; node; node = jack_slist_next (node)) {
  665. param = (const jack_driver_param_t *) node->data;
  666. switch (param->character) {
  667. case 'n':
  668. name = (char *) param->value.str;
  669. PALog("Driver name found %s\n",name);
  670. break;
  671. case 'D':
  672. capture = TRUE;
  673. playback = TRUE;
  674. break;
  675. case 'c':
  676. chan_in = (int) param->value.ui;
  677. chan_out = (int) param->value.ui;
  678. break;
  679. case 'i':
  680. chan_in = (int) param->value.ui;
  681. break;
  682. case 'o':
  683. chan_out = (int) param->value.ui;
  684. break;
  685. case 'C':
  686. capture = param->value.i;
  687. break;
  688. case 'P':
  689. playback = param->value.i;
  690. break;
  691. case 'r':
  692. srate = param->value.ui;
  693. break;
  694. case 'p':
  695. frames_per_interrupt = (unsigned int) param->value.ui;
  696. break;
  697. case 'z':
  698. switch ((int) param->value.c) {
  699. case '-':
  700. dither = None;
  701. break;
  702. case 'r':
  703. dither = Rectangular;
  704. break;
  705. case 's':
  706. dither = Shaped;
  707. break;
  708. case 't':
  709. default:
  710. dither = Triangular;
  711. break;
  712. }
  713. break;
  714. }
  715. }
  716. /* duplex is the default */
  717. if (!capture && !playback) {
  718. capture = TRUE;
  719. playback = TRUE;
  720. }
  721. return portaudio_driver_new ("portaudio", client, frames_per_interrupt,
  722. srate, capture, playback, chan_in,
  723. chan_out, dither, name);
  724. }
  725. void
  726. driver_finish (jack_driver_t *driver)
  727. {
  728. portaudio_driver_delete ((portaudio_driver_t *) driver);
  729. }