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.

608 lines
22KB

  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. #include "JackCoreAudioIOAdapter.h"
  16. #include "JackError.h"
  17. #include <unistd.h>
  18. namespace Jack
  19. {
  20. static void printError(OSStatus err)
  21. {
  22. switch (err) {
  23. case kAudioHardwareNoError:
  24. jack_log("error code : kAudioHardwareNoError");
  25. break;
  26. case kAudioConverterErr_FormatNotSupported:
  27. jack_log("error code : kAudioConverterErr_FormatNotSupported");
  28. break;
  29. case kAudioConverterErr_OperationNotSupported:
  30. jack_log("error code : kAudioConverterErr_OperationNotSupported");
  31. break;
  32. case kAudioConverterErr_PropertyNotSupported:
  33. jack_log("error code : kAudioConverterErr_PropertyNotSupported");
  34. break;
  35. case kAudioConverterErr_InvalidInputSize:
  36. jack_log("error code : kAudioConverterErr_InvalidInputSize");
  37. break;
  38. case kAudioConverterErr_InvalidOutputSize:
  39. jack_log("error code : kAudioConverterErr_InvalidOutputSize");
  40. break;
  41. case kAudioConverterErr_UnspecifiedError:
  42. jack_log("error code : kAudioConverterErr_UnspecifiedError");
  43. break;
  44. case kAudioConverterErr_BadPropertySizeError:
  45. jack_log("error code : kAudioConverterErr_BadPropertySizeError");
  46. break;
  47. case kAudioConverterErr_RequiresPacketDescriptionsError:
  48. jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
  49. break;
  50. case kAudioConverterErr_InputSampleRateOutOfRange:
  51. jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
  52. break;
  53. case kAudioConverterErr_OutputSampleRateOutOfRange:
  54. jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
  55. break;
  56. case kAudioHardwareNotRunningError:
  57. jack_log("error code : kAudioHardwareNotRunningError");
  58. break;
  59. case kAudioHardwareUnknownPropertyError:
  60. jack_log("error code : kAudioHardwareUnknownPropertyError");
  61. break;
  62. case kAudioHardwareIllegalOperationError:
  63. jack_log("error code : kAudioHardwareIllegalOperationError");
  64. break;
  65. case kAudioHardwareBadDeviceError:
  66. jack_log("error code : kAudioHardwareBadDeviceError");
  67. break;
  68. case kAudioHardwareBadStreamError:
  69. jack_log("error code : kAudioHardwareBadStreamError");
  70. break;
  71. case kAudioDeviceUnsupportedFormatError:
  72. jack_log("error code : kAudioDeviceUnsupportedFormatError");
  73. break;
  74. case kAudioDevicePermissionsError:
  75. jack_log("error code : kAudioDevicePermissionsError");
  76. break;
  77. case kAudioHardwareBadObjectError:
  78. jack_log("error code : kAudioHardwareBadObjectError");
  79. break;
  80. case kAudioHardwareUnsupportedOperationError:
  81. jack_log("error code : kAudioHardwareUnsupportedOperationError");
  82. break;
  83. default:
  84. jack_log("error code : unknown");
  85. break;
  86. }
  87. }
  88. OSStatus JackCoreAudioIOAdapter::SRNotificationCallback(AudioDeviceID inDevice,
  89. UInt32 inChannel,
  90. Boolean isInput,
  91. AudioDevicePropertyID inPropertyID,
  92. void* inClientData)
  93. {
  94. JackCoreAudioIOAdapter* driver = static_cast<JackCoreAudioIOAdapter*>(inClientData);
  95. switch (inPropertyID) {
  96. case kAudioDevicePropertyNominalSampleRate: {
  97. jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
  98. driver->fState = true;
  99. break;
  100. }
  101. }
  102. return noErr;
  103. }
  104. OSStatus JackCoreAudioIOAdapter::Render(void *inRefCon,
  105. AudioUnitRenderActionFlags *ioActionFlags,
  106. const AudioTimeStamp *inTimeStamp,
  107. UInt32 inBusNumber,
  108. UInt32 inNumberFrames,
  109. AudioBufferList *ioData)
  110. {
  111. JackCoreAudioIOAdapter* adapter = static_cast<JackCoreAudioIOAdapter*>(inRefCon);
  112. jack_log("JackCoreAudioIOAdapter::Render inNumberFrames %ld", inNumberFrames);
  113. AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
  114. /*
  115. adapter->fLastCallbackTime = adapter->fCurCallbackTime;
  116. adapter->fCurCallbackTime = jack_get_time();
  117. adapter->fConsumerFilter.AddValue(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  118. adapter->fProducerFilter.AddValue(adapter->fDeltaTime);
  119. */
  120. //jack_log("JackCoreAudioIOAdapter::Render delta %ld", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  121. //printf("JackCoreAudioIOAdapter::Render delta %ld\n", adapter->fCurCallbackTime - adapter->fLastCallbackTime);
  122. if (!adapter->fRunning) {
  123. adapter->fRunning = true;
  124. jack_time_t time = jack_get_time();
  125. adapter->fProducerDLL.Init(time);
  126. adapter->fConsumerDLL.Init(time);
  127. }
  128. // DLL based
  129. //adapter->fConsumerDLL.IncFrame(adapter->fConsumerTime);
  130. jack_time_t time = jack_get_time();
  131. adapter->fProducerDLL.IncFrame(time);
  132. /*
  133. jack_time_t time1 = adapter->fConsumerDLL.CurFrame2Time();
  134. jack_time_t time2 = adapter->fProducerDLL.CurFrame2Time();
  135. */
  136. jack_nframes_t time1 = adapter->fConsumerDLL.Time2Frames(time);
  137. jack_nframes_t time2 = adapter->fProducerDLL.Time2Frames(time);
  138. printf("time1 %ld time2 %ld\n",time1, time2);
  139. double src_ratio_output = double(time2) / double(time1);
  140. double src_ratio_input = double(time1) / double(time2);
  141. /*
  142. jack_time_t val2 = adapter->fConsumerFilter.GetVal();
  143. jack_time_t val1 = adapter->fProducerFilter.GetVal();
  144. double src_ratio_output = double(val1) / double(val2);
  145. double src_ratio_input = double(val2) / double(val1);
  146. */
  147. if (src_ratio_input < 0.8f || src_ratio_input > 1.2f) {
  148. jack_error("src_ratio_input = %f", src_ratio_input);
  149. src_ratio_input = 1;
  150. time1 = 1;
  151. time2 = 1;
  152. }
  153. if (src_ratio_output < 0.8f || src_ratio_output > 1.2f) {
  154. jack_error("src_ratio_output = %f", src_ratio_output);
  155. src_ratio_output = 1;
  156. time1 = 1;
  157. time2 = 1;
  158. }
  159. src_ratio_input = Range(0.8f, 1.2f, src_ratio_input);
  160. src_ratio_output = Range(0.8f, 1.2f, src_ratio_output);
  161. //jack_log("Callback resampler src_ratio_input = %f src_ratio_output = %f", src_ratio_input, src_ratio_output);
  162. //jack_info("Callback resampler src_ratio_input = %f src_ratio_output = %f", src_ratio_input, src_ratio_output);
  163. printf("Callback resampler src_ratio_input = %f src_ratio_output = %f\n", src_ratio_input, src_ratio_output);
  164. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  165. adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
  166. adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
  167. // adapter->fCaptureRingBuffer[i].Write((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames);
  168. }
  169. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  170. adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
  171. adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames);
  172. // adapter->fPlaybackRingBuffer[i].Read((float*)ioData->mBuffers[i].mData, inNumberFrames);
  173. }
  174. return noErr;
  175. }
  176. OSStatus JackCoreAudioIOAdapter::GetDefaultDevice(AudioDeviceID* id)
  177. {
  178. OSStatus res;
  179. UInt32 theSize = sizeof(UInt32);
  180. AudioDeviceID inDefault;
  181. AudioDeviceID outDefault;
  182. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  183. return res;
  184. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  185. return res;
  186. jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
  187. // Get the device only if default input and ouput are the same
  188. if (inDefault == outDefault) {
  189. *id = inDefault;
  190. return noErr;
  191. } else {
  192. jack_error("Default input and output devices are not the same !!");
  193. return kAudioHardwareBadDeviceError;
  194. }
  195. }
  196. OSStatus JackCoreAudioIOAdapter::GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput)
  197. {
  198. OSStatus err = noErr;
  199. UInt32 outSize;
  200. Boolean outWritable;
  201. AudioBufferList* bufferList = 0;
  202. *channelCount = 0;
  203. err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
  204. if (err == noErr) {
  205. bufferList = (AudioBufferList*)malloc(outSize);
  206. err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
  207. if (err == noErr) {
  208. for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
  209. *channelCount += bufferList->mBuffers[i].mNumberChannels;
  210. }
  211. if (bufferList)
  212. free(bufferList);
  213. }
  214. return err;
  215. }
  216. // Setup
  217. int JackCoreAudioIOAdapter::SetupDevices(const char* capture_driver_uid,
  218. const char* playback_driver_uid,
  219. char* capture_driver_name,
  220. char* playback_driver_name)
  221. {
  222. if (GetDefaultDevice(&fDeviceID) != noErr) {
  223. jack_error("Cannot open default device");
  224. return -1;
  225. }
  226. return 0;
  227. }
  228. int JackCoreAudioIOAdapter::SetupChannels(bool capturing,
  229. bool playing,
  230. int& inchannels,
  231. int& outchannels,
  232. int& in_nChannels,
  233. int& out_nChannels,
  234. bool strict)
  235. {
  236. OSStatus err = noErr;
  237. err = GetTotalChannels(fDeviceID, &in_nChannels, true);
  238. if (err != noErr) {
  239. jack_error("Cannot get input channel number");
  240. printError(err);
  241. return -1;
  242. }
  243. err = GetTotalChannels(fDeviceID, &out_nChannels, false);
  244. if (err != noErr) {
  245. jack_error("Cannot get output channel number");
  246. printError(err);
  247. return -1;
  248. }
  249. return 0;
  250. }
  251. int JackCoreAudioIOAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
  252. {
  253. OSStatus err = noErr;
  254. UInt32 outSize;
  255. Float64 sampleRate;
  256. // Setting buffer size
  257. outSize = sizeof(UInt32);
  258. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
  259. if (err != noErr) {
  260. jack_error("Cannot set buffer size %ld", nframes);
  261. printError(err);
  262. return -1;
  263. }
  264. // Get sample rate
  265. outSize = sizeof(Float64);
  266. err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  267. if (err != noErr) {
  268. jack_error("Cannot get current sample rate");
  269. printError(err);
  270. return -1;
  271. }
  272. // If needed, set new sample rate
  273. if (samplerate != (jack_nframes_t)sampleRate) {
  274. sampleRate = (Float64)samplerate;
  275. // To get SR change notification
  276. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
  277. if (err != noErr) {
  278. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  279. printError(err);
  280. return -1;
  281. }
  282. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
  283. if (err != noErr) {
  284. jack_error("Cannot set sample rate = %ld", samplerate);
  285. printError(err);
  286. return -1;
  287. }
  288. // Waiting for SR change notification
  289. int count = 0;
  290. while (!fState && count++ < 100) {
  291. usleep(100000);
  292. jack_log("Wait count = %ld", count);
  293. }
  294. // Remove SR change notification
  295. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
  296. }
  297. return 0;
  298. }
  299. int JackCoreAudioIOAdapter::SetupBuffers(int inchannels, int outchannels)
  300. {
  301. jack_log("JackCoreAudioIOAdapter::SetupBuffers: input = %ld output = %ld", inchannels, outchannels);
  302. // Prepare buffers
  303. fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
  304. if (fInputData == 0) {
  305. jack_error("Cannot allocate memory for input buffers");
  306. return -1;
  307. }
  308. fInputData->mNumberBuffers = inchannels;
  309. for (int i = 0; i < fCaptureChannels; i++) {
  310. fInputData->mBuffers[i].mNumberChannels = 1;
  311. fInputData->mBuffers[i].mDataByteSize = fBufferSize * sizeof(float);
  312. fInputData->mBuffers[i].mData = malloc(fBufferSize * sizeof(float));
  313. }
  314. return 0;
  315. }
  316. void JackCoreAudioIOAdapter::DisposeBuffers()
  317. {
  318. if (fInputData) {
  319. for (int i = 0; i < fCaptureChannels; i++)
  320. free(fInputData->mBuffers[i].mData);
  321. free(fInputData);
  322. fInputData = 0;
  323. }
  324. }
  325. int JackCoreAudioIOAdapter::OpenAUHAL(bool capturing,
  326. bool playing,
  327. int inchannels,
  328. int outchannels,
  329. int in_nChannels,
  330. int out_nChannels,
  331. jack_nframes_t nframes,
  332. jack_nframes_t samplerate,
  333. bool strict)
  334. {
  335. ComponentResult err1;
  336. UInt32 enableIO;
  337. AudioStreamBasicDescription srcFormat, dstFormat;
  338. 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);
  339. // AUHAL
  340. ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
  341. Component HALOutput = FindNextComponent(NULL, &cd);
  342. err1 = OpenAComponent(HALOutput, &fAUHAL);
  343. if (err1 != noErr) {
  344. jack_error("Error calling OpenAComponent");
  345. printError(err1);
  346. return -1;
  347. }
  348. err1 = AudioUnitInitialize(fAUHAL);
  349. if (err1 != noErr) {
  350. jack_error("Cannot initialize AUHAL unit");
  351. printError(err1);
  352. return -1;
  353. }
  354. // Start I/O
  355. enableIO = 1;
  356. if (capturing && inchannels > 0) {
  357. jack_log("Setup AUHAL input");
  358. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
  359. if (err1 != noErr) {
  360. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
  361. printError(err1);
  362. if (strict)
  363. return -1;
  364. }
  365. }
  366. if (playing && outchannels > 0) {
  367. jack_log("Setup AUHAL output");
  368. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
  369. if (err1 != noErr) {
  370. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
  371. printError(err1);
  372. if (strict)
  373. return -1;
  374. }
  375. }
  376. // Setup up choosen device, in both input and output cases
  377. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
  378. if (err1 != noErr) {
  379. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
  380. printError(err1);
  381. if (strict)
  382. return -1;
  383. }
  384. // Set buffer size
  385. if (capturing && inchannels > 0) {
  386. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
  387. if (err1 != noErr) {
  388. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  389. printError(err1);
  390. if (strict)
  391. return -1;
  392. }
  393. }
  394. if (playing && outchannels > 0) {
  395. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
  396. if (err1 != noErr) {
  397. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  398. printError(err1);
  399. if (strict)
  400. return -1;
  401. }
  402. }
  403. // Setup channel map
  404. if (capturing && inchannels > 0 && inchannels < in_nChannels) {
  405. SInt32 chanArr[in_nChannels];
  406. for (int i = 0; i < in_nChannels; i++) {
  407. chanArr[i] = -1;
  408. }
  409. for (int i = 0; i < inchannels; i++) {
  410. chanArr[i] = i;
  411. }
  412. AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
  413. if (err1 != noErr) {
  414. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
  415. printError(err1);
  416. }
  417. }
  418. if (playing && outchannels > 0 && outchannels < out_nChannels) {
  419. SInt32 chanArr[out_nChannels];
  420. for (int i = 0; i < out_nChannels; i++) {
  421. chanArr[i] = -1;
  422. }
  423. for (int i = 0; i < outchannels; i++) {
  424. chanArr[i] = i;
  425. }
  426. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
  427. if (err1 != noErr) {
  428. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
  429. printError(err1);
  430. }
  431. }
  432. // Setup stream converters
  433. jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
  434. srcFormat.mSampleRate = samplerate;
  435. srcFormat.mFormatID = kAudioFormatLinearPCM;
  436. srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  437. srcFormat.mBytesPerPacket = sizeof(float);
  438. srcFormat.mFramesPerPacket = 1;
  439. srcFormat.mBytesPerFrame = sizeof(float);
  440. srcFormat.mChannelsPerFrame = outchannels;
  441. srcFormat.mBitsPerChannel = 32;
  442. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
  443. if (err1 != noErr) {
  444. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
  445. printError(err1);
  446. }
  447. jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
  448. dstFormat.mSampleRate = samplerate;
  449. dstFormat.mFormatID = kAudioFormatLinearPCM;
  450. dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  451. dstFormat.mBytesPerPacket = sizeof(float);
  452. dstFormat.mFramesPerPacket = 1;
  453. dstFormat.mBytesPerFrame = sizeof(float);
  454. dstFormat.mChannelsPerFrame = inchannels;
  455. dstFormat.mBitsPerChannel = 32;
  456. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
  457. if (err1 != noErr) {
  458. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
  459. printError(err1);
  460. }
  461. // Setup callbacks
  462. if (inchannels > 0 && outchannels == 0) {
  463. AURenderCallbackStruct output;
  464. output.inputProc = Render;
  465. output.inputProcRefCon = this;
  466. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
  467. if (err1 != noErr) {
  468. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
  469. printError(err1);
  470. return -1;
  471. }
  472. } else {
  473. AURenderCallbackStruct output;
  474. output.inputProc = Render;
  475. output.inputProcRefCon = this;
  476. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
  477. if (err1 != noErr) {
  478. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
  479. printError(err1);
  480. return -1;
  481. }
  482. }
  483. return 0;
  484. }
  485. void JackCoreAudioIOAdapter::CloseAUHAL()
  486. {
  487. AudioUnitUninitialize(fAUHAL);
  488. CloseComponent(fAUHAL);
  489. }
  490. int JackCoreAudioIOAdapter::Open()
  491. {
  492. OSStatus err;
  493. int in_nChannels = 0;
  494. int out_nChannels = 0;
  495. if (SetupDevices("", "", "", "") < 0)
  496. return -1;
  497. if (SetupChannels(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
  498. return -1;
  499. if (SetupBufferSizeAndSampleRate(fBufferSize, fSampleRate) < 0)
  500. return -1;
  501. if (OpenAUHAL(true, true, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fBufferSize, fSampleRate, true) < 0)
  502. goto error;
  503. if (SetupBuffers(fCaptureChannels, fPlaybackChannels) < 0)
  504. goto error;
  505. err = AudioOutputUnitStart(fAUHAL);
  506. if (err != noErr)
  507. goto error;
  508. return 0;
  509. error:
  510. Close();
  511. return -1;
  512. }
  513. int JackCoreAudioIOAdapter::Close()
  514. {
  515. AudioOutputUnitStop(fAUHAL);
  516. DisposeBuffers();
  517. CloseAUHAL();
  518. return 0;
  519. }
  520. }