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 jack_default_audio_sample_t* inputBuffer[adapter->fCaptureChannels];
00280 jack_default_audio_sample_t* outputBuffer[adapter->fPlaybackChannels];
00281
00282 for (int i = 0; i < adapter->fCaptureChannels; i++) {
00283 inputBuffer[i] = (jack_default_audio_sample_t*)adapter->fInputData->mBuffers[i].mData;
00284 }
00285 for (int i = 0; i < adapter->fPlaybackChannels; i++) {
00286 outputBuffer[i] = (jack_default_audio_sample_t*)ioData->mBuffers[i].mData;
00287 }
00288
00289 adapter->PushAndPull((jack_default_audio_sample_t**)inputBuffer, (jack_default_audio_sample_t**)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 if (inDefault == 0) {
00492 jack_error("Error : input device is 0, please select a correct one !!");
00493 return -1;
00494 }
00495 jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
00496 *id = inDefault;
00497 return noErr;
00498 }
00499
00500 OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id)
00501 {
00502 OSStatus res;
00503 UInt32 theSize = sizeof(UInt32);
00504 AudioDeviceID outDefault;
00505
00506 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00507 return res;
00508
00509 if (outDefault == 0) {
00510 jack_error("Error : output device is 0, please select a correct one !!");
00511 return -1;
00512 }
00513 jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
00514 *id = outDefault;
00515 return noErr;
00516 }
00517
00518 OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name)
00519 {
00520 UInt32 size = 256;
00521 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00522 }
00523
00524
00525 int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
00526 const char* playback_driver_uid,
00527 char* capture_driver_name,
00528 char* playback_driver_name,
00529 jack_nframes_t samplerate)
00530 {
00531 capture_driver_name[0] = 0;
00532 playback_driver_name[0] = 0;
00533
00534
00535 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00536
00537
00538 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
00539
00540 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00541 jack_log("Will take default in/out");
00542 if (GetDefaultDevice(&fDeviceID) != noErr) {
00543 jack_error("Cannot open default device");
00544 return -1;
00545 }
00546 }
00547 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00548 jack_error("Cannot get device name from device ID");
00549 return -1;
00550 }
00551
00552 } else {
00553
00554
00555 AudioDeviceID captureID, playbackID;
00556
00557 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
00558 jack_log("Will take default input");
00559 if (GetDefaultInputDevice(&captureID) != noErr) {
00560 jack_error("Cannot open default input device");
00561 return -1;
00562 }
00563 }
00564
00565 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
00566 jack_log("Will take default output");
00567 if (GetDefaultOutputDevice(&playbackID) != noErr) {
00568 jack_error("Cannot open default output device");
00569 return -1;
00570 }
00571 }
00572
00573 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
00574 return -1;
00575 }
00576
00577
00578 } else if (strcmp(capture_driver_uid, "") != 0) {
00579 jack_log("JackCoreAudioAdapter::Open capture only");
00580 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00581 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00582 jack_error("Cannot open default input device");
00583 return -1;
00584 }
00585 }
00586 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00587 jack_error("Cannot get device name from device ID");
00588 return -1;
00589 }
00590
00591
00592 } else if (strcmp(playback_driver_uid, "") != 0) {
00593 jack_log("JackCoreAudioAdapter::Open playback only");
00594 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00595 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00596 jack_error("Cannot open default output device");
00597 return -1;
00598 }
00599 }
00600 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00601 jack_error("Cannot get device name from device ID");
00602 return -1;
00603 }
00604
00605
00606 } else {
00607 jack_log("JackCoreAudioDriver::Open default driver");
00608 if (GetDefaultDevice(&fDeviceID) != noErr) {
00609 jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
00610
00611
00612 AudioDeviceID captureID, playbackID;
00613
00614 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
00615 jack_log("Will take default input");
00616 if (GetDefaultInputDevice(&captureID) != noErr) {
00617 jack_error("Cannot open default input device");
00618 return -1;
00619 }
00620 }
00621
00622 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
00623 jack_log("Will take default output");
00624 if (GetDefaultOutputDevice(&playbackID) != noErr) {
00625 jack_error("Cannot open default output device");
00626 return -1;
00627 }
00628 }
00629
00630 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
00631 return -1;
00632 }
00633 }
00634
00635 return 0;
00636 }
00637
00638 int JackCoreAudioAdapter::SetupChannels(bool capturing,
00639 bool playing,
00640 int& inchannels,
00641 int& outchannels,
00642 int& in_nChannels,
00643 int& out_nChannels,
00644 bool strict)
00645 {
00646 OSStatus err = noErr;
00647
00648 if (capturing) {
00649 err = GetTotalChannels(fDeviceID, in_nChannels, true);
00650 if (err != noErr) {
00651 jack_error("Cannot get input channel number");
00652 printError(err);
00653 return -1;
00654 } else {
00655 jack_log("Max input channels : %d", in_nChannels);
00656 }
00657 }
00658
00659 if (playing) {
00660 err = GetTotalChannels(fDeviceID, out_nChannels, false);
00661 if (err != noErr) {
00662 jack_error("Cannot get output channel number");
00663 printError(err);
00664 return -1;
00665 } else {
00666 jack_log("Max output channels : %d", out_nChannels);
00667 }
00668 }
00669
00670 if (inchannels > in_nChannels) {
00671 jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00672 if (strict)
00673 return -1;
00674 }
00675
00676 if (outchannels > out_nChannels) {
00677 jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00678 if (strict)
00679 return -1;
00680 }
00681
00682 if (inchannels == -1) {
00683 jack_log("Setup max in channels = %ld", in_nChannels);
00684 inchannels = in_nChannels;
00685 }
00686
00687 if (outchannels == -1) {
00688 jack_log("Setup max out channels = %ld", out_nChannels);
00689 outchannels = out_nChannels;
00690 }
00691
00692 return 0;
00693 }
00694
00695 int JackCoreAudioAdapter::SetupBufferSize(jack_nframes_t buffer_size)
00696 {
00697
00698 UInt32 outSize = sizeof(UInt32);
00699 OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
00700 if (err != noErr) {
00701 jack_error("Cannot set buffer size %ld", buffer_size);
00702 printError(err);
00703 return -1;
00704 }
00705
00706 return 0;
00707 }
00708
00709 int JackCoreAudioAdapter::SetupSampleRate(jack_nframes_t samplerate)
00710 {
00711 return SetupSampleRateAux(fDeviceID, samplerate);
00712 }
00713
00714 int JackCoreAudioAdapter::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate)
00715 {
00716 OSStatus err = noErr;
00717 UInt32 outSize;
00718 Float64 sampleRate;
00719
00720
00721 outSize = sizeof(Float64);
00722 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00723 if (err != noErr) {
00724 jack_error("Cannot get current sample rate");
00725 printError(err);
00726 return -1;
00727 } else {
00728 jack_log("Current sample rate = %f", sampleRate);
00729 }
00730
00731
00732 if (samplerate != (jack_nframes_t)sampleRate) {
00733 sampleRate = (Float64)samplerate;
00734
00735
00736 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
00737 if (err != noErr) {
00738 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00739 printError(err);
00740 return -1;
00741 }
00742 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
00743 if (err != noErr) {
00744 jack_error("Cannot set sample rate = %ld", samplerate);
00745 printError(err);
00746 return -1;
00747 }
00748
00749
00750 int count = 0;
00751 while (!fState && count++ < WAIT_COUNTER) {
00752 usleep(100000);
00753 jack_log("Wait count = %d", count);
00754 }
00755
00756
00757 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
00758 }
00759
00760 return 0;
00761 }
00762
00763 int JackCoreAudioAdapter::SetupBuffers(int inchannels)
00764 {
00765 jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld", inchannels);
00766
00767
00768 fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00769 fInputData->mNumberBuffers = inchannels;
00770 for (int i = 0; i < fCaptureChannels; i++) {
00771 fInputData->mBuffers[i].mNumberChannels = 1;
00772 fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(jack_default_audio_sample_t);
00773 fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(jack_default_audio_sample_t));
00774 }
00775 return 0;
00776 }
00777
00778 void JackCoreAudioAdapter::DisposeBuffers()
00779 {
00780 if (fInputData) {
00781 for (int i = 0; i < fCaptureChannels; i++)
00782 free(fInputData->mBuffers[i].mData);
00783 free(fInputData);
00784 fInputData = 0;
00785 }
00786 }
00787
00788 int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
00789 bool playing,
00790 int inchannels,
00791 int outchannels,
00792 int in_nChannels,
00793 int out_nChannels,
00794 jack_nframes_t buffer_size,
00795 jack_nframes_t samplerate)
00796 {
00797 ComponentResult err1;
00798 UInt32 enableIO;
00799 AudioStreamBasicDescription srcFormat, dstFormat;
00800 AudioDeviceID currAudioDeviceID;
00801 UInt32 size;
00802
00803 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);
00804
00805 if (inchannels == 0 && outchannels == 0) {
00806 jack_error("No input and output channels...");
00807 return -1;
00808 }
00809
00810
00811 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00812 Component HALOutput = FindNextComponent(NULL, &cd);
00813
00814 err1 = OpenAComponent(HALOutput, &fAUHAL);
00815 if (err1 != noErr) {
00816 jack_error("Error calling OpenAComponent");
00817 printError(err1);
00818 goto error;
00819 }
00820
00821 err1 = AudioUnitInitialize(fAUHAL);
00822 if (err1 != noErr) {
00823 jack_error("Cannot initialize AUHAL unit");
00824 printError(err1);
00825 goto error;
00826 }
00827
00828
00829 if (capturing && inchannels > 0) {
00830 enableIO = 1;
00831 jack_log("Setup AUHAL input on");
00832 } else {
00833 enableIO = 0;
00834 jack_log("Setup AUHAL input off");
00835 }
00836
00837 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00838 if (err1 != noErr) {
00839 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00840 printError(err1);
00841 goto error;
00842 }
00843
00844 if (playing && outchannels > 0) {
00845 enableIO = 1;
00846 jack_log("Setup AUHAL output on");
00847 } else {
00848 enableIO = 0;
00849 jack_log("Setup AUHAL output off");
00850 }
00851
00852 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00853 if (err1 != noErr) {
00854 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00855 printError(err1);
00856 goto error;
00857 }
00858
00859 size = sizeof(AudioDeviceID);
00860 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00861 if (err1 != noErr) {
00862 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00863 printError(err1);
00864 goto error;
00865 } else {
00866 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00867 }
00868
00869
00870 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00871 if (err1 != noErr) {
00872 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00873 printError(err1);
00874 goto error;
00875 }
00876
00877
00878 if (capturing && inchannels > 0) {
00879 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
00880 if (err1 != noErr) {
00881 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00882 printError(err1);
00883 goto error;
00884 }
00885 }
00886
00887 if (playing && outchannels > 0) {
00888 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
00889 if (err1 != noErr) {
00890 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00891 printError(err1);
00892 goto error;
00893 }
00894 }
00895
00896
00897 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00898 SInt32 chanArr[in_nChannels];
00899 for (int i = 0; i < in_nChannels; i++) {
00900 chanArr[i] = -1;
00901 }
00902 for (int i = 0; i < inchannels; i++) {
00903 chanArr[i] = i;
00904 }
00905 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00906 if (err1 != noErr) {
00907 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00908 printError(err1);
00909 goto error;
00910 }
00911 }
00912
00913 if (playing && outchannels > 0 && outchannels < out_nChannels) {
00914 SInt32 chanArr[out_nChannels];
00915 for (int i = 0; i < out_nChannels; i++) {
00916 chanArr[i] = -1;
00917 }
00918 for (int i = 0; i < outchannels; i++) {
00919 chanArr[i] = i;
00920 }
00921 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00922 if (err1 != noErr) {
00923 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00924 printError(err1);
00925 goto error;
00926 }
00927 }
00928
00929
00930 if (capturing && inchannels > 0) {
00931
00932 size = sizeof(AudioStreamBasicDescription);
00933 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size);
00934 if (err1 != noErr) {
00935 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00936 printError(err1);
00937 goto error;
00938 }
00939 PrintStreamDesc(&srcFormat);
00940
00941 jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
00942 srcFormat.mSampleRate = samplerate;
00943 srcFormat.mFormatID = kAudioFormatLinearPCM;
00944 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00945 srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
00946 srcFormat.mFramesPerPacket = 1;
00947 srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
00948 srcFormat.mChannelsPerFrame = inchannels;
00949 srcFormat.mBitsPerChannel = 32;
00950 PrintStreamDesc(&srcFormat);
00951
00952 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
00953
00954 if (err1 != noErr) {
00955 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00956 printError(err1);
00957 goto error;
00958 }
00959 }
00960
00961 if (playing && outchannels > 0) {
00962
00963 size = sizeof(AudioStreamBasicDescription);
00964 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size);
00965 if (err1 != noErr) {
00966 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00967 printError(err1);
00968 goto error;
00969 }
00970 PrintStreamDesc(&dstFormat);
00971
00972 jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
00973 dstFormat.mSampleRate = samplerate;
00974 dstFormat.mFormatID = kAudioFormatLinearPCM;
00975 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00976 dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
00977 dstFormat.mFramesPerPacket = 1;
00978 dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
00979 dstFormat.mChannelsPerFrame = outchannels;
00980 dstFormat.mBitsPerChannel = 32;
00981 PrintStreamDesc(&dstFormat);
00982
00983 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
00984
00985 if (err1 != noErr) {
00986 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00987 printError(err1);
00988 goto error;
00989 }
00990 }
00991
00992
00993 if (inchannels > 0 && outchannels == 0) {
00994 AURenderCallbackStruct output;
00995 output.inputProc = Render;
00996 output.inputProcRefCon = this;
00997 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00998 if (err1 != noErr) {
00999 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
01000 printError(err1);
01001 goto error;
01002 }
01003 } else {
01004 AURenderCallbackStruct output;
01005 output.inputProc = Render;
01006 output.inputProcRefCon = this;
01007 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
01008 if (err1 != noErr) {
01009 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
01010 printError(err1);
01011 goto error;
01012 }
01013 }
01014
01015 return 0;
01016
01017 error:
01018 CloseAUHAL();
01019 return -1;
01020 }
01021
01022 OSStatus JackCoreAudioAdapter::DestroyAggregateDevice()
01023 {
01024 OSStatus osErr = noErr;
01025 AudioObjectPropertyAddress pluginAOPA;
01026 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
01027 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01028 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01029 UInt32 outDataSize;
01030
01031 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
01032 if (osErr != noErr) {
01033 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
01034 printError(osErr);
01035 return osErr;
01036 }
01037
01038 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
01039 if (osErr != noErr) {
01040 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
01041 printError(osErr);
01042 return osErr;
01043 }
01044
01045 return noErr;
01046 }
01047
01048 static CFStringRef GetDeviceName(AudioDeviceID id)
01049 {
01050 UInt32 size = sizeof(CFStringRef);
01051 CFStringRef UIname;
01052 OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
01053 return (err == noErr) ? UIname : NULL;
01054 }
01055
01056 OSStatus JackCoreAudioAdapter::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
01057 {
01058 OSStatus err = noErr;
01059 AudioObjectID sub_device[32];
01060 UInt32 outSize = sizeof(sub_device);
01061
01062 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01063 vector<AudioDeviceID> captureDeviceIDArray;
01064
01065 if (err != noErr) {
01066 jack_log("Input device does not have subdevices");
01067 captureDeviceIDArray.push_back(captureDeviceID);
01068 } else {
01069 int num_devices = outSize / sizeof(AudioObjectID);
01070 jack_log("Input device has %d subdevices", num_devices);
01071 for (int i = 0; i < num_devices; i++) {
01072 captureDeviceIDArray.push_back(sub_device[i]);
01073 }
01074 }
01075
01076 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01077 vector<AudioDeviceID> playbackDeviceIDArray;
01078
01079 if (err != noErr) {
01080 jack_log("Output device does not have subdevices");
01081 playbackDeviceIDArray.push_back(playbackDeviceID);
01082 } else {
01083 int num_devices = outSize / sizeof(AudioObjectID);
01084 jack_log("Output device has %d subdevices", num_devices);
01085 for (int i = 0; i < num_devices; i++) {
01086 playbackDeviceIDArray.push_back(sub_device[i]);
01087 }
01088 }
01089
01090 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
01091 }
01092
01093 OSStatus JackCoreAudioAdapter::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
01094 {
01095 OSStatus osErr = noErr;
01096 UInt32 outSize;
01097 Boolean outWritable;
01098
01099
01100
01101 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01102 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01103 UInt32 theQualifierDataSize = sizeof(AudioObjectID);
01104 AudioClassID inClass = kAudioSubDeviceClassID;
01105 void* theQualifierData = &inClass;
01106 UInt32 subDevicesNum = 0;
01107
01108
01109
01110
01111 UInt32 keptclockdomain = 0;
01112 UInt32 clockdomain = 0;
01113 outSize = sizeof(UInt32);
01114 bool need_clock_drift_compensation = false;
01115
01116 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01117 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
01118 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
01119 } else {
01120
01121 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
01122 if (osErr != 0) {
01123 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
01124 printError(osErr);
01125 } else {
01126 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
01127 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
01128 if (clockdomain != 0 && clockdomain != keptclockdomain) {
01129 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
01130 need_clock_drift_compensation = true;
01131 }
01132 }
01133 }
01134 }
01135
01136 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01137 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
01138 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
01139 } else {
01140
01141 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
01142 if (osErr != 0) {
01143 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
01144 printError(osErr);
01145 } else {
01146 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
01147 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
01148 if (clockdomain != 0 && clockdomain != keptclockdomain) {
01149 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
01150 need_clock_drift_compensation = true;
01151 }
01152 }
01153 }
01154 }
01155
01156
01157 if (keptclockdomain == 0) {
01158 need_clock_drift_compensation = true;
01159 }
01160
01161
01162
01163
01164
01165 char device_name[256];
01166 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01167 GetDeviceNameFromID(captureDeviceID[i], device_name);
01168 jack_info("Separated input = '%s' ", device_name);
01169 }
01170
01171 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01172 GetDeviceNameFromID(playbackDeviceID[i], device_name);
01173 jack_info("Separated output = '%s' ", device_name);
01174 }
01175
01176 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
01177 if (osErr != noErr) {
01178 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
01179 printError(osErr);
01180 return osErr;
01181 }
01182
01183 AudioValueTranslation pluginAVT;
01184
01185 CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
01186
01187 pluginAVT.mInputData = &inBundleRef;
01188 pluginAVT.mInputDataSize = sizeof(inBundleRef);
01189 pluginAVT.mOutputData = &fPluginID;
01190 pluginAVT.mOutputDataSize = sizeof(fPluginID);
01191
01192 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
01193 if (osErr != noErr) {
01194 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
01195 printError(osErr);
01196 return osErr;
01197 }
01198
01199
01200
01201
01202
01203 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
01204
01205 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
01206 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
01207
01208
01209 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
01210
01211
01212 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
01213
01214
01215 int value = 1;
01216 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
01217
01218 SInt32 system;
01219 Gestalt(gestaltSystemVersion, &system);
01220
01221 jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
01222
01223
01224 if (system < 0x00001054) {
01225 jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
01226 } else {
01227 jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
01228 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
01229 }
01230
01231
01232 CFMutableArrayRef subDevicesArrayClock = NULL;
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
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
01276
01277 vector<CFStringRef> captureDeviceUID;
01278 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01279 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
01280 if (ref == NULL)
01281 return -1;
01282 captureDeviceUID.push_back(ref);
01283
01284 CFArrayAppendValue(subDevicesArray, ref);
01285 }
01286
01287 vector<CFStringRef> playbackDeviceUID;
01288 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01289 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
01290 if (ref == NULL)
01291 return -1;
01292 playbackDeviceUID.push_back(ref);
01293
01294 CFArrayAppendValue(subDevicesArray, ref);
01295 }
01296
01297
01298
01299
01300
01301 AudioObjectPropertyAddress pluginAOPA;
01302 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
01303 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01304 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01305 UInt32 outDataSize;
01306
01307 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
01308 if (osErr != noErr) {
01309 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
01310 printError(osErr);
01311 goto error;
01312 }
01313
01314 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
01315 if (osErr != noErr) {
01316 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
01317 printError(osErr);
01318 goto error;
01319 }
01320
01321
01322
01323 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01324
01325
01326
01327
01328
01329 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
01330 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01331 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01332 outDataSize = sizeof(CFMutableArrayRef);
01333 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
01334 if (osErr != noErr) {
01335 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
01336 printError(osErr);
01337 goto error;
01338 }
01339
01340
01341 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01342
01343
01344
01345
01346
01347
01348
01349 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
01350 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01351 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01352 outDataSize = sizeof(CFStringRef);
01353 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
01354 if (osErr != noErr) {
01355 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
01356 printError(osErr);
01357 goto error;
01358 }
01359
01360
01361 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01362
01363
01364
01365
01366 if (fClockDriftCompensate) {
01367 if (need_clock_drift_compensation) {
01368 jack_info("Clock drift compensation activated...");
01369
01370
01371 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
01372 if (osErr != noErr) {
01373 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01374 printError(osErr);
01375 }
01376
01377
01378 subDevicesNum = outSize / sizeof(AudioObjectID);
01379 jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
01380 AudioObjectID subDevices[subDevicesNum];
01381 outSize = sizeof(subDevices);
01382
01383 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
01384 if (osErr != noErr) {
01385 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01386 printError(osErr);
01387 }
01388
01389
01390 for (UInt32 index = 0; index < subDevicesNum; ++index) {
01391 UInt32 theDriftCompensationValue = 1;
01392 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
01393 if (osErr != noErr) {
01394 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
01395 printError(osErr);
01396 }
01397 }
01398 } else {
01399 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
01400 }
01401 }
01402
01403
01404 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01405
01406
01407
01408
01409
01410
01411 CFRelease(AggregateDeviceNumberRef);
01412
01413
01414 CFRelease(aggDeviceDict);
01415 CFRelease(subDevicesArray);
01416
01417 if (subDevicesArrayClock)
01418 CFRelease(subDevicesArrayClock);
01419
01420
01421 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
01422 CFRelease(captureDeviceUID[i]);
01423 }
01424
01425 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
01426 CFRelease(playbackDeviceUID[i]);
01427 }
01428
01429 jack_log("New aggregate device %ld", *outAggregateDevice);
01430 return noErr;
01431
01432 error:
01433 DestroyAggregateDevice();
01434 return -1;
01435 }
01436
01437
01438 bool JackCoreAudioAdapter::IsAggregateDevice(AudioDeviceID device)
01439 {
01440 OSStatus err = noErr;
01441 AudioObjectID sub_device[32];
01442 UInt32 outSize = sizeof(sub_device);
01443 err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01444
01445 if (err != noErr) {
01446 jack_log("Device does not have subdevices");
01447 return false;
01448 } else {
01449 int num_devices = outSize / sizeof(AudioObjectID);
01450 jack_log("Device does has %d subdevices", num_devices);
01451 return true;
01452 }
01453 }
01454
01455 void JackCoreAudioAdapter::CloseAUHAL()
01456 {
01457 AudioUnitUninitialize(fAUHAL);
01458 CloseComponent(fAUHAL);
01459 }
01460
01461 int JackCoreAudioAdapter::Open()
01462 {
01463 return (AudioOutputUnitStart(fAUHAL) != noErr) ? -1 : 0;
01464 }
01465
01466 int JackCoreAudioAdapter::Close()
01467 {
01468 #ifdef JACK_MONITOR
01469 fTable.Save(fHostBufferSize, fHostSampleRate, fAdaptedSampleRate, fAdaptedBufferSize);
01470 #endif
01471 AudioOutputUnitStop(fAUHAL);
01472 DisposeBuffers();
01473 CloseAUHAL();
01474 RemoveListeners();
01475 if (fPluginID > 0)
01476 DestroyAggregateDevice();
01477 return 0;
01478 }
01479
01480 int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
01481 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
01482 Close();
01483 return Open();
01484 }
01485
01486 int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
01487 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
01488 Close();
01489 return Open();
01490 }
01491
01492 }
01493
01494 #ifdef __cplusplus
01495 extern "C"
01496 {
01497 #endif
01498
01499 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
01500 {
01501 jack_driver_desc_t *desc;
01502 unsigned int i;
01503 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
01504
01505 strcpy(desc->name, "audioadapter");
01506 strcpy(desc->desc, "netjack audio <==> net backend adapter");
01507
01508 desc->nparams = 13;
01509 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
01510
01511 i = 0;
01512 strcpy(desc->params[i].name, "channels");
01513 desc->params[i].character = 'c';
01514 desc->params[i].type = JackDriverParamInt;
01515 desc->params[i].value.ui = -1;
01516 strcpy(desc->params[i].short_desc, "Maximum number of channels");
01517 strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used");
01518
01519 i++;
01520 strcpy(desc->params[i].name, "inchannels");
01521 desc->params[i].character = 'i';
01522 desc->params[i].type = JackDriverParamInt;
01523 desc->params[i].value.ui = -1;
01524 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01525 strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used");
01526
01527 i++;
01528 strcpy(desc->params[i].name, "outchannels");
01529 desc->params[i].character = 'o';
01530 desc->params[i].type = JackDriverParamInt;
01531 desc->params[i].value.ui = -1;
01532 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01533 strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used");
01534
01535 i++;
01536 strcpy(desc->params[i].name, "capture");
01537 desc->params[i].character = 'C';
01538 desc->params[i].type = JackDriverParamString;
01539 strcpy(desc->params[i].short_desc, "Input CoreAudio device name");
01540 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01541
01542 i++;
01543 strcpy(desc->params[i].name, "playback");
01544 desc->params[i].character = 'P';
01545 desc->params[i].type = JackDriverParamString;
01546 strcpy(desc->params[i].short_desc, "Output CoreAudio device name");
01547 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01548
01549 i++;
01550 strcpy(desc->params[i].name, "rate");
01551 desc->params[i].character = 'r';
01552 desc->params[i].type = JackDriverParamUInt;
01553 desc->params[i].value.ui = 44100U;
01554 strcpy(desc->params[i].short_desc, "Sample rate");
01555 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01556
01557 i++;
01558 strcpy(desc->params[i].name, "period");
01559 desc->params[i].character = 'p';
01560 desc->params[i].type = JackDriverParamUInt;
01561 desc->params[i].value.ui = 512U;
01562 strcpy(desc->params[i].short_desc, "Frames per period");
01563 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01564
01565 i++;
01566 strcpy(desc->params[i].name, "duplex");
01567 desc->params[i].character = 'D';
01568 desc->params[i].type = JackDriverParamBool;
01569 desc->params[i].value.i = TRUE;
01570 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01571 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01572
01573 i++;
01574 strcpy(desc->params[i].name, "device");
01575 desc->params[i].character = 'd';
01576 desc->params[i].type = JackDriverParamString;
01577 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01578 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01579
01580 i++;
01581 strcpy(desc->params[i].name, "list-devices");
01582 desc->params[i].character = 'l';
01583 desc->params[i].type = JackDriverParamBool;
01584 desc->params[i].value.i = TRUE;
01585 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01586 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01587
01588 i++;
01589 strcpy(desc->params[i].name, "quality");
01590 desc->params[i].character = 'q';
01591 desc->params[i].type = JackDriverParamInt;
01592 desc->params[i].value.ui = 0;
01593 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
01594 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01595
01596 i++;
01597 strcpy(desc->params[i].name, "ring-buffer");
01598 desc->params[i].character = 'g';
01599 desc->params[i].type = JackDriverParamInt;
01600 desc->params[i].value.ui = 32768;
01601 strcpy(desc->params[i].short_desc, "Fixed ringbuffer size");
01602 strcpy(desc->params[i].long_desc, "Fixed ringbuffer size (if not set => automatic adaptative)");
01603
01604 i++;
01605 strcpy(desc->params[i].name, "clock-drift");
01606 desc->params[i].character = 's';
01607 desc->params[i].type = JackDriverParamBool;
01608 desc->params[i].value.i = FALSE;
01609 strcpy(desc->params[i].short_desc, "Clock drift compensation");
01610 strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device");
01611
01612 return desc;
01613 }
01614
01615
01616 #ifdef __cplusplus
01617 }
01618 #endif
01619