00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "JackCoreAudioAdapter.h"
00021 #include "JackError.h"
00022 #include <unistd.h>
00023
00024 #include <CoreServices/CoreServices.h>
00025
00026 namespace Jack
00027 {
00028
00029 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
00030 {
00031 jack_log("- - - - - - - - - - - - - - - - - - - -");
00032 jack_log(" Sample Rate:%f", inDesc->mSampleRate);
00033 jack_log(" Format ID:%.*s", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
00034 jack_log(" Format Flags:%lX", inDesc->mFormatFlags);
00035 jack_log(" Bytes per Packet:%ld", inDesc->mBytesPerPacket);
00036 jack_log(" Frames per Packet:%ld", inDesc->mFramesPerPacket);
00037 jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame);
00038 jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame);
00039 jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel);
00040 jack_log("- - - - - - - - - - - - - - - - - - - -");
00041 }
00042
00043 static OSStatus DisplayDeviceNames()
00044 {
00045 UInt32 size;
00046 Boolean isWritable;
00047 int i, deviceNum;
00048 OSStatus err;
00049 CFStringRef UIname;
00050
00051 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00052 if (err != noErr)
00053 return err;
00054
00055 deviceNum = size / sizeof(AudioDeviceID);
00056 AudioDeviceID devices[deviceNum];
00057
00058 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00059 if (err != noErr)
00060 return err;
00061
00062 for (i = 0; i < deviceNum; i++) {
00063 char device_name[256];
00064 char internal_name[256];
00065
00066 size = sizeof(CFStringRef);
00067 UIname = NULL;
00068 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00069 if (err == noErr) {
00070 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00071 } else {
00072 goto error;
00073 }
00074
00075 size = 256;
00076 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00077 if (err != noErr)
00078 return err;
00079
00080 jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
00081 }
00082
00083 return noErr;
00084
00085 error:
00086 if (UIname != NULL)
00087 CFRelease(UIname);
00088 return err;
00089 }
00090
00091 static void printError(OSStatus err)
00092 {
00093 switch (err) {
00094 case kAudioHardwareNoError:
00095 jack_log("error code : kAudioHardwareNoError");
00096 break;
00097 case kAudioConverterErr_FormatNotSupported:
00098 jack_log("error code : kAudioConverterErr_FormatNotSupported");
00099 break;
00100 case kAudioConverterErr_OperationNotSupported:
00101 jack_log("error code : kAudioConverterErr_OperationNotSupported");
00102 break;
00103 case kAudioConverterErr_PropertyNotSupported:
00104 jack_log("error code : kAudioConverterErr_PropertyNotSupported");
00105 break;
00106 case kAudioConverterErr_InvalidInputSize:
00107 jack_log("error code : kAudioConverterErr_InvalidInputSize");
00108 break;
00109 case kAudioConverterErr_InvalidOutputSize:
00110 jack_log("error code : kAudioConverterErr_InvalidOutputSize");
00111 break;
00112 case kAudioConverterErr_UnspecifiedError:
00113 jack_log("error code : kAudioConverterErr_UnspecifiedError");
00114 break;
00115 case kAudioConverterErr_BadPropertySizeError:
00116 jack_log("error code : kAudioConverterErr_BadPropertySizeError");
00117 break;
00118 case kAudioConverterErr_RequiresPacketDescriptionsError:
00119 jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
00120 break;
00121 case kAudioConverterErr_InputSampleRateOutOfRange:
00122 jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
00123 break;
00124 case kAudioConverterErr_OutputSampleRateOutOfRange:
00125 jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
00126 break;
00127 case kAudioHardwareNotRunningError:
00128 jack_log("error code : kAudioHardwareNotRunningError");
00129 break;
00130 case kAudioHardwareUnknownPropertyError:
00131 jack_log("error code : kAudioHardwareUnknownPropertyError");
00132 break;
00133 case kAudioHardwareIllegalOperationError:
00134 jack_log("error code : kAudioHardwareIllegalOperationError");
00135 break;
00136 case kAudioHardwareBadDeviceError:
00137 jack_log("error code : kAudioHardwareBadDeviceError");
00138 break;
00139 case kAudioHardwareBadStreamError:
00140 jack_log("error code : kAudioHardwareBadStreamError");
00141 break;
00142 case kAudioDeviceUnsupportedFormatError:
00143 jack_log("error code : kAudioDeviceUnsupportedFormatError");
00144 break;
00145 case kAudioDevicePermissionsError:
00146 jack_log("error code : kAudioDevicePermissionsError");
00147 break;
00148 case kAudioHardwareBadObjectError:
00149 jack_log("error code : kAudioHardwareBadObjectError");
00150 break;
00151 case kAudioHardwareUnsupportedOperationError:
00152 jack_log("error code : kAudioHardwareUnsupportedOperationError");
00153 break;
00154 default:
00155 jack_log("error code : unknown");
00156 break;
00157 }
00158 }
00159
00160 OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
00161 UInt32 inChannel,
00162 Boolean isInput,
00163 AudioDevicePropertyID inPropertyID,
00164 void* inClientData)
00165 {
00166 JackCoreAudioAdapter* driver = static_cast<JackCoreAudioAdapter*>(inClientData);
00167
00168 switch (inPropertyID) {
00169
00170 case kAudioDevicePropertyNominalSampleRate: {
00171 jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
00172 driver->fState = true;
00173 break;
00174 }
00175 }
00176
00177 return noErr;
00178 }
00179
00180
00181 OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice,
00182 UInt32 inChannel,
00183 Boolean isInput,
00184 AudioDevicePropertyID inPropertyID,
00185 void* inClientData)
00186 {
00187
00188 switch (inPropertyID) {
00189
00190 case kAudioDeviceProcessorOverload: {
00191 jack_error("JackCoreAudioAdapter::DeviceNotificationCallback kAudioDeviceProcessorOverload");
00192 break;
00193 }
00194
00195 case kAudioDevicePropertyStreamConfiguration: {
00196 jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration");
00197 return kAudioHardwareUnsupportedOperationError;
00198 }
00199
00200 case kAudioDevicePropertyNominalSampleRate: {
00201 jack_error("Cannot handle kAudioDevicePropertyNominalSampleRate");
00202 return kAudioHardwareUnsupportedOperationError;
00203 }
00204
00205 }
00206 return noErr;
00207 }
00208
00209 int JackCoreAudioAdapter::AddListeners()
00210 {
00211 OSStatus err = noErr;
00212
00213
00214 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
00215 if (err != noErr) {
00216 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
00217 printError(err);
00218 return -1;
00219 }
00220
00221 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
00222 if (err != noErr) {
00223 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
00224 printError(err);
00225 return -1;
00226 }
00227
00228 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
00229 if (err != noErr) {
00230 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00231 printError(err);
00232 return -1;
00233 }
00234
00235 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
00236 if (err != noErr) {
00237 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
00238 printError(err);
00239 return -1;
00240 }
00241
00242 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00243 if (err != noErr) {
00244 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00245 printError(err);
00246 return -1;
00247 }
00248
00249 err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00250 if (err != noErr) {
00251 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00252 printError(err);
00253 return -1;
00254 }
00255
00256 return 0;
00257 }
00258
00259 void JackCoreAudioAdapter::RemoveListeners()
00260 {
00261 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
00262 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
00263 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
00264 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
00265 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00266 AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00267 }
00268
00269 OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
00270 AudioUnitRenderActionFlags *ioActionFlags,
00271 const AudioTimeStamp *inTimeStamp,
00272 UInt32 inBusNumber,
00273 UInt32 inNumberFrames,
00274 AudioBufferList *ioData)
00275 {
00276 JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
00277 AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
00278
00279 float* inputBuffer[adapter->fCaptureChannels];
00280 float* outputBuffer[adapter->fPlaybackChannels];
00281
00282 for (int i = 0; i < adapter->fCaptureChannels; i++) {
00283 inputBuffer[i] = (float*)adapter->fInputData->mBuffers[i].mData;
00284 }
00285 for (int i = 0; i < adapter->fPlaybackChannels; i++) {
00286 outputBuffer[i] = (float*)ioData->mBuffers[i].mData;
00287 }
00288
00289 adapter->PushAndPull((float**)inputBuffer, (float**)outputBuffer, inNumberFrames);
00290 return noErr;
00291 }
00292
00293 JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
00294 :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false)
00295 {
00296 const JSList* node;
00297 const jack_driver_param_t* param;
00298 int in_nChannels = 0;
00299 int out_nChannels = 0;
00300 char captureName[256];
00301 char playbackName[256];
00302 fCaptureUID[0] = 0;
00303 fPlaybackUID[0] = 0;
00304 fClockDriftCompensate = false;
00305
00306
00307 fCaptureChannels = -1;
00308 fPlaybackChannels = -1;
00309
00310 SInt32 major;
00311 SInt32 minor;
00312 Gestalt(gestaltSystemVersionMajor, &major);
00313 Gestalt(gestaltSystemVersionMinor, &minor);
00314
00315
00316 if (major == 10 && minor >= 6) {
00317 CFRunLoopRef theRunLoop = NULL;
00318 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00319 OSStatus theError = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
00320 if (theError != noErr) {
00321 jack_error("JackCoreAudioAdapter::Open kAudioHardwarePropertyRunLoop error");
00322 }
00323 }
00324
00325 for (node = params; node; node = jack_slist_next(node)) {
00326 param = (const jack_driver_param_t*) node->data;
00327
00328 switch (param->character) {
00329
00330 case 'c' :
00331 fCaptureChannels = fPlaybackChannels = param->value.ui;
00332 break;
00333
00334 case 'i':
00335 fCaptureChannels = param->value.ui;
00336 break;
00337
00338 case 'o':
00339 fPlaybackChannels = param->value.ui;
00340 break;
00341
00342 case 'C':
00343 fCapturing = true;
00344 strncpy(fCaptureUID, param->value.str, 256);
00345 break;
00346
00347 case 'P':
00348 fPlaying = true;
00349 strncpy(fPlaybackUID, param->value.str, 256);
00350 break;
00351
00352 case 'd':
00353 strncpy(fCaptureUID, param->value.str, 256);
00354 strncpy(fPlaybackUID, param->value.str, 256);
00355 break;
00356
00357 case 'D':
00358 fCapturing = fPlaying = true;
00359 break;
00360
00361 case 'r':
00362 SetAdaptedSampleRate(param->value.ui);
00363 break;
00364
00365 case 'p':
00366 SetAdaptedBufferSize(param->value.ui);
00367 break;
00368
00369 case 'l':
00370 DisplayDeviceNames();
00371 break;
00372
00373 case 'q':
00374 fQuality = param->value.ui;
00375 break;
00376
00377 case 'g':
00378 fRingbufferCurSize = param->value.ui;
00379 fAdaptative = false;
00380 break;
00381
00382 case 's':
00383 fClockDriftCompensate = true;
00384 break;
00385 }
00386 }
00387
00388
00389 if (!fCapturing && !fPlaying) {
00390 fCapturing = true;
00391 fPlaying = true;
00392 }
00393
00394 if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName, fAdaptedSampleRate) < 0)
00395 throw -1;
00396
00397 if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
00398 throw -1;
00399
00400 if (SetupBufferSize(fAdaptedBufferSize) < 0)
00401 throw -1;
00402
00403 if (SetupSampleRate(fAdaptedSampleRate) < 0)
00404 throw -1;
00405
00406 if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate) < 0)
00407 throw -1;
00408
00409 if (fCapturing && fCaptureChannels > 0)
00410 if (SetupBuffers(fCaptureChannels) < 0)
00411 throw -1;
00412
00413 if (AddListeners() < 0)
00414 throw -1;
00415 }
00416
00417 OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
00418 {
00419 OSStatus res;
00420 UInt32 theSize = sizeof(UInt32);
00421 AudioDeviceID inDefault;
00422 AudioDeviceID outDefault;
00423
00424 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00425 return res;
00426
00427 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00428 return res;
00429
00430 jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
00431
00432
00433 if (inDefault == outDefault) {
00434 *id = inDefault;
00435 return noErr;
00436 } else {
00437 jack_error("Default input and output devices are not the same !!");
00438 return kAudioHardwareBadDeviceError;
00439 }
00440 }
00441
00442 OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
00443 {
00444 OSStatus err = noErr;
00445 UInt32 outSize;
00446 Boolean outWritable;
00447 AudioBufferList* bufferList = 0;
00448
00449 channelCount = 0;
00450 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00451 if (err == noErr) {
00452 bufferList = (AudioBufferList*)malloc(outSize);
00453 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00454 if (err == noErr) {
00455 for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
00456 channelCount += bufferList->mBuffers[i].mNumberChannels;
00457 }
00458
00459 if (bufferList)
00460 free(bufferList);
00461 }
00462
00463 return err;
00464 }
00465
00466 OSStatus JackCoreAudioAdapter::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00467 {
00468 UInt32 size = sizeof(AudioValueTranslation);
00469 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00470 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00471
00472 if (inIUD == NULL) {
00473 return kAudioHardwareUnspecifiedError;
00474 } else {
00475 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00476 CFRelease(inIUD);
00477 jack_log("GetDeviceIDFromUID %s %ld", UID, *id);
00478 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00479 }
00480 }
00481
00482 OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id)
00483 {
00484 OSStatus res;
00485 UInt32 theSize = sizeof(UInt32);
00486 AudioDeviceID inDefault;
00487
00488 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00489 return res;
00490
00491 jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
00492 *id = inDefault;
00493 return noErr;
00494 }
00495
00496 OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id)
00497 {
00498 OSStatus res;
00499 UInt32 theSize = sizeof(UInt32);
00500 AudioDeviceID outDefault;
00501
00502 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00503 return res;
00504
00505 jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
00506 *id = outDefault;
00507 return noErr;
00508 }
00509
00510 OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name)
00511 {
00512 UInt32 size = 256;
00513 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00514 }
00515
00516
00517 int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
00518 const char* playback_driver_uid,
00519 char* capture_driver_name,
00520 char* playback_driver_name,
00521 jack_nframes_t samplerate)
00522 {
00523 capture_driver_name[0] = 0;
00524 playback_driver_name[0] = 0;
00525
00526
00527 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00528
00529
00530 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
00531
00532 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00533 jack_log("Will take default in/out");
00534 if (GetDefaultDevice(&fDeviceID) != noErr) {
00535 jack_error("Cannot open default device");
00536 return -1;
00537 }
00538 }
00539 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00540 jack_error("Cannot get device name from device ID");
00541 return -1;
00542 }
00543
00544 } else {
00545
00546
00547 AudioDeviceID captureID, playbackID;
00548
00549 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
00550 jack_log("Will take default input");
00551 if (GetDefaultInputDevice(&captureID) != noErr) {
00552 jack_error("Cannot open default input device");
00553 return -1;
00554 }
00555 }
00556
00557 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
00558 jack_log("Will take default output");
00559 if (GetDefaultOutputDevice(&playbackID) != noErr) {
00560 jack_error("Cannot open default output device");
00561 return -1;
00562 }
00563 }
00564
00565 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
00566 return -1;
00567 }
00568
00569
00570 } else if (strcmp(capture_driver_uid, "") != 0) {
00571 jack_log("JackCoreAudioAdapter::Open capture only");
00572 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00573 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00574 jack_error("Cannot open default input device");
00575 return -1;
00576 }
00577 }
00578 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00579 jack_error("Cannot get device name from device ID");
00580 return -1;
00581 }
00582
00583
00584 } else if (strcmp(playback_driver_uid, "") != 0) {
00585 jack_log("JackCoreAudioAdapter::Open playback only");
00586 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00587 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00588 jack_error("Cannot open default output device");
00589 return -1;
00590 }
00591 }
00592 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00593 jack_error("Cannot get device name from device ID");
00594 return -1;
00595 }
00596
00597
00598 } else {
00599 jack_log("JackCoreAudioDriver::Open default driver");
00600 if (GetDefaultDevice(&fDeviceID) != noErr) {
00601 jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
00602
00603
00604 AudioDeviceID captureID, playbackID;
00605
00606 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
00607 jack_log("Will take default input");
00608 if (GetDefaultInputDevice(&captureID) != noErr) {
00609 jack_error("Cannot open default input device");
00610 return -1;
00611 }
00612 }
00613
00614 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
00615 jack_log("Will take default output");
00616 if (GetDefaultOutputDevice(&playbackID) != noErr) {
00617 jack_error("Cannot open default output device");
00618 return -1;
00619 }
00620 }
00621
00622 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
00623 return -1;
00624 }
00625 }
00626
00627 return 0;
00628 }
00629
00630 int JackCoreAudioAdapter::SetupChannels(bool capturing,
00631 bool playing,
00632 int& inchannels,
00633 int& outchannels,
00634 int& in_nChannels,
00635 int& out_nChannels,
00636 bool strict)
00637 {
00638 OSStatus err = noErr;
00639
00640 if (capturing) {
00641 err = GetTotalChannels(fDeviceID, in_nChannels, true);
00642 if (err != noErr) {
00643 jack_error("Cannot get input channel number");
00644 printError(err);
00645 return -1;
00646 } else {
00647 jack_log("Max input channels : %d", in_nChannels);
00648 }
00649 }
00650
00651 if (playing) {
00652 err = GetTotalChannels(fDeviceID, out_nChannels, false);
00653 if (err != noErr) {
00654 jack_error("Cannot get output channel number");
00655 printError(err);
00656 return -1;
00657 } else {
00658 jack_log("Max output channels : %d", out_nChannels);
00659 }
00660 }
00661
00662 if (inchannels > in_nChannels) {
00663 jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00664 if (strict)
00665 return -1;
00666 }
00667
00668 if (outchannels > out_nChannels) {
00669 jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00670 if (strict)
00671 return -1;
00672 }
00673
00674 if (inchannels == -1) {
00675 jack_log("Setup max in channels = %ld", in_nChannels);
00676 inchannels = in_nChannels;
00677 }
00678
00679 if (outchannels == -1) {
00680 jack_log("Setup max out channels = %ld", out_nChannels);
00681 outchannels = out_nChannels;
00682 }
00683
00684 return 0;
00685 }
00686
00687 int JackCoreAudioAdapter::SetupBufferSize(jack_nframes_t buffer_size)
00688 {
00689
00690 UInt32 outSize = sizeof(UInt32);
00691 OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
00692 if (err != noErr) {
00693 jack_error("Cannot set buffer size %ld", buffer_size);
00694 printError(err);
00695 return -1;
00696 }
00697
00698 return 0;
00699 }
00700
00701 int JackCoreAudioAdapter::SetupSampleRate(jack_nframes_t samplerate)
00702 {
00703 return SetupSampleRateAux(fDeviceID, samplerate);
00704 }
00705
00706 int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate)
00707 {
00708 OSStatus err = noErr;
00709 UInt32 outSize;
00710 Float64 sampleRate;
00711
00712
00713 outSize = sizeof(Float64);
00714 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00715 if (err != noErr) {
00716 jack_error("Cannot get current sample rate");
00717 printError(err);
00718 return -1;
00719 }
00720
00721
00722 if (samplerate != (jack_nframes_t)sampleRate) {
00723 sampleRate = (Float64)samplerate;
00724
00725
00726 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
00727 if (err != noErr) {
00728 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00729 printError(err);
00730 return -1;
00731 }
00732 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
00733 if (err != noErr) {
00734 jack_error("Cannot set sample rate = %ld", samplerate);
00735 printError(err);
00736 return -1;
00737 }
00738
00739
00740 int count = 0;
00741 while (!fState && count++ < WAIT_COUNTER) {
00742 usleep(100000);
00743 jack_log("Wait count = %d", count);
00744 }
00745
00746
00747 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
00748 }
00749
00750 return 0;
00751 }
00752
00753 int JackCoreAudioAdapter::SetupBuffers(int inchannels)
00754 {
00755 jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld", inchannels);
00756
00757
00758 fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00759 fInputData->mNumberBuffers = inchannels;
00760 for (int i = 0; i < fCaptureChannels; i++) {
00761 fInputData->mBuffers[i].mNumberChannels = 1;
00762 fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float);
00763 fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float));
00764 }
00765 return 0;
00766 }
00767
00768 void JackCoreAudioAdapter::DisposeBuffers()
00769 {
00770 if (fInputData) {
00771 for (int i = 0; i < fCaptureChannels; i++)
00772 free(fInputData->mBuffers[i].mData);
00773 free(fInputData);
00774 fInputData = 0;
00775 }
00776 }
00777
00778 int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
00779 bool playing,
00780 int inchannels,
00781 int outchannels,
00782 int in_nChannels,
00783 int out_nChannels,
00784 jack_nframes_t buffer_size,
00785 jack_nframes_t samplerate)
00786 {
00787 ComponentResult err1;
00788 UInt32 enableIO;
00789 AudioStreamBasicDescription srcFormat, dstFormat;
00790 AudioDeviceID currAudioDeviceID;
00791 UInt32 size;
00792
00793 jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels);
00794
00795 if (inchannels == 0 && outchannels == 0) {
00796 jack_error("No input and output channels...");
00797 return -1;
00798 }
00799
00800
00801 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00802 Component HALOutput = FindNextComponent(NULL, &cd);
00803
00804 err1 = OpenAComponent(HALOutput, &fAUHAL);
00805 if (err1 != noErr) {
00806 jack_error("Error calling OpenAComponent");
00807 printError(err1);
00808 goto error;
00809 }
00810
00811 err1 = AudioUnitInitialize(fAUHAL);
00812 if (err1 != noErr) {
00813 jack_error("Cannot initialize AUHAL unit");
00814 printError(err1);
00815 goto error;
00816 }
00817
00818
00819 if (capturing && inchannels > 0) {
00820 enableIO = 1;
00821 jack_log("Setup AUHAL input on");
00822 } else {
00823 enableIO = 0;
00824 jack_log("Setup AUHAL input off");
00825 }
00826
00827 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00828 if (err1 != noErr) {
00829 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00830 printError(err1);
00831 goto error;
00832 }
00833
00834 if (playing && outchannels > 0) {
00835 enableIO = 1;
00836 jack_log("Setup AUHAL output on");
00837 } else {
00838 enableIO = 0;
00839 jack_log("Setup AUHAL output off");
00840 }
00841
00842 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00843 if (err1 != noErr) {
00844 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00845 printError(err1);
00846 goto error;
00847 }
00848
00849 size = sizeof(AudioDeviceID);
00850 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00851 if (err1 != noErr) {
00852 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00853 printError(err1);
00854 goto error;
00855 } else {
00856 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00857 }
00858
00859
00860 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00861 if (err1 != noErr) {
00862 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00863 printError(err1);
00864 goto error;
00865 }
00866
00867
00868 if (capturing && inchannels > 0) {
00869 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
00870 if (err1 != noErr) {
00871 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00872 printError(err1);
00873 goto error;
00874 }
00875 }
00876
00877 if (playing && outchannels > 0) {
00878 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
00879 if (err1 != noErr) {
00880 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00881 printError(err1);
00882 goto error;
00883 }
00884 }
00885
00886
00887 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00888 SInt32 chanArr[in_nChannels];
00889 for (int i = 0; i < in_nChannels; i++) {
00890 chanArr[i] = -1;
00891 }
00892 for (int i = 0; i < inchannels; i++) {
00893 chanArr[i] = i;
00894 }
00895 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00896 if (err1 != noErr) {
00897 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00898 printError(err1);
00899 goto error;
00900 }
00901 }
00902
00903 if (playing && outchannels > 0 && outchannels < out_nChannels) {
00904 SInt32 chanArr[out_nChannels];
00905 for (int i = 0; i < out_nChannels; i++) {
00906 chanArr[i] = -1;
00907 }
00908 for (int i = 0; i < outchannels; i++) {
00909 chanArr[i] = i;
00910 }
00911 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00912 if (err1 != noErr) {
00913 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00914 printError(err1);
00915 goto error;
00916 }
00917 }
00918
00919
00920 if (capturing && inchannels > 0) {
00921
00922 size = sizeof(AudioStreamBasicDescription);
00923 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size);
00924 if (err1 != noErr) {
00925 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00926 printError(err1);
00927 goto error;
00928 }
00929 PrintStreamDesc(&srcFormat);
00930
00931 jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
00932 srcFormat.mSampleRate = samplerate;
00933 srcFormat.mFormatID = kAudioFormatLinearPCM;
00934 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00935 srcFormat.mBytesPerPacket = sizeof(float);
00936 srcFormat.mFramesPerPacket = 1;
00937 srcFormat.mBytesPerFrame = sizeof(float);
00938 srcFormat.mChannelsPerFrame = inchannels;
00939 srcFormat.mBitsPerChannel = 32;
00940 PrintStreamDesc(&srcFormat);
00941
00942 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
00943
00944 if (err1 != noErr) {
00945 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00946 printError(err1);
00947 goto error;
00948 }
00949 }
00950
00951 if (playing && outchannels > 0) {
00952
00953 size = sizeof(AudioStreamBasicDescription);
00954 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size);
00955 if (err1 != noErr) {
00956 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00957 printError(err1);
00958 goto error;
00959 }
00960 PrintStreamDesc(&dstFormat);
00961
00962 jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
00963 dstFormat.mSampleRate = samplerate;
00964 dstFormat.mFormatID = kAudioFormatLinearPCM;
00965 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00966 dstFormat.mBytesPerPacket = sizeof(float);
00967 dstFormat.mFramesPerPacket = 1;
00968 dstFormat.mBytesPerFrame = sizeof(float);
00969 dstFormat.mChannelsPerFrame = outchannels;
00970 dstFormat.mBitsPerChannel = 32;
00971 PrintStreamDesc(&dstFormat);
00972
00973 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
00974
00975 if (err1 != noErr) {
00976 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00977 printError(err1);
00978 goto error;
00979 }
00980 }
00981
00982
00983 if (inchannels > 0 && outchannels == 0) {
00984 AURenderCallbackStruct output;
00985 output.inputProc = Render;
00986 output.inputProcRefCon = this;
00987 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00988 if (err1 != noErr) {
00989 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
00990 printError(err1);
00991 goto error;
00992 }
00993 } else {
00994 AURenderCallbackStruct output;
00995 output.inputProc = Render;
00996 output.inputProcRefCon = this;
00997 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
00998 if (err1 != noErr) {
00999 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
01000 printError(err1);
01001 goto error;
01002 }
01003 }
01004
01005 return 0;
01006
01007 error:
01008 CloseAUHAL();
01009 return -1;
01010 }
01011
01012 OSStatus JackCoreAudioAdapter::DestroyAggregateDevice()
01013 {
01014 OSStatus osErr = noErr;
01015 AudioObjectPropertyAddress pluginAOPA;
01016 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
01017 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01018 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01019 UInt32 outDataSize;
01020
01021 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
01022 if (osErr != noErr) {
01023 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
01024 printError(osErr);
01025 return osErr;
01026 }
01027
01028 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
01029 if (osErr != noErr) {
01030 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
01031 printError(osErr);
01032 return osErr;
01033 }
01034
01035 return noErr;
01036 }
01037
01038 static CFStringRef GetDeviceName(AudioDeviceID id)
01039 {
01040 UInt32 size = sizeof(CFStringRef);
01041 CFStringRef UIname;
01042 OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
01043 return (err == noErr) ? UIname : NULL;
01044 }
01045
01046 OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
01047 {
01048 OSStatus err = noErr;
01049 AudioObjectID sub_device[32];
01050 UInt32 outSize = sizeof(sub_device);
01051
01052 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01053 vector<AudioDeviceID> captureDeviceIDArray;
01054
01055 if (err != noErr) {
01056 jack_log("Input device does not have subdevices");
01057 captureDeviceIDArray.push_back(captureDeviceID);
01058 } else {
01059 int num_devices = outSize / sizeof(AudioObjectID);
01060 jack_log("Input device has %d subdevices", num_devices);
01061 for (int i = 0; i < num_devices; i++) {
01062 captureDeviceIDArray.push_back(sub_device[i]);
01063 }
01064 }
01065
01066 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01067 vector<AudioDeviceID> playbackDeviceIDArray;
01068
01069 if (err != noErr) {
01070 jack_log("Output device does not have subdevices");
01071 playbackDeviceIDArray.push_back(playbackDeviceID);
01072 } else {
01073 int num_devices = outSize / sizeof(AudioObjectID);
01074 jack_log("Output device has %d subdevices", num_devices);
01075 for (int i = 0; i < num_devices; i++) {
01076 playbackDeviceIDArray.push_back(sub_device[i]);
01077 }
01078 }
01079
01080 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
01081 }
01082
01083 OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
01084 {
01085 OSStatus osErr = noErr;
01086 UInt32 outSize;
01087 Boolean outWritable;
01088
01089
01090
01091 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01092 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01093 UInt32 theQualifierDataSize = sizeof(AudioObjectID);
01094 AudioClassID inClass = kAudioSubDeviceClassID;
01095 void* theQualifierData = &inClass;
01096 UInt32 subDevicesNum = 0;
01097
01098
01099
01100
01101 UInt32 keptclockdomain = 0;
01102 UInt32 clockdomain = 0;
01103 outSize = sizeof(UInt32);
01104 bool need_clock_drift_compensation = false;
01105
01106 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01107 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
01108 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
01109 } else {
01110
01111 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
01112 if (osErr != 0) {
01113 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
01114 printError(osErr);
01115 } else {
01116 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
01117 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
01118 if (clockdomain != 0 && clockdomain != keptclockdomain) {
01119 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
01120 need_clock_drift_compensation = true;
01121 }
01122 }
01123 }
01124 }
01125
01126 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01127 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
01128 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
01129 } else {
01130
01131 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
01132 if (osErr != 0) {
01133 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
01134 printError(osErr);
01135 } else {
01136 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
01137 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
01138 if (clockdomain != 0 && clockdomain != keptclockdomain) {
01139 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
01140 need_clock_drift_compensation = true;
01141 }
01142 }
01143 }
01144 }
01145
01146
01147 if (keptclockdomain == 0) {
01148 need_clock_drift_compensation = true;
01149 }
01150
01151
01152
01153
01154
01155 char device_name[256];
01156 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01157 GetDeviceNameFromID(captureDeviceID[i], device_name);
01158 jack_info("Separated input = '%s' ", device_name);
01159 }
01160
01161 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01162 GetDeviceNameFromID(playbackDeviceID[i], device_name);
01163 jack_info("Separated output = '%s' ", device_name);
01164 }
01165
01166 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
01167 if (osErr != noErr) {
01168 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
01169 printError(osErr);
01170 return osErr;
01171 }
01172
01173 AudioValueTranslation pluginAVT;
01174
01175 CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
01176
01177 pluginAVT.mInputData = &inBundleRef;
01178 pluginAVT.mInputDataSize = sizeof(inBundleRef);
01179 pluginAVT.mOutputData = &fPluginID;
01180 pluginAVT.mOutputDataSize = sizeof(fPluginID);
01181
01182 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
01183 if (osErr != noErr) {
01184 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
01185 printError(osErr);
01186 return osErr;
01187 }
01188
01189
01190
01191
01192
01193 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
01194
01195 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
01196 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
01197
01198
01199 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
01200
01201
01202 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
01203
01204
01205 int value = 1;
01206 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
01207
01208 SInt32 system;
01209 Gestalt(gestaltSystemVersion, &system);
01210
01211 jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
01212
01213
01214 if (system < 0x00001054) {
01215 jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
01216 } else {
01217 jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
01218 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
01219 }
01220
01221
01222 CFMutableArrayRef subDevicesArrayClock = NULL;
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
01266
01267 vector<CFStringRef> captureDeviceUID;
01268 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01269 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
01270 if (ref == NULL)
01271 return -1;
01272 captureDeviceUID.push_back(ref);
01273
01274 CFArrayAppendValue(subDevicesArray, ref);
01275 }
01276
01277 vector<CFStringRef> playbackDeviceUID;
01278 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01279 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
01280 if (ref == NULL)
01281 return -1;
01282 playbackDeviceUID.push_back(ref);
01283
01284 CFArrayAppendValue(subDevicesArray, ref);
01285 }
01286
01287
01288
01289
01290
01291 AudioObjectPropertyAddress pluginAOPA;
01292 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
01293 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01294 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01295 UInt32 outDataSize;
01296
01297 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
01298 if (osErr != noErr) {
01299 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
01300 printError(osErr);
01301 goto error;
01302 }
01303
01304 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
01305 if (osErr != noErr) {
01306 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
01307 printError(osErr);
01308 goto error;
01309 }
01310
01311
01312
01313 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01314
01315
01316
01317
01318
01319 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
01320 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01321 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01322 outDataSize = sizeof(CFMutableArrayRef);
01323 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
01324 if (osErr != noErr) {
01325 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
01326 printError(osErr);
01327 goto error;
01328 }
01329
01330
01331 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01332
01333
01334
01335
01336
01337
01338
01339 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
01340 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01341 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01342 outDataSize = sizeof(CFStringRef);
01343 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
01344 if (osErr != noErr) {
01345 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
01346 printError(osErr);
01347 goto error;
01348 }
01349
01350
01351 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01352
01353
01354
01355
01356 if (fClockDriftCompensate) {
01357 if (need_clock_drift_compensation) {
01358 jack_info("Clock drift compensation activated...");
01359
01360
01361 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
01362 if (osErr != noErr) {
01363 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01364 printError(osErr);
01365 }
01366
01367
01368 subDevicesNum = outSize / sizeof(AudioObjectID);
01369 jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
01370 AudioObjectID subDevices[subDevicesNum];
01371 outSize = sizeof(subDevices);
01372
01373 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
01374 if (osErr != noErr) {
01375 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01376 printError(osErr);
01377 }
01378
01379
01380 for (UInt32 index = 0; index < subDevicesNum; ++index) {
01381 UInt32 theDriftCompensationValue = 1;
01382 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
01383 if (osErr != noErr) {
01384 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
01385 printError(osErr);
01386 }
01387 }
01388 } else {
01389 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
01390 }
01391 }
01392
01393
01394 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01395
01396
01397
01398
01399
01400
01401 CFRelease(AggregateDeviceNumberRef);
01402
01403
01404 CFRelease(aggDeviceDict);
01405 CFRelease(subDevicesArray);
01406
01407 if (subDevicesArrayClock)
01408 CFRelease(subDevicesArrayClock);
01409
01410
01411 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
01412 CFRelease(captureDeviceUID[i]);
01413 }
01414
01415 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
01416 CFRelease(playbackDeviceUID[i]);
01417 }
01418
01419 jack_log("New aggregate device %ld", *outAggregateDevice);
01420 return noErr;
01421
01422 error:
01423 DestroyAggregateDevice();
01424 return -1;
01425 }
01426
01427
01428 bool JackCoreAudioAdapter::IsAggregateDevice(AudioDeviceID device)
01429 {
01430 OSStatus err = noErr;
01431 AudioObjectID sub_device[32];
01432 UInt32 outSize = sizeof(sub_device);
01433 err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01434
01435 if (err != noErr) {
01436 jack_log("Device does not have subdevices");
01437 return false;
01438 } else {
01439 int num_devices = outSize / sizeof(AudioObjectID);
01440 jack_log("Device does has %d subdevices", num_devices);
01441 return true;
01442 }
01443 }
01444
01445 void JackCoreAudioAdapter::CloseAUHAL()
01446 {
01447 AudioUnitUninitialize(fAUHAL);
01448 CloseComponent(fAUHAL);
01449 }
01450
01451 int JackCoreAudioAdapter::Open()
01452 {
01453 return (AudioOutputUnitStart(fAUHAL) != noErr) ? -1 : 0;
01454 }
01455
01456 int JackCoreAudioAdapter::Close()
01457 {
01458 #ifdef JACK_MONITOR
01459 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
01460 #endif
01461 AudioOutputUnitStop(fAUHAL);
01462 DisposeBuffers();
01463 CloseAUHAL();
01464 RemoveListeners();
01465 if (fPluginID > 0)
01466 DestroyAggregateDevice();
01467 return 0;
01468 }
01469
01470 int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
01471 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
01472 Close();
01473 return Open();
01474 }
01475
01476 int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
01477 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
01478 Close();
01479 return Open();
01480 }
01481
01482 }
01483
01484 #ifdef __cplusplus
01485 extern "C"
01486 {
01487 #endif
01488
01489 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
01490 {
01491 jack_driver_desc_t *desc;
01492 unsigned int i;
01493 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
01494
01495 strcpy(desc->name, "audioadapter");
01496 strcpy(desc->desc, "netjack audio <==> net backend adapter");
01497
01498 desc->nparams = 13;
01499 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
01500
01501 i = 0;
01502 strcpy(desc->params[i].name, "channels");
01503 desc->params[i].character = 'c';
01504 desc->params[i].type = JackDriverParamInt;
01505 desc->params[i].value.ui = -1;
01506 strcpy(desc->params[i].short_desc, "Maximum number of channels");
01507 strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used");
01508
01509 i++;
01510 strcpy(desc->params[i].name, "inchannels");
01511 desc->params[i].character = 'i';
01512 desc->params[i].type = JackDriverParamInt;
01513 desc->params[i].value.ui = -1;
01514 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01515 strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used");
01516
01517 i++;
01518 strcpy(desc->params[i].name, "outchannels");
01519 desc->params[i].character = 'o';
01520 desc->params[i].type = JackDriverParamInt;
01521 desc->params[i].value.ui = -1;
01522 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01523 strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used");
01524
01525 i++;
01526 strcpy(desc->params[i].name, "capture");
01527 desc->params[i].character = 'C';
01528 desc->params[i].type = JackDriverParamString;
01529 strcpy(desc->params[i].short_desc, "Input CoreAudio device name");
01530 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01531
01532 i++;
01533 strcpy(desc->params[i].name, "playback");
01534 desc->params[i].character = 'P';
01535 desc->params[i].type = JackDriverParamString;
01536 strcpy(desc->params[i].short_desc, "Output CoreAudio device name");
01537 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01538
01539 i++;
01540 strcpy(desc->params[i].name, "rate");
01541 desc->params[i].character = 'r';
01542 desc->params[i].type = JackDriverParamUInt;
01543 desc->params[i].value.ui = 44100U;
01544 strcpy(desc->params[i].short_desc, "Sample rate");
01545 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01546
01547 i++;
01548 strcpy(desc->params[i].name, "period");
01549 desc->params[i].character = 'p';
01550 desc->params[i].type = JackDriverParamUInt;
01551 desc->params[i].value.ui = 512U;
01552 strcpy(desc->params[i].short_desc, "Frames per period");
01553 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01554
01555 i++;
01556 strcpy(desc->params[i].name, "duplex");
01557 desc->params[i].character = 'D';
01558 desc->params[i].type = JackDriverParamBool;
01559 desc->params[i].value.i = TRUE;
01560 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01561 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01562
01563 i++;
01564 strcpy(desc->params[i].name, "device");
01565 desc->params[i].character = 'd';
01566 desc->params[i].type = JackDriverParamString;
01567 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01568 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01569
01570 i++;
01571 strcpy(desc->params[i].name, "list-devices");
01572 desc->params[i].character = 'l';
01573 desc->params[i].type = JackDriverParamBool;
01574 desc->params[i].value.i = TRUE;
01575 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01576 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01577
01578 i++;
01579 strcpy(desc->params[i].name, "quality");
01580 desc->params[i].character = 'q';
01581 desc->params[i].type = JackDriverParamInt;
01582 desc->params[i].value.ui = 0;
01583 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
01584 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01585
01586 i++;
01587 strcpy(desc->params[i].name, "ring-buffer");
01588 desc->params[i].character = 'g';
01589 desc->params[i].type = JackDriverParamInt;
01590 desc->params[i].value.ui = 32768;
01591 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
01592 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
01593
01594 i++;
01595 strcpy(desc->params[i].name, "clock-drift");
01596 desc->params[i].character = 's';
01597 desc->params[i].type = JackDriverParamBool;
01598 desc->params[i].value.i = FALSE;
01599 strcpy(desc->params[i].short_desc, "Clock drift compensation");
01600 strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device");
01601
01602 return desc;
01603 }
01604
01605
01606 #ifdef __cplusplus
01607 }
01608 #endif
01609