jack2 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.

727 lines
26KB

  1. /*
  2. Copyright (C) 2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #if defined(HAVE_CONFIG_H)
  16. #include "config.h"
  17. #endif
  18. #include "JackCoreAudioAdapter.h"
  19. #include "JackError.h"
  20. #include <unistd.h>
  21. namespace Jack
  22. {
  23. static void printError(OSStatus err)
  24. {
  25. switch (err) {
  26. case kAudioHardwareNoError:
  27. jack_log("error code : kAudioHardwareNoError");
  28. break;
  29. case kAudioConverterErr_FormatNotSupported:
  30. jack_log("error code : kAudioConverterErr_FormatNotSupported");
  31. break;
  32. case kAudioConverterErr_OperationNotSupported:
  33. jack_log("error code : kAudioConverterErr_OperationNotSupported");
  34. break;
  35. case kAudioConverterErr_PropertyNotSupported:
  36. jack_log("error code : kAudioConverterErr_PropertyNotSupported");
  37. break;
  38. case kAudioConverterErr_InvalidInputSize:
  39. jack_log("error code : kAudioConverterErr_InvalidInputSize");
  40. break;
  41. case kAudioConverterErr_InvalidOutputSize:
  42. jack_log("error code : kAudioConverterErr_InvalidOutputSize");
  43. break;
  44. case kAudioConverterErr_UnspecifiedError:
  45. jack_log("error code : kAudioConverterErr_UnspecifiedError");
  46. break;
  47. case kAudioConverterErr_BadPropertySizeError:
  48. jack_log("error code : kAudioConverterErr_BadPropertySizeError");
  49. break;
  50. case kAudioConverterErr_RequiresPacketDescriptionsError:
  51. jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
  52. break;
  53. case kAudioConverterErr_InputSampleRateOutOfRange:
  54. jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
  55. break;
  56. case kAudioConverterErr_OutputSampleRateOutOfRange:
  57. jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
  58. break;
  59. case kAudioHardwareNotRunningError:
  60. jack_log("error code : kAudioHardwareNotRunningError");
  61. break;
  62. case kAudioHardwareUnknownPropertyError:
  63. jack_log("error code : kAudioHardwareUnknownPropertyError");
  64. break;
  65. case kAudioHardwareIllegalOperationError:
  66. jack_log("error code : kAudioHardwareIllegalOperationError");
  67. break;
  68. case kAudioHardwareBadDeviceError:
  69. jack_log("error code : kAudioHardwareBadDeviceError");
  70. break;
  71. case kAudioHardwareBadStreamError:
  72. jack_log("error code : kAudioHardwareBadStreamError");
  73. break;
  74. case kAudioDeviceUnsupportedFormatError:
  75. jack_log("error code : kAudioDeviceUnsupportedFormatError");
  76. break;
  77. case kAudioDevicePermissionsError:
  78. jack_log("error code : kAudioDevicePermissionsError");
  79. break;
  80. case kAudioHardwareBadObjectError:
  81. jack_log("error code : kAudioHardwareBadObjectError");
  82. break;
  83. case kAudioHardwareUnsupportedOperationError:
  84. jack_log("error code : kAudioHardwareUnsupportedOperationError");
  85. break;
  86. default:
  87. jack_log("error code : unknown");
  88. break;
  89. }
  90. }
  91. OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
  92. UInt32 inChannel,
  93. Boolean isInput,
  94. AudioDevicePropertyID inPropertyID,
  95. void* inClientData)
  96. {
  97. JackCoreAudioAdapter* driver = static_cast<JackCoreAudioAdapter*>(inClientData);
  98. switch (inPropertyID) {
  99. case kAudioDevicePropertyNominalSampleRate: {
  100. jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
  101. driver->fState = true;
  102. break;
  103. }
  104. }
  105. return noErr;
  106. }
  107. OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
  108. AudioUnitRenderActionFlags *ioActionFlags,
  109. const AudioTimeStamp *inTimeStamp,
  110. UInt32 inBusNumber,
  111. UInt32 inNumberFrames,
  112. AudioBufferList *ioData)
  113. {
  114. JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
  115. AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
  116. bool failure = false;
  117. jack_nframes_t time1, time2;
  118. adapter->ResampleFactor(time1, time2);
  119. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  120. adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
  121. if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
  122. failure = true;
  123. }
  124. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  125. adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  126. if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
  127. failure = true;
  128. }
  129. #ifdef JACK_MONITOR
  130. adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
  131. adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
  132. #endif
  133. // Reset all ringbuffers in case of failure
  134. if (failure) {
  135. jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset");
  136. adapter->ResetRingBuffers();
  137. }
  138. return noErr;
  139. }
  140. JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  141. :JackAudioAdapterInterface(buffer_size, sample_rate),fInputData(0),fState(false)
  142. {
  143. const JSList* node;
  144. const jack_driver_param_t* param;
  145. fCaptureChannels = 2;
  146. fPlaybackChannels = 2;
  147. for (node = params; node; node = jack_slist_next(node)) {
  148. param = (const jack_driver_param_t*) node->data;
  149. switch (param->character) {
  150. case 'c' :
  151. break;
  152. case 'i':
  153. fCaptureChannels = param->value.ui;
  154. break;
  155. case 'o':
  156. fPlaybackChannels = param->value.ui;
  157. break;
  158. case 'C':
  159. break;
  160. case 'P':
  161. break;
  162. case 'D':
  163. break;
  164. case 'r':
  165. SetAdaptedSampleRate(param->value.ui);
  166. break;
  167. case 'p':
  168. SetAdaptedBufferSize(param->value.ui);
  169. break;
  170. case 'l':
  171. break;
  172. }
  173. }
  174. }
  175. OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
  176. {
  177. OSStatus res;
  178. UInt32 theSize = sizeof(UInt32);
  179. AudioDeviceID inDefault;
  180. AudioDeviceID outDefault;
  181. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  182. return res;
  183. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  184. return res;
  185. jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
  186. // Get the device only if default input and ouput are the same
  187. if (inDefault == outDefault) {
  188. *id = inDefault;
  189. return noErr;
  190. } else {
  191. jack_error("Default input and output devices are not the same !!");
  192. return kAudioHardwareBadDeviceError;
  193. }
  194. }
  195. OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput)
  196. {
  197. OSStatus err = noErr;
  198. UInt32 outSize;
  199. Boolean outWritable;
  200. AudioBufferList* bufferList = 0;
  201. *channelCount = 0;
  202. err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
  203. if (err == noErr) {
  204. bufferList = (AudioBufferList*)malloc(outSize);
  205. err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
  206. if (err == noErr) {
  207. for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
  208. *channelCount += bufferList->mBuffers[i].mNumberChannels;
  209. }
  210. if (bufferList)
  211. free(bufferList);
  212. }
  213. return err;
  214. }
  215. // Setup
  216. int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
  217. const char* playback_driver_uid,
  218. char* capture_driver_name,
  219. char* playback_driver_name)
  220. {
  221. if (GetDefaultDevice(&fDeviceID) != noErr) {
  222. jack_error("Cannot open default device");
  223. return -1;
  224. }
  225. return 0;
  226. }
  227. int JackCoreAudioAdapter::SetupChannels(bool capturing,
  228. bool playing,
  229. int& inchannels,
  230. int& outchannels,
  231. int& in_nChannels,
  232. int& out_nChannels,
  233. bool strict)
  234. {
  235. OSStatus err = noErr;
  236. err = GetTotalChannels(fDeviceID, &in_nChannels, true);
  237. if (err != noErr) {
  238. jack_error("Cannot get input channel number");
  239. printError(err);
  240. return -1;
  241. }
  242. err = GetTotalChannels(fDeviceID, &out_nChannels, false);
  243. if (err != noErr) {
  244. jack_error("Cannot get output channel number");
  245. printError(err);
  246. return -1;
  247. }
  248. return 0;
  249. }
  250. int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
  251. {
  252. OSStatus err = noErr;
  253. UInt32 outSize;
  254. Float64 sampleRate;
  255. // Setting buffer size
  256. outSize = sizeof(UInt32);
  257. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
  258. if (err != noErr) {
  259. jack_error("Cannot set buffer size %ld", nframes);
  260. printError(err);
  261. return -1;
  262. }
  263. // Get sample rate
  264. outSize = sizeof(Float64);
  265. err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  266. if (err != noErr) {
  267. jack_error("Cannot get current sample rate");
  268. printError(err);
  269. return -1;
  270. }
  271. // If needed, set new sample rate
  272. if (samplerate != (jack_nframes_t)sampleRate) {
  273. sampleRate = (Float64)samplerate;
  274. // To get SR change notification
  275. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
  276. if (err != noErr) {
  277. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  278. printError(err);
  279. return -1;
  280. }
  281. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
  282. if (err != noErr) {
  283. jack_error("Cannot set sample rate = %ld", samplerate);
  284. printError(err);
  285. return -1;
  286. }
  287. // Waiting for SR change notification
  288. int count = 0;
  289. while (!fState && count++ < 100) {
  290. usleep(100000);
  291. jack_log("Wait count = %ld", count);
  292. }
  293. // Remove SR change notification
  294. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
  295. }
  296. return 0;
  297. }
  298. int JackCoreAudioAdapter::SetupBuffers(int inchannels, int outchannels)
  299. {
  300. jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels);
  301. // Prepare buffers
  302. fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
  303. if (fInputData == 0) {
  304. jack_error("Cannot allocate memory for input buffers");
  305. return -1;
  306. }
  307. fInputData->mNumberBuffers = inchannels;
  308. for (int i = 0; i < fCaptureChannels; i++) {
  309. fInputData->mBuffers[i].mNumberChannels = 1;
  310. fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float);
  311. fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float));
  312. }
  313. return 0;
  314. }
  315. void JackCoreAudioAdapter::DisposeBuffers()
  316. {
  317. if (fInputData) {
  318. for (int i = 0; i < fCaptureChannels; i++)
  319. free(fInputData->mBuffers[i].mData);
  320. free(fInputData);
  321. fInputData = 0;
  322. }
  323. }
  324. int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
  325. bool playing,
  326. int inchannels,
  327. int outchannels,
  328. int in_nChannels,
  329. int out_nChannels,
  330. jack_nframes_t nframes,
  331. jack_nframes_t samplerate,
  332. bool strict)
  333. {
  334. ComponentResult err1;
  335. UInt32 enableIO;
  336. AudioStreamBasicDescription srcFormat, dstFormat;
  337. jack_log("OpenAUHAL capturing = %ld playing = %ld playing = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld ", capturing, playing, inchannels, inchannels, in_nChannels, out_nChannels);
  338. // AUHAL
  339. ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
  340. Component HALOutput = FindNextComponent(NULL, &cd);
  341. err1 = OpenAComponent(HALOutput, &fAUHAL);
  342. if (err1 != noErr) {
  343. jack_error("Error calling OpenAComponent");
  344. printError(err1);
  345. return -1;
  346. }
  347. err1 = AudioUnitInitialize(fAUHAL);
  348. if (err1 != noErr) {
  349. jack_error("Cannot initialize AUHAL unit");
  350. printError(err1);
  351. return -1;
  352. }
  353. // Start I/O
  354. enableIO = 1;
  355. if (capturing && inchannels > 0) {
  356. jack_log("Setup AUHAL input");
  357. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
  358. if (err1 != noErr) {
  359. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
  360. printError(err1);
  361. if (strict)
  362. return -1;
  363. }
  364. }
  365. if (playing && outchannels > 0) {
  366. jack_log("Setup AUHAL output");
  367. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
  368. if (err1 != noErr) {
  369. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
  370. printError(err1);
  371. if (strict)
  372. return -1;
  373. }
  374. }
  375. // Setup up choosen device, in both input and output cases
  376. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
  377. if (err1 != noErr) {
  378. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
  379. printError(err1);
  380. if (strict)
  381. return -1;
  382. }
  383. // Set buffer size
  384. if (capturing && inchannels > 0) {
  385. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
  386. if (err1 != noErr) {
  387. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  388. printError(err1);
  389. if (strict)
  390. return -1;
  391. }
  392. }
  393. if (playing && outchannels > 0) {
  394. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
  395. if (err1 != noErr) {
  396. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  397. printError(err1);
  398. if (strict)
  399. return -1;
  400. }
  401. }
  402. // Setup channel map
  403. if (capturing && inchannels > 0 && inchannels < in_nChannels) {
  404. SInt32 chanArr[in_nChannels];
  405. for (int i = 0; i < in_nChannels; i++) {
  406. chanArr[i] = -1;
  407. }
  408. for (int i = 0; i < inchannels; i++) {
  409. chanArr[i] = i;
  410. }
  411. AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
  412. if (err1 != noErr) {
  413. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
  414. printError(err1);
  415. }
  416. }
  417. if (playing && outchannels > 0 && outchannels < out_nChannels) {
  418. SInt32 chanArr[out_nChannels];
  419. for (int i = 0; i < out_nChannels; i++) {
  420. chanArr[i] = -1;
  421. }
  422. for (int i = 0; i < outchannels; i++) {
  423. chanArr[i] = i;
  424. }
  425. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
  426. if (err1 != noErr) {
  427. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
  428. printError(err1);
  429. }
  430. }
  431. // Setup stream converters
  432. jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
  433. srcFormat.mSampleRate = samplerate;
  434. srcFormat.mFormatID = kAudioFormatLinearPCM;
  435. srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  436. srcFormat.mBytesPerPacket = sizeof(float);
  437. srcFormat.mFramesPerPacket = 1;
  438. srcFormat.mBytesPerFrame = sizeof(float);
  439. srcFormat.mChannelsPerFrame = outchannels;
  440. srcFormat.mBitsPerChannel = 32;
  441. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
  442. if (err1 != noErr) {
  443. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
  444. printError(err1);
  445. }
  446. jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
  447. dstFormat.mSampleRate = samplerate;
  448. dstFormat.mFormatID = kAudioFormatLinearPCM;
  449. dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  450. dstFormat.mBytesPerPacket = sizeof(float);
  451. dstFormat.mFramesPerPacket = 1;
  452. dstFormat.mBytesPerFrame = sizeof(float);
  453. dstFormat.mChannelsPerFrame = inchannels;
  454. dstFormat.mBitsPerChannel = 32;
  455. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
  456. if (err1 != noErr) {
  457. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
  458. printError(err1);
  459. }
  460. // Setup callbacks
  461. if (inchannels > 0 && outchannels == 0) {
  462. AURenderCallbackStruct output;
  463. output.inputProc = Render;
  464. output.inputProcRefCon = this;
  465. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
  466. if (err1 != noErr) {
  467. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
  468. printError(err1);
  469. return -1;
  470. }
  471. } else {
  472. AURenderCallbackStruct output;
  473. output.inputProc = Render;
  474. output.inputProcRefCon = this;
  475. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
  476. if (err1 != noErr) {
  477. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
  478. printError(err1);
  479. return -1;
  480. }
  481. }
  482. return 0;
  483. }
  484. void JackCoreAudioAdapter::CloseAUHAL()
  485. {
  486. AudioUnitUninitialize(fAUHAL);
  487. CloseComponent(fAUHAL);
  488. }
  489. int JackCoreAudioAdapter::Open()
  490. {
  491. OSStatus err;
  492. int in_nChannels = 0;
  493. int out_nChannels = 0;
  494. if (SetupDevices("", "", "", "") < 0)
  495. return -1;
  496. if (SetupChannels(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
  497. return -1;
  498. if (SetupBufferSizeAndSampleRate(fAdaptedBufferSize, fAdaptedSampleRate) < 0)
  499. return -1;
  500. if (OpenAUHAL(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate, true) < 0)
  501. goto error;
  502. if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0)
  503. goto error;
  504. err = AudioOutputUnitStart(fAUHAL);
  505. if (err != noErr)
  506. goto error;
  507. return 0;
  508. error:
  509. Close();
  510. return -1;
  511. }
  512. int JackCoreAudioAdapter::Close()
  513. {
  514. #ifdef JACK_MONITOR
  515. fTable.Save();
  516. #endif
  517. AudioOutputUnitStop(fAUHAL);
  518. DisposeBuffers();
  519. CloseAUHAL();
  520. return 0;
  521. }
  522. int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
  523. JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
  524. Close();
  525. return Open();
  526. }
  527. int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
  528. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  529. Close();
  530. return Open();
  531. }
  532. } // namespace
  533. #ifdef __cplusplus
  534. extern "C"
  535. {
  536. #endif
  537. EXPORT jack_driver_desc_t* jack_get_descriptor()
  538. {
  539. jack_driver_desc_t *desc;
  540. unsigned int i;
  541. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  542. strcpy(desc->name, "coreaudio-adapter");
  543. desc->nparams = 10;
  544. desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  545. i = 0;
  546. strcpy(desc->params[i].name, "channels");
  547. desc->params[i].character = 'c';
  548. desc->params[i].type = JackDriverParamInt;
  549. desc->params[i].value.ui = 0;
  550. strcpy(desc->params[i].short_desc, "Maximum number of channels");
  551. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  552. i++;
  553. strcpy(desc->params[i].name, "inchannels");
  554. desc->params[i].character = 'i';
  555. desc->params[i].type = JackDriverParamInt;
  556. desc->params[i].value.ui = 0;
  557. strcpy(desc->params[i].short_desc, "Maximum number of input channels");
  558. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  559. i++;
  560. strcpy(desc->params[i].name, "outchannels");
  561. desc->params[i].character = 'o';
  562. desc->params[i].type = JackDriverParamInt;
  563. desc->params[i].value.ui = 0;
  564. strcpy(desc->params[i].short_desc, "Maximum number of output channels");
  565. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  566. i++;
  567. strcpy(desc->params[i].name, "capture");
  568. desc->params[i].character = 'C';
  569. desc->params[i].type = JackDriverParamString;
  570. strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
  571. strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
  572. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  573. i++;
  574. strcpy(desc->params[i].name, "playback");
  575. desc->params[i].character = 'P';
  576. desc->params[i].type = JackDriverParamString;
  577. strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
  578. strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
  579. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  580. i++;
  581. strcpy(desc->params[i].name, "rate");
  582. desc->params[i].character = 'r';
  583. desc->params[i].type = JackDriverParamUInt;
  584. desc->params[i].value.ui = 44100U;
  585. strcpy(desc->params[i].short_desc, "Sample rate");
  586. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  587. i++;
  588. strcpy(desc->params[i].name, "periodsize");
  589. desc->params[i].character = 'p';
  590. desc->params[i].type = JackDriverParamUInt;
  591. desc->params[i].value.ui = 512U;
  592. strcpy(desc->params[i].short_desc, "Period size");
  593. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  594. i++;
  595. strcpy(desc->params[i].name, "duplex");
  596. desc->params[i].character = 'D';
  597. desc->params[i].type = JackDriverParamBool;
  598. desc->params[i].value.i = TRUE;
  599. strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
  600. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  601. i++;
  602. strcpy(desc->params[i].name, "device");
  603. desc->params[i].character = 'd';
  604. desc->params[i].type = JackDriverParamString;
  605. strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
  606. strcpy(desc->params[i].short_desc, "CoreAudio device name");
  607. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  608. i++;
  609. strcpy(desc->params[i].name, "list-devices");
  610. desc->params[i].character = 'l';
  611. desc->params[i].type = JackDriverParamBool;
  612. desc->params[i].value.i = TRUE;
  613. strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
  614. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  615. return desc;
  616. }
  617. #ifdef __cplusplus
  618. }
  619. #endif