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.

1098 lines
40KB

  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 "JackCoreAudioAdapter.h"
  16. #include "JackError.h"
  17. #include <unistd.h>
  18. #include <CoreServices/CoreServices.h>
  19. namespace Jack
  20. {
  21. static OSStatus DisplayDeviceNames()
  22. {
  23. UInt32 size;
  24. Boolean isWritable;
  25. int i, deviceNum;
  26. OSStatus err;
  27. CFStringRef UIname;
  28. err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
  29. if (err != noErr)
  30. return err;
  31. deviceNum = size / sizeof(AudioDeviceID);
  32. AudioDeviceID devices[deviceNum];
  33. err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
  34. if (err != noErr)
  35. return err;
  36. for (i = 0; i < deviceNum; i++) {
  37. char device_name[256];
  38. char internal_name[256];
  39. size = sizeof(CFStringRef);
  40. UIname = NULL;
  41. err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
  42. if (err == noErr) {
  43. CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
  44. } else {
  45. goto error;
  46. }
  47. size = 256;
  48. err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
  49. if (err != noErr)
  50. return err;
  51. jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
  52. }
  53. return noErr;
  54. error:
  55. if (UIname != NULL)
  56. CFRelease(UIname);
  57. return err;
  58. }
  59. static void printError(OSStatus err)
  60. {
  61. switch (err) {
  62. case kAudioHardwareNoError:
  63. jack_log("error code : kAudioHardwareNoError");
  64. break;
  65. case kAudioConverterErr_FormatNotSupported:
  66. jack_log("error code : kAudioConverterErr_FormatNotSupported");
  67. break;
  68. case kAudioConverterErr_OperationNotSupported:
  69. jack_log("error code : kAudioConverterErr_OperationNotSupported");
  70. break;
  71. case kAudioConverterErr_PropertyNotSupported:
  72. jack_log("error code : kAudioConverterErr_PropertyNotSupported");
  73. break;
  74. case kAudioConverterErr_InvalidInputSize:
  75. jack_log("error code : kAudioConverterErr_InvalidInputSize");
  76. break;
  77. case kAudioConverterErr_InvalidOutputSize:
  78. jack_log("error code : kAudioConverterErr_InvalidOutputSize");
  79. break;
  80. case kAudioConverterErr_UnspecifiedError:
  81. jack_log("error code : kAudioConverterErr_UnspecifiedError");
  82. break;
  83. case kAudioConverterErr_BadPropertySizeError:
  84. jack_log("error code : kAudioConverterErr_BadPropertySizeError");
  85. break;
  86. case kAudioConverterErr_RequiresPacketDescriptionsError:
  87. jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
  88. break;
  89. case kAudioConverterErr_InputSampleRateOutOfRange:
  90. jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
  91. break;
  92. case kAudioConverterErr_OutputSampleRateOutOfRange:
  93. jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
  94. break;
  95. case kAudioHardwareNotRunningError:
  96. jack_log("error code : kAudioHardwareNotRunningError");
  97. break;
  98. case kAudioHardwareUnknownPropertyError:
  99. jack_log("error code : kAudioHardwareUnknownPropertyError");
  100. break;
  101. case kAudioHardwareIllegalOperationError:
  102. jack_log("error code : kAudioHardwareIllegalOperationError");
  103. break;
  104. case kAudioHardwareBadDeviceError:
  105. jack_log("error code : kAudioHardwareBadDeviceError");
  106. break;
  107. case kAudioHardwareBadStreamError:
  108. jack_log("error code : kAudioHardwareBadStreamError");
  109. break;
  110. case kAudioDeviceUnsupportedFormatError:
  111. jack_log("error code : kAudioDeviceUnsupportedFormatError");
  112. break;
  113. case kAudioDevicePermissionsError:
  114. jack_log("error code : kAudioDevicePermissionsError");
  115. break;
  116. case kAudioHardwareBadObjectError:
  117. jack_log("error code : kAudioHardwareBadObjectError");
  118. break;
  119. case kAudioHardwareUnsupportedOperationError:
  120. jack_log("error code : kAudioHardwareUnsupportedOperationError");
  121. break;
  122. default:
  123. jack_log("error code : unknown");
  124. break;
  125. }
  126. }
  127. OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
  128. UInt32 inChannel,
  129. Boolean isInput,
  130. AudioDevicePropertyID inPropertyID,
  131. void* inClientData)
  132. {
  133. JackCoreAudioAdapter* driver = static_cast<JackCoreAudioAdapter*>(inClientData);
  134. switch (inPropertyID) {
  135. case kAudioDevicePropertyNominalSampleRate: {
  136. jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
  137. driver->fState = true;
  138. break;
  139. }
  140. }
  141. return noErr;
  142. }
  143. // A better implementation would try to recover in case of hardware device change (see HALLAB HLFilePlayerWindowControllerAudioDevicePropertyListenerProc code)
  144. OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice,
  145. UInt32 inChannel,
  146. Boolean isInput,
  147. AudioDevicePropertyID inPropertyID,
  148. void* inClientData)
  149. {
  150. JackCoreAudioAdapter* driver = (JackCoreAudioAdapter*)inClientData;
  151. switch (inPropertyID) {
  152. case kAudioDevicePropertyStreamConfiguration:
  153. case kAudioDevicePropertyNominalSampleRate: {
  154. UInt32 outSize = sizeof(Float64);
  155. Float64 sampleRate;
  156. int in_nChannels = 0;
  157. int out_nChannels = 0;
  158. char capture_driver_name[256];
  159. char playback_driver_name[256];
  160. // Stop and restart
  161. AudioOutputUnitStop(driver->fAUHAL);
  162. driver->RemoveListeners();
  163. driver->CloseAUHAL();
  164. OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  165. if (err != noErr) {
  166. jack_error("Cannot get current sample rate");
  167. printError(err);
  168. }
  169. jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyNominalSampleRate %ld", long(sampleRate));
  170. if (driver->SetupDevices(driver->fCaptureUID, driver->fPlaybackUID, capture_driver_name, playback_driver_name) < 0)
  171. return -1;
  172. if (driver->SetupChannels(driver->fCapturing, driver->fPlaying, driver->fCaptureChannels, driver->fPlaybackChannels, in_nChannels, out_nChannels, false) < 0)
  173. return -1;
  174. if (driver->SetupBufferSizeAndSampleRate(driver->fAdaptedBufferSize, sampleRate) < 0)
  175. return -1;
  176. driver->SetAdaptedSampleRate(sampleRate);
  177. if (driver->OpenAUHAL(driver->fCapturing,
  178. driver->fPlaying,
  179. driver->fCaptureChannels,
  180. driver->fPlaybackChannels,
  181. in_nChannels,
  182. out_nChannels,
  183. driver->fAdaptedBufferSize,
  184. sampleRate,
  185. false) < 0)
  186. goto error;
  187. if (driver->AddListeners() < 0)
  188. goto error;
  189. AudioOutputUnitStart(driver->fAUHAL);
  190. return noErr;
  191. error:
  192. driver->CloseAUHAL();
  193. break;
  194. }
  195. }
  196. return noErr;
  197. }
  198. int JackCoreAudioAdapter::AddListeners()
  199. {
  200. OSStatus err = noErr;
  201. // Add listeners
  202. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
  203. if (err != noErr) {
  204. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
  205. printError(err);
  206. return -1;
  207. }
  208. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
  209. if (err != noErr) {
  210. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  211. printError(err);
  212. return -1;
  213. }
  214. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
  215. if (err != noErr) {
  216. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
  217. printError(err);
  218. return -1;
  219. }
  220. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
  221. if (err != noErr) {
  222. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
  223. printError(err);
  224. return -1;
  225. }
  226. err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
  227. if (err != noErr) {
  228. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
  229. printError(err);
  230. return -1;
  231. }
  232. return 0;
  233. }
  234. void JackCoreAudioAdapter::RemoveListeners()
  235. {
  236. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
  237. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
  238. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
  239. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
  240. AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
  241. }
  242. OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
  243. AudioUnitRenderActionFlags *ioActionFlags,
  244. const AudioTimeStamp *inTimeStamp,
  245. UInt32 inBusNumber,
  246. UInt32 inNumberFrames,
  247. AudioBufferList *ioData)
  248. {
  249. JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
  250. AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
  251. float* inputBuffer[adapter->fCaptureChannels];
  252. float* outputBuffer[adapter->fPlaybackChannels];
  253. for (int i = 0; i < adapter->fCaptureChannels; i++) {
  254. inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData;
  255. }
  256. for (int i = 0; i < adapter->fPlaybackChannels; i++) {
  257. outputBuffer[i] = (float*)ioData->mBuffers[i].mData;
  258. }
  259. adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames);
  260. return noErr;
  261. }
  262. JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
  263. :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false)
  264. {
  265. const JSList* node;
  266. const jack_driver_param_t* param;
  267. char captureName[256];
  268. char playbackName[256];
  269. fCaptureUID[0] = 0;
  270. fPlaybackUID[0] = 0;
  271. // Default values
  272. fCaptureChannels = 0;
  273. fPlaybackChannels = 0;
  274. for (node = params; node; node = jack_slist_next(node)) {
  275. param = (const jack_driver_param_t*) node->data;
  276. switch (param->character) {
  277. case 'c' :
  278. fCaptureChannels = fPlaybackChannels = param->value.ui;
  279. break;
  280. case 'i':
  281. fCaptureChannels = param->value.ui;
  282. break;
  283. case 'o':
  284. fPlaybackChannels = param->value.ui;
  285. break;
  286. case 'C':
  287. fCapturing = true;
  288. strncpy(fCaptureUID, param->value.str, 256);
  289. break;
  290. case 'P':
  291. fPlaying = true;
  292. strncpy(fPlaybackUID, param->value.str, 256);
  293. break;
  294. case 'd':
  295. strncpy(fCaptureUID, param->value.str, 256);
  296. strncpy(fPlaybackUID, param->value.str, 256);
  297. break;
  298. case 'D':
  299. fCapturing = fPlaying = true;
  300. break;
  301. case 'r':
  302. SetAdaptedSampleRate(param->value.ui);
  303. break;
  304. case 'p':
  305. SetAdaptedBufferSize(param->value.ui);
  306. break;
  307. case 'l':
  308. DisplayDeviceNames();
  309. break;
  310. case 'q':
  311. fQuality = param->value.ui;
  312. break;
  313. case 'g':
  314. fRingbufferCurSize = param->value.ui;
  315. fAdaptative = false;
  316. break;
  317. }
  318. }
  319. /* duplex is the default */
  320. if (!fCapturing && !fPlaying) {
  321. fCapturing = true;
  322. fPlaying = true;
  323. }
  324. int in_nChannels = 0;
  325. int out_nChannels = 0;
  326. if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName) < 0)
  327. throw -1;
  328. if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
  329. throw -1;
  330. if (SetupBufferSizeAndSampleRate(fAdaptedBufferSize, fAdaptedSampleRate) < 0)
  331. throw -1;
  332. if (fCapturing && fCaptureChannels > 0)
  333. if (SetupBuffers(fCaptureChannels) < 0)
  334. throw -1;
  335. if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate, true) < 0)
  336. throw -1;
  337. if (AddListeners() < 0)
  338. throw -1;
  339. }
  340. OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
  341. {
  342. OSStatus res;
  343. UInt32 theSize = sizeof(UInt32);
  344. AudioDeviceID inDefault;
  345. AudioDeviceID outDefault;
  346. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  347. return res;
  348. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  349. return res;
  350. jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
  351. // Get the device only if default input and ouput are the same
  352. if (inDefault == outDefault) {
  353. *id = inDefault;
  354. return noErr;
  355. } else {
  356. jack_error("Default input and output devices are not the same !!");
  357. return kAudioHardwareBadDeviceError;
  358. }
  359. }
  360. OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
  361. {
  362. OSStatus err = noErr;
  363. UInt32 outSize;
  364. Boolean outWritable;
  365. AudioBufferList* bufferList = 0;
  366. channelCount = 0;
  367. err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
  368. if (err == noErr) {
  369. bufferList = (AudioBufferList*)malloc(outSize);
  370. err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
  371. if (err == noErr) {
  372. for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
  373. channelCount += bufferList->mBuffers[i].mNumberChannels;
  374. }
  375. if (bufferList)
  376. free(bufferList);
  377. }
  378. return err;
  379. }
  380. OSStatus JackCoreAudioAdapter::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
  381. {
  382. UInt32 size = sizeof(AudioValueTranslation);
  383. CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
  384. AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
  385. if (inIUD == NULL) {
  386. return kAudioHardwareUnspecifiedError;
  387. } else {
  388. OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
  389. CFRelease(inIUD);
  390. jack_log("GetDeviceIDFromUID %s %ld", UID, *id);
  391. return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
  392. }
  393. }
  394. OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id)
  395. {
  396. OSStatus res;
  397. UInt32 theSize = sizeof(UInt32);
  398. AudioDeviceID inDefault;
  399. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
  400. return res;
  401. jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
  402. *id = inDefault;
  403. return noErr;
  404. }
  405. OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id)
  406. {
  407. OSStatus res;
  408. UInt32 theSize = sizeof(UInt32);
  409. AudioDeviceID outDefault;
  410. if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
  411. return res;
  412. jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
  413. *id = outDefault;
  414. return noErr;
  415. }
  416. OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name)
  417. {
  418. UInt32 size = 256;
  419. return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
  420. }
  421. // Setup
  422. int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
  423. const char* playback_driver_uid,
  424. char* capture_driver_name,
  425. char* playback_driver_name)
  426. {
  427. capture_driver_name[0] = 0;
  428. playback_driver_name[0] = 0;
  429. // Duplex
  430. if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
  431. jack_log("JackCoreAudioAdapter::Open duplex");
  432. if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
  433. if (GetDefaultDevice(&fDeviceID) != noErr) {
  434. jack_error("Cannot open default device");
  435. return -1;
  436. }
  437. }
  438. if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
  439. jack_error("Cannot get device name from device ID");
  440. return -1;
  441. }
  442. // Capture only
  443. } else if (strcmp(capture_driver_uid, "") != 0) {
  444. jack_log("JackCoreAudioAdapter::Open capture only");
  445. if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
  446. if (GetDefaultInputDevice(&fDeviceID) != noErr) {
  447. jack_error("Cannot open default device");
  448. return -1;
  449. }
  450. }
  451. if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
  452. jack_error("Cannot get device name from device ID");
  453. return -1;
  454. }
  455. // Playback only
  456. } else if (strcmp(playback_driver_uid, "") != 0) {
  457. jack_log("JackCoreAudioAdapter::Open playback only");
  458. if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
  459. if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
  460. jack_error("Cannot open default device");
  461. return -1;
  462. }
  463. }
  464. if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
  465. jack_error("Cannot get device name from device ID");
  466. return -1;
  467. }
  468. // Use default driver in duplex mode
  469. } else {
  470. jack_log("JackCoreAudioAdapter::Open default driver");
  471. if (GetDefaultDevice(&fDeviceID) != noErr) {
  472. jack_error("Cannot open default device");
  473. return -1;
  474. }
  475. if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
  476. jack_error("Cannot get device name from device ID");
  477. return -1;
  478. }
  479. }
  480. return 0;
  481. }
  482. int JackCoreAudioAdapter::SetupChannels(bool capturing,
  483. bool playing,
  484. int& inchannels,
  485. int& outchannels,
  486. int& in_nChannels,
  487. int& out_nChannels,
  488. bool strict)
  489. {
  490. OSStatus err = noErr;
  491. if (capturing) {
  492. err = GetTotalChannels(fDeviceID, in_nChannels, true);
  493. if (err != noErr) {
  494. jack_error("Cannot get input channel number");
  495. printError(err);
  496. return -1;
  497. } else {
  498. jack_log("Max input channels : %d", in_nChannels);
  499. }
  500. }
  501. if (playing) {
  502. err = GetTotalChannels(fDeviceID, out_nChannels, false);
  503. if (err != noErr) {
  504. jack_error("Cannot get output channel number");
  505. printError(err);
  506. return -1;
  507. } else {
  508. jack_log("Max output channels : %d", out_nChannels);
  509. }
  510. }
  511. if (inchannels > in_nChannels) {
  512. jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
  513. if (strict)
  514. return -1;
  515. }
  516. if (outchannels > out_nChannels) {
  517. jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
  518. if (strict)
  519. return -1;
  520. }
  521. if (inchannels == 0) {
  522. jack_log("Setup max in channels = %ld", in_nChannels);
  523. inchannels = in_nChannels;
  524. }
  525. if (outchannels == 0) {
  526. jack_log("Setup max out channels = %ld", out_nChannels);
  527. outchannels = out_nChannels;
  528. }
  529. return 0;
  530. }
  531. int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
  532. {
  533. OSStatus err = noErr;
  534. UInt32 outSize;
  535. Float64 sampleRate;
  536. // Setting buffer size
  537. outSize = sizeof(UInt32);
  538. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
  539. if (err != noErr) {
  540. jack_error("Cannot set buffer size %ld", nframes);
  541. printError(err);
  542. return -1;
  543. }
  544. // Get sample rate
  545. outSize = sizeof(Float64);
  546. err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
  547. if (err != noErr) {
  548. jack_error("Cannot get current sample rate");
  549. printError(err);
  550. return -1;
  551. }
  552. // If needed, set new sample rate
  553. if (samplerate != (jack_nframes_t)sampleRate) {
  554. sampleRate = (Float64)samplerate;
  555. // To get SR change notification
  556. err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
  557. if (err != noErr) {
  558. jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
  559. printError(err);
  560. return -1;
  561. }
  562. err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
  563. if (err != noErr) {
  564. jack_error("Cannot set sample rate = %ld", samplerate);
  565. printError(err);
  566. return -1;
  567. }
  568. // Waiting for SR change notification
  569. int count = 0;
  570. while (!fState && count++ < 100) {
  571. usleep(100000);
  572. jack_log("Wait count = %ld", count);
  573. }
  574. // Remove SR change notification
  575. AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
  576. }
  577. return 0;
  578. }
  579. int JackCoreAudioAdapter::SetupBuffers(int inchannels)
  580. {
  581. jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld", inchannels);
  582. // Prepare buffers
  583. fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
  584. if (fInputData == 0) {
  585. jack_error("Cannot allocate memory for input buffers");
  586. return -1;
  587. }
  588. fInputData->mNumberBuffers = inchannels;
  589. for (int i = 0; i < fCaptureChannels; i++) {
  590. fInputData->mBuffers[i].mNumberChannels = 1;
  591. fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float);
  592. fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float));
  593. }
  594. return 0;
  595. }
  596. void JackCoreAudioAdapter::DisposeBuffers()
  597. {
  598. if (fInputData) {
  599. for (int i = 0; i < fCaptureChannels; i++)
  600. free(fInputData->mBuffers[i].mData);
  601. free(fInputData);
  602. fInputData = 0;
  603. }
  604. }
  605. int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
  606. bool playing,
  607. int inchannels,
  608. int outchannels,
  609. int in_nChannels,
  610. int out_nChannels,
  611. jack_nframes_t buffer_size,
  612. jack_nframes_t samplerate,
  613. bool strict)
  614. {
  615. ComponentResult err1;
  616. UInt32 enableIO;
  617. AudioStreamBasicDescription srcFormat, dstFormat;
  618. jack_log("OpenAUHAL capturing = %ld playing = %ld inchannels = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld ", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels);
  619. if (inchannels == 0 && outchannels == 0) {
  620. jack_error("No input and output channels...");
  621. return -1;
  622. }
  623. // AUHAL
  624. ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
  625. Component HALOutput = FindNextComponent(NULL, &cd);
  626. err1 = OpenAComponent(HALOutput, &fAUHAL);
  627. if (err1 != noErr) {
  628. jack_error("Error calling OpenAComponent");
  629. printError(err1);
  630. return -1;
  631. }
  632. err1 = AudioUnitInitialize(fAUHAL);
  633. if (err1 != noErr) {
  634. jack_error("Cannot initialize AUHAL unit");
  635. printError(err1);
  636. return -1;
  637. }
  638. // Start I/O
  639. if (capturing && inchannels > 0) {
  640. enableIO = 1;
  641. jack_log("Setup AUHAL input on");
  642. } else {
  643. enableIO = 0;
  644. jack_log("Setup AUHAL input off");
  645. }
  646. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
  647. if (err1 != noErr) {
  648. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
  649. printError(err1);
  650. if (strict)
  651. return -1;
  652. }
  653. if (playing && outchannels > 0) {
  654. enableIO = 1;
  655. jack_log("Setup AUHAL output on");
  656. } else {
  657. enableIO = 0;
  658. jack_log("Setup AUHAL output off");
  659. }
  660. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
  661. if (err1 != noErr) {
  662. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
  663. printError(err1);
  664. if (strict)
  665. return -1;
  666. }
  667. AudioDeviceID currAudioDeviceID;
  668. UInt32 size = sizeof(AudioDeviceID);
  669. err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
  670. if (err1 != noErr) {
  671. jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
  672. printError(err1);
  673. if (strict)
  674. return -1;
  675. } else {
  676. jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
  677. }
  678. // Setup up choosen device, in both input and output cases
  679. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
  680. if (err1 != noErr) {
  681. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
  682. printError(err1);
  683. if (strict)
  684. return -1;
  685. }
  686. err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
  687. if (err1 != noErr) {
  688. jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
  689. printError(err1);
  690. if (strict)
  691. return -1;
  692. } else {
  693. jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
  694. }
  695. // Set buffer size
  696. if (capturing && inchannels > 0) {
  697. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
  698. if (err1 != noErr) {
  699. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  700. printError(err1);
  701. if (strict)
  702. return -1;
  703. }
  704. }
  705. if (playing && outchannels > 0) {
  706. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
  707. if (err1 != noErr) {
  708. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
  709. printError(err1);
  710. if (strict)
  711. return -1;
  712. }
  713. }
  714. // Setup channel map
  715. if (capturing && inchannels > 0 && inchannels < in_nChannels) {
  716. SInt32 chanArr[in_nChannels];
  717. for (int i = 0; i < in_nChannels; i++) {
  718. chanArr[i] = -1;
  719. }
  720. for (int i = 0; i < inchannels; i++) {
  721. chanArr[i] = i;
  722. }
  723. AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
  724. if (err1 != noErr) {
  725. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
  726. printError(err1);
  727. }
  728. }
  729. if (playing && outchannels > 0 && outchannels < out_nChannels) {
  730. SInt32 chanArr[out_nChannels];
  731. for (int i = 0; i < out_nChannels; i++) {
  732. chanArr[i] = -1;
  733. }
  734. for (int i = 0; i < outchannels; i++) {
  735. chanArr[i] = i;
  736. }
  737. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
  738. if (err1 != noErr) {
  739. jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
  740. printError(err1);
  741. }
  742. }
  743. // Setup stream converters
  744. jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
  745. srcFormat.mSampleRate = samplerate;
  746. srcFormat.mFormatID = kAudioFormatLinearPCM;
  747. srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  748. srcFormat.mBytesPerPacket = sizeof(float);
  749. srcFormat.mFramesPerPacket = 1;
  750. srcFormat.mBytesPerFrame = sizeof(float);
  751. srcFormat.mChannelsPerFrame = outchannels;
  752. srcFormat.mBitsPerChannel = 32;
  753. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
  754. if (err1 != noErr) {
  755. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
  756. printError(err1);
  757. }
  758. jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
  759. dstFormat.mSampleRate = samplerate;
  760. dstFormat.mFormatID = kAudioFormatLinearPCM;
  761. dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
  762. dstFormat.mBytesPerPacket = sizeof(float);
  763. dstFormat.mFramesPerPacket = 1;
  764. dstFormat.mBytesPerFrame = sizeof(float);
  765. dstFormat.mChannelsPerFrame = inchannels;
  766. dstFormat.mBitsPerChannel = 32;
  767. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
  768. if (err1 != noErr) {
  769. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
  770. printError(err1);
  771. }
  772. // Setup callbacks
  773. if (inchannels > 0 && outchannels == 0) {
  774. AURenderCallbackStruct output;
  775. output.inputProc = Render;
  776. output.inputProcRefCon = this;
  777. err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
  778. if (err1 != noErr) {
  779. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
  780. printError(err1);
  781. return -1;
  782. }
  783. } else {
  784. AURenderCallbackStruct output;
  785. output.inputProc = Render;
  786. output.inputProcRefCon = this;
  787. err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
  788. if (err1 != noErr) {
  789. jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
  790. printError(err1);
  791. return -1;
  792. }
  793. }
  794. return 0;
  795. }
  796. void JackCoreAudioAdapter::CloseAUHAL()
  797. {
  798. AudioUnitUninitialize(fAUHAL);
  799. CloseComponent(fAUHAL);
  800. }
  801. int JackCoreAudioAdapter::Open()
  802. {
  803. return (AudioOutputUnitStart(fAUHAL) != noErr) ? -1 : 0;
  804. }
  805. int JackCoreAudioAdapter::Close()
  806. {
  807. #ifdef JACK_MONITOR
  808. fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
  809. #endif
  810. AudioOutputUnitStop(fAUHAL);
  811. DisposeBuffers();
  812. CloseAUHAL();
  813. RemoveListeners();
  814. return 0;
  815. }
  816. int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
  817. JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
  818. Close();
  819. return Open();
  820. }
  821. int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
  822. JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
  823. Close();
  824. return Open();
  825. }
  826. } // namespace
  827. #ifdef __cplusplus
  828. extern "C"
  829. {
  830. #endif
  831. SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
  832. {
  833. jack_driver_desc_t *desc;
  834. unsigned int i;
  835. desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
  836. strcpy(desc->name, "audioadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
  837. strcpy(desc->desc, "netjack audio <==> net backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
  838. desc->nparams = 12;
  839. desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
  840. i = 0;
  841. strcpy(desc->params[i].name, "channels");
  842. desc->params[i].character = 'c';
  843. desc->params[i].type = JackDriverParamInt;
  844. desc->params[i].value.ui = 0;
  845. strcpy(desc->params[i].short_desc, "Maximum number of channels");
  846. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  847. i++;
  848. strcpy(desc->params[i].name, "inchannels");
  849. desc->params[i].character = 'i';
  850. desc->params[i].type = JackDriverParamInt;
  851. desc->params[i].value.ui = 0;
  852. strcpy(desc->params[i].short_desc, "Maximum number of input channels");
  853. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  854. i++;
  855. strcpy(desc->params[i].name, "outchannels");
  856. desc->params[i].character = 'o';
  857. desc->params[i].type = JackDriverParamInt;
  858. desc->params[i].value.ui = 0;
  859. strcpy(desc->params[i].short_desc, "Maximum number of output channels");
  860. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  861. i++;
  862. strcpy(desc->params[i].name, "capture");
  863. desc->params[i].character = 'C';
  864. desc->params[i].type = JackDriverParamString;
  865. strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
  866. strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
  867. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  868. i++;
  869. strcpy(desc->params[i].name, "playback");
  870. desc->params[i].character = 'P';
  871. desc->params[i].type = JackDriverParamString;
  872. strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
  873. strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
  874. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  875. i++;
  876. strcpy(desc->params[i].name, "rate");
  877. desc->params[i].character = 'r';
  878. desc->params[i].type = JackDriverParamUInt;
  879. desc->params[i].value.ui = 44100U;
  880. strcpy(desc->params[i].short_desc, "Sample rate");
  881. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  882. i++;
  883. strcpy(desc->params[i].name, "periodsize");
  884. desc->params[i].character = 'p';
  885. desc->params[i].type = JackDriverParamUInt;
  886. desc->params[i].value.ui = 512U;
  887. strcpy(desc->params[i].short_desc, "Period size");
  888. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  889. i++;
  890. strcpy(desc->params[i].name, "duplex");
  891. desc->params[i].character = 'D';
  892. desc->params[i].type = JackDriverParamBool;
  893. desc->params[i].value.i = TRUE;
  894. strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
  895. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  896. i++;
  897. strcpy(desc->params[i].name, "device");
  898. desc->params[i].character = 'd';
  899. desc->params[i].type = JackDriverParamString;
  900. strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
  901. strcpy(desc->params[i].short_desc, "CoreAudio device name");
  902. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  903. i++;
  904. strcpy(desc->params[i].name, "list-devices");
  905. desc->params[i].character = 'l';
  906. desc->params[i].type = JackDriverParamBool;
  907. desc->params[i].value.i = TRUE;
  908. strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
  909. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  910. i++;
  911. strcpy(desc->params[i].name, "quality");
  912. desc->params[i].character = 'q';
  913. desc->params[i].type = JackDriverParamInt;
  914. desc->params[i].value.ui = 0;
  915. strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
  916. strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
  917. i++;
  918. strcpy(desc->params[i].name, "ring-buffer");
  919. desc->params[i].character = 'g';
  920. desc->params[i].type = JackDriverParamInt;
  921. desc->params[i].value.ui = 32768;
  922. strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
  923. strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
  924. return desc;
  925. }
  926. #ifdef __cplusplus
  927. }
  928. #endif