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 namespace Jack
00025 {
00026
00027 static OSStatus DisplayDeviceNames()
00028 {
00029 UInt32 size;
00030 Boolean isWritable;
00031 int i, deviceNum;
00032 OSStatus err;
00033 CFStringRef UIname;
00034
00035 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00036 if (err != noErr)
00037 return err;
00038
00039 deviceNum = size / sizeof(AudioDeviceID);
00040 AudioDeviceID devices[deviceNum];
00041
00042 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00043 if (err != noErr)
00044 return err;
00045
00046 for (i = 0; i < deviceNum; i++) {
00047 char device_name[256];
00048 char internal_name[256];
00049
00050 size = sizeof(CFStringRef);
00051 UIname = NULL;
00052 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00053 if (err == noErr) {
00054 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00055 } else {
00056 goto error;
00057 }
00058
00059 size = 256;
00060 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00061 if (err != noErr)
00062 return err;
00063
00064 jack_info("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)", device_name, internal_name);
00065 }
00066
00067 return noErr;
00068
00069 error:
00070 if (UIname != NULL)
00071 CFRelease(UIname);
00072 return err;
00073 }
00074
00075 static void printError(OSStatus err)
00076 {
00077 switch (err) {
00078 case kAudioHardwareNoError:
00079 jack_log("error code : kAudioHardwareNoError");
00080 break;
00081 case kAudioConverterErr_FormatNotSupported:
00082 jack_log("error code : kAudioConverterErr_FormatNotSupported");
00083 break;
00084 case kAudioConverterErr_OperationNotSupported:
00085 jack_log("error code : kAudioConverterErr_OperationNotSupported");
00086 break;
00087 case kAudioConverterErr_PropertyNotSupported:
00088 jack_log("error code : kAudioConverterErr_PropertyNotSupported");
00089 break;
00090 case kAudioConverterErr_InvalidInputSize:
00091 jack_log("error code : kAudioConverterErr_InvalidInputSize");
00092 break;
00093 case kAudioConverterErr_InvalidOutputSize:
00094 jack_log("error code : kAudioConverterErr_InvalidOutputSize");
00095 break;
00096 case kAudioConverterErr_UnspecifiedError:
00097 jack_log("error code : kAudioConverterErr_UnspecifiedError");
00098 break;
00099 case kAudioConverterErr_BadPropertySizeError:
00100 jack_log("error code : kAudioConverterErr_BadPropertySizeError");
00101 break;
00102 case kAudioConverterErr_RequiresPacketDescriptionsError:
00103 jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
00104 break;
00105 case kAudioConverterErr_InputSampleRateOutOfRange:
00106 jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
00107 break;
00108 case kAudioConverterErr_OutputSampleRateOutOfRange:
00109 jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
00110 break;
00111 case kAudioHardwareNotRunningError:
00112 jack_log("error code : kAudioHardwareNotRunningError");
00113 break;
00114 case kAudioHardwareUnknownPropertyError:
00115 jack_log("error code : kAudioHardwareUnknownPropertyError");
00116 break;
00117 case kAudioHardwareIllegalOperationError:
00118 jack_log("error code : kAudioHardwareIllegalOperationError");
00119 break;
00120 case kAudioHardwareBadDeviceError:
00121 jack_log("error code : kAudioHardwareBadDeviceError");
00122 break;
00123 case kAudioHardwareBadStreamError:
00124 jack_log("error code : kAudioHardwareBadStreamError");
00125 break;
00126 case kAudioDeviceUnsupportedFormatError:
00127 jack_log("error code : kAudioDeviceUnsupportedFormatError");
00128 break;
00129 case kAudioDevicePermissionsError:
00130 jack_log("error code : kAudioDevicePermissionsError");
00131 break;
00132 case kAudioHardwareBadObjectError:
00133 jack_log("error code : kAudioHardwareBadObjectError");
00134 break;
00135 case kAudioHardwareUnsupportedOperationError:
00136 jack_log("error code : kAudioHardwareUnsupportedOperationError");
00137 break;
00138 default:
00139 jack_log("error code : unknown");
00140 break;
00141 }
00142 }
00143
00144 OSStatus JackCoreAudioAdapter::SRNotificationCallback(AudioDeviceID inDevice,
00145 UInt32 inChannel,
00146 Boolean isInput,
00147 AudioDevicePropertyID inPropertyID,
00148 void* inClientData)
00149 {
00150 JackCoreAudioAdapter* driver = static_cast<JackCoreAudioAdapter*>(inClientData);
00151
00152 switch (inPropertyID) {
00153
00154 case kAudioDevicePropertyNominalSampleRate: {
00155 jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
00156 driver->fState = true;
00157 break;
00158 }
00159 }
00160
00161 return noErr;
00162 }
00163
00164
00165
00166 OSStatus JackCoreAudioAdapter::DeviceNotificationCallback(AudioDeviceID inDevice,
00167 UInt32 inChannel,
00168 Boolean isInput,
00169 AudioDevicePropertyID inPropertyID,
00170 void* inClientData)
00171 {
00172 JackCoreAudioAdapter* driver = (JackCoreAudioAdapter*)inClientData;
00173
00174 switch (inPropertyID) {
00175
00176 case kAudioDevicePropertyStreamConfiguration:
00177 case kAudioDevicePropertyNominalSampleRate: {
00178
00179 UInt32 outSize = sizeof(Float64);
00180 Float64 sampleRate;
00181 int in_nChannels = 0;
00182 int out_nChannels = 0;
00183 char capture_driver_name[256];
00184 char playback_driver_name[256];
00185
00186
00187 AudioOutputUnitStop(driver->fAUHAL);
00188 driver->RemoveListeners();
00189 driver->CloseAUHAL();
00190
00191 OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00192 if (err != noErr) {
00193 jack_error("Cannot get current sample rate");
00194 printError(err);
00195 }
00196 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyNominalSampleRate %ld", long(sampleRate));
00197
00198 if (driver->SetupDevices(driver->fCaptureUID, driver->fPlaybackUID, capture_driver_name, playback_driver_name) < 0)
00199 return -1;
00200
00201 if (driver->SetupChannels(driver->fCapturing, driver->fPlaying, driver->fCaptureChannels, driver->fPlaybackChannels, in_nChannels, out_nChannels, false) < 0)
00202 return -1;
00203
00204 if (driver->SetupBufferSizeAndSampleRate(driver->fAdaptedBufferSize, sampleRate) < 0)
00205 return -1;
00206
00207 driver->SetAdaptedSampleRate(sampleRate);
00208
00209 if (driver->OpenAUHAL(driver->fCapturing,
00210 driver->fPlaying,
00211 driver->fCaptureChannels,
00212 driver->fPlaybackChannels,
00213 in_nChannels,
00214 out_nChannels,
00215 driver->fAdaptedBufferSize,
00216 sampleRate,
00217 false) < 0)
00218 goto error;
00219
00220 if (driver->AddListeners() < 0)
00221 goto error;
00222
00223 AudioOutputUnitStart(driver->fAUHAL);
00224 return noErr;
00225 error:
00226 driver->CloseAUHAL();
00227 break;
00228 }
00229 }
00230 return noErr;
00231 }
00232
00233 int JackCoreAudioAdapter::AddListeners()
00234 {
00235 OSStatus err = noErr;
00236
00237
00238
00239 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
00240 if (err != noErr) {
00241 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
00242 printError(err);
00243 return -1;
00244 }
00245
00246 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
00247 if (err != noErr) {
00248 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00249 printError(err);
00250 return -1;
00251 }
00252
00253 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
00254 if (err != noErr) {
00255 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
00256 printError(err);
00257 return -1;
00258 }
00259
00260 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00261 if (err != noErr) {
00262 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00263 printError(err);
00264 return -1;
00265 }
00266
00267 err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
00268 if (err != noErr) {
00269 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
00270 printError(err);
00271 return -1;
00272 }
00273
00274 return 0;
00275 }
00276
00277
00278 void JackCoreAudioAdapter::RemoveListeners()
00279 {
00280 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
00281 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
00282 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
00283 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00284 AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
00285 }
00286
00287 OSStatus JackCoreAudioAdapter::Render(void *inRefCon,
00288 AudioUnitRenderActionFlags *ioActionFlags,
00289 const AudioTimeStamp *inTimeStamp,
00290 UInt32 inBusNumber,
00291 UInt32 inNumberFrames,
00292 AudioBufferList *ioData)
00293 {
00294 JackCoreAudioAdapter* adapter = static_cast<JackCoreAudioAdapter*>(inRefCon);
00295 AudioUnitRender(adapter->fAUHAL, ioActionFlags, inTimeStamp, 1, inNumberFrames, adapter->fInputData);
00296 bool failure = false;
00297
00298 jack_nframes_t time1, time2;
00299 adapter->ResampleFactor(time1, time2);
00300
00301 for (int i = 0; i < adapter->fCaptureChannels; i++) {
00302 adapter->fCaptureRingBuffer[i]->SetRatio(time1, time2);
00303 if (adapter->fCaptureRingBuffer[i]->WriteResample((float*)adapter->fInputData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
00304 failure = true;
00305 }
00306
00307 for (int i = 0; i < adapter->fPlaybackChannels; i++) {
00308 adapter->fPlaybackRingBuffer[i]->SetRatio(time2, time1);
00309 if (adapter->fPlaybackRingBuffer[i]->ReadResample((float*)ioData->mBuffers[i].mData, inNumberFrames) < inNumberFrames)
00310 failure = true;
00311 }
00312
00313 #ifdef JACK_MONITOR
00314 adapter->fTable.Write(time1, time2, double(time1) / double(time2), double(time2) / double(time1),
00315 adapter->fCaptureRingBuffer[0]->ReadSpace(), adapter->fPlaybackRingBuffer[0]->WriteSpace());
00316 #endif
00317
00318
00319 if (failure) {
00320 jack_error("JackCoreAudioAdapter::Render ringbuffer failure... reset");
00321 adapter->ResetRingBuffers();
00322 }
00323
00324 return noErr;
00325 }
00326
00327 JackCoreAudioAdapter::JackCoreAudioAdapter(jack_nframes_t buffer_size, jack_nframes_t sample_rate, const JSList* params)
00328 :JackAudioAdapterInterface(buffer_size, sample_rate), fInputData(0), fCapturing(false), fPlaying(false), fState(false)
00329 {
00330
00331 const JSList* node;
00332 const jack_driver_param_t* param;
00333
00334 char captureName[256];
00335 char playbackName[256];
00336
00337 fCaptureUID[0] = 0;
00338 fPlaybackUID[0] = 0;
00339
00340
00341 fCaptureChannels = 0;
00342 fPlaybackChannels = 0;
00343
00344 for (node = params; node; node = jack_slist_next(node)) {
00345 param = (const jack_driver_param_t*) node->data;
00346
00347 switch (param->character) {
00348
00349 case 'c' :
00350 fCaptureChannels = fPlaybackChannels = param->value.ui;
00351 break;
00352
00353 case 'i':
00354 fCaptureChannels = param->value.ui;
00355 break;
00356
00357 case 'o':
00358 fPlaybackChannels = param->value.ui;
00359 break;
00360
00361 case 'C':
00362 fCapturing = true;
00363 strncpy(fCaptureUID, param->value.str, 256);
00364 break;
00365
00366 case 'P':
00367 fPlaying = true;
00368 strncpy(fPlaybackUID, param->value.str, 256);
00369 break;
00370
00371 case 'd':
00372 strncpy(fCaptureUID, param->value.str, 256);
00373 strncpy(fPlaybackUID, param->value.str, 256);
00374 break;
00375
00376 case 'D':
00377 fCapturing = fPlaying = true;
00378 break;
00379
00380 case 'r':
00381 SetAdaptedSampleRate(param->value.ui);
00382 break;
00383
00384 case 'p':
00385 SetAdaptedBufferSize(param->value.ui);
00386 break;
00387
00388 case 'l':
00389 DisplayDeviceNames();
00390 break;
00391
00392 case 'q':
00393 fQuality = param->value.ui;
00394 break;
00395 }
00396 }
00397
00398
00399 if (!fCapturing && !fPlaying) {
00400 fCapturing = true;
00401 fPlaying = true;
00402 }
00403
00404 int in_nChannels = 0;
00405 int out_nChannels = 0;
00406
00407 if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName) < 0)
00408 throw -1;
00409
00410 if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
00411 throw -1;
00412
00413 if (SetupBufferSizeAndSampleRate(fAdaptedBufferSize, fAdaptedSampleRate) < 0)
00414 throw -1;
00415
00416 if (fCapturing && fCaptureChannels > 0)
00417 if (SetupBuffers(fCaptureChannels) < 0)
00418 throw -1;
00419
00420 if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate, true) < 0)
00421 throw -1;
00422
00423 if (AddListeners() < 0)
00424 throw -1;
00425 }
00426
00427 OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
00428 {
00429 OSStatus res;
00430 UInt32 theSize = sizeof(UInt32);
00431 AudioDeviceID inDefault;
00432 AudioDeviceID outDefault;
00433
00434 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00435 return res;
00436
00437 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00438 return res;
00439
00440 jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
00441
00442
00443 if (inDefault == outDefault) {
00444 *id = inDefault;
00445 return noErr;
00446 } else {
00447 jack_error("Default input and output devices are not the same !!");
00448 return kAudioHardwareBadDeviceError;
00449 }
00450 }
00451
00452 OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
00453 {
00454 OSStatus err = noErr;
00455 UInt32 outSize;
00456 Boolean outWritable;
00457 AudioBufferList* bufferList = 0;
00458
00459 channelCount = 0;
00460 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00461 if (err == noErr) {
00462 bufferList = (AudioBufferList*)malloc(outSize);
00463 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00464 if (err == noErr) {
00465 for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
00466 channelCount += bufferList->mBuffers[i].mNumberChannels;
00467 }
00468
00469 if (bufferList)
00470 free(bufferList);
00471 }
00472
00473 return err;
00474 }
00475
00476 OSStatus JackCoreAudioAdapter::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00477 {
00478 UInt32 size = sizeof(AudioValueTranslation);
00479 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00480 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00481
00482 if (inIUD == NULL) {
00483 return kAudioHardwareUnspecifiedError;
00484 } else {
00485 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00486 CFRelease(inIUD);
00487 jack_log("GetDeviceIDFromUID %s %ld", UID, *id);
00488 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00489 }
00490 }
00491
00492 OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id)
00493 {
00494 OSStatus res;
00495 UInt32 theSize = sizeof(UInt32);
00496 AudioDeviceID inDefault;
00497
00498 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00499 return res;
00500
00501 jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
00502 *id = inDefault;
00503 return noErr;
00504 }
00505
00506 OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id)
00507 {
00508 OSStatus res;
00509 UInt32 theSize = sizeof(UInt32);
00510 AudioDeviceID outDefault;
00511
00512 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00513 return res;
00514
00515 jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
00516 *id = outDefault;
00517 return noErr;
00518 }
00519
00520 OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name)
00521 {
00522 UInt32 size = 256;
00523 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00524 }
00525
00526
00527 int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
00528 const char* playback_driver_uid,
00529 char* capture_driver_name,
00530 char* playback_driver_name)
00531 {
00532 capture_driver_name[0] = 0;
00533 playback_driver_name[0] = 0;
00534
00535
00536 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00537 jack_log("JackCoreAudioAdapter::Open duplex");
00538 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00539 if (GetDefaultDevice(&fDeviceID) != noErr) {
00540 jack_error("Cannot open default device");
00541 return -1;
00542 }
00543 }
00544 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00545 jack_error("Cannot get device name from device ID");
00546 return -1;
00547 }
00548
00549
00550 } else if (strcmp(capture_driver_uid, "") != 0) {
00551 jack_log("JackCoreAudioAdapter::Open capture only");
00552 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00553 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00554 jack_error("Cannot open default device");
00555 return -1;
00556 }
00557 }
00558 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00559 jack_error("Cannot get device name from device ID");
00560 return -1;
00561 }
00562
00563
00564 } else if (strcmp(playback_driver_uid, "") != 0) {
00565 jack_log("JackCoreAudioAdapter::Open playback only");
00566 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00567 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00568 jack_error("Cannot open default device");
00569 return -1;
00570 }
00571 }
00572 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00573 jack_error("Cannot get device name from device ID");
00574 return -1;
00575 }
00576
00577
00578 } else {
00579 jack_log("JackCoreAudioAdapter::Open default driver");
00580 if (GetDefaultDevice(&fDeviceID) != noErr) {
00581 jack_error("Cannot open default device");
00582 return -1;
00583 }
00584 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00585 jack_error("Cannot get device name from device ID");
00586 return -1;
00587 }
00588 }
00589
00590 return 0;
00591 }
00592
00593 int JackCoreAudioAdapter::SetupChannels(bool capturing,
00594 bool playing,
00595 int& inchannels,
00596 int& outchannels,
00597 int& in_nChannels,
00598 int& out_nChannels,
00599 bool strict)
00600 {
00601 OSStatus err = noErr;
00602
00603 if (capturing) {
00604 err = GetTotalChannels(fDeviceID, in_nChannels, true);
00605 if (err != noErr) {
00606 jack_error("Cannot get input channel number");
00607 printError(err);
00608 return -1;
00609 } else {
00610 jack_log("Max input channels : %d", in_nChannels);
00611 }
00612 }
00613
00614 if (playing) {
00615 err = GetTotalChannels(fDeviceID, out_nChannels, false);
00616 if (err != noErr) {
00617 jack_error("Cannot get output channel number");
00618 printError(err);
00619 return -1;
00620 } else {
00621 jack_log("Max output channels : %d", out_nChannels);
00622 }
00623 }
00624
00625 if (inchannels > in_nChannels) {
00626 jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00627 if (strict)
00628 return -1;
00629 }
00630
00631 if (outchannels > out_nChannels) {
00632 jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00633 if (strict)
00634 return -1;
00635 }
00636
00637 if (inchannels == 0) {
00638 jack_log("Setup max in channels = %ld", in_nChannels);
00639 inchannels = in_nChannels;
00640 }
00641
00642 if (outchannels == 0) {
00643 jack_log("Setup max out channels = %ld", out_nChannels);
00644 outchannels = out_nChannels;
00645 }
00646
00647 return 0;
00648 }
00649
00650 int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
00651 {
00652 OSStatus err = noErr;
00653 UInt32 outSize;
00654 Float64 sampleRate;
00655
00656
00657 outSize = sizeof(UInt32);
00658 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
00659 if (err != noErr) {
00660 jack_error("Cannot set buffer size %ld", nframes);
00661 printError(err);
00662 return -1;
00663 }
00664
00665
00666 outSize = sizeof(Float64);
00667 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00668 if (err != noErr) {
00669 jack_error("Cannot get current sample rate");
00670 printError(err);
00671 return -1;
00672 }
00673
00674
00675 if (samplerate != (jack_nframes_t)sampleRate) {
00676 sampleRate = (Float64)samplerate;
00677
00678
00679 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
00680 if (err != noErr) {
00681 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00682 printError(err);
00683 return -1;
00684 }
00685 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
00686 if (err != noErr) {
00687 jack_error("Cannot set sample rate = %ld", samplerate);
00688 printError(err);
00689 return -1;
00690 }
00691
00692
00693 int count = 0;
00694 while (!fState && count++ < 100) {
00695 usleep(100000);
00696 jack_log("Wait count = %ld", count);
00697 }
00698
00699
00700 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
00701 }
00702
00703 return 0;
00704 }
00705
00706 int JackCoreAudioAdapter::SetupBuffers(int inchannels)
00707 {
00708 jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld", inchannels);
00709
00710
00711 fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00712 if (fInputData == 0) {
00713 jack_error("Cannot allocate memory for input buffers");
00714 return -1;
00715 }
00716 fInputData->mNumberBuffers = inchannels;
00717 for (int i = 0; i < fCaptureChannels; i++) {
00718 fInputData->mBuffers[i].mNumberChannels = 1;
00719 fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float);
00720 fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float));
00721 }
00722 return 0;
00723 }
00724
00725 void JackCoreAudioAdapter::DisposeBuffers()
00726 {
00727 if (fInputData) {
00728 for (int i = 0; i < fCaptureChannels; i++)
00729 free(fInputData->mBuffers[i].mData);
00730 free(fInputData);
00731 fInputData = 0;
00732 }
00733 }
00734
00735 int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
00736 bool playing,
00737 int inchannels,
00738 int outchannels,
00739 int in_nChannels,
00740 int out_nChannels,
00741 jack_nframes_t buffer_size,
00742 jack_nframes_t samplerate,
00743 bool strict)
00744 {
00745 ComponentResult err1;
00746 UInt32 enableIO;
00747 AudioStreamBasicDescription srcFormat, dstFormat;
00748
00749 jack_log("OpenAUHAL capturing = %ld playing = %ld inchannels = %ld outchannels = %ld in_nChannels = %ld out_nChannels = %ld ", capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels);
00750
00751 if (inchannels == 0 && outchannels == 0) {
00752 jack_error("No input and output channels...");
00753 return -1;
00754 }
00755
00756
00757 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00758 Component HALOutput = FindNextComponent(NULL, &cd);
00759
00760 err1 = OpenAComponent(HALOutput, &fAUHAL);
00761 if (err1 != noErr) {
00762 jack_error("Error calling OpenAComponent");
00763 printError(err1);
00764 return -1;
00765 }
00766
00767 err1 = AudioUnitInitialize(fAUHAL);
00768 if (err1 != noErr) {
00769 jack_error("Cannot initialize AUHAL unit");
00770 printError(err1);
00771 return -1;
00772 }
00773
00774
00775 if (capturing && inchannels > 0) {
00776 enableIO = 1;
00777 jack_log("Setup AUHAL input on");
00778 } else {
00779 enableIO = 0;
00780 jack_log("Setup AUHAL input off");
00781 }
00782
00783 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00784 if (err1 != noErr) {
00785 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00786 printError(err1);
00787 if (strict)
00788 return -1;
00789 }
00790
00791 if (playing && outchannels > 0) {
00792 enableIO = 1;
00793 jack_log("Setup AUHAL output on");
00794 } else {
00795 enableIO = 0;
00796 jack_log("Setup AUHAL output off");
00797 }
00798
00799 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00800 if (err1 != noErr) {
00801 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00802 printError(err1);
00803 if (strict)
00804 return -1;
00805 }
00806
00807 AudioDeviceID currAudioDeviceID;
00808 UInt32 size = sizeof(AudioDeviceID);
00809 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00810 if (err1 != noErr) {
00811 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00812 printError(err1);
00813 if (strict)
00814 return -1;
00815 } else {
00816 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00817 }
00818
00819
00820 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00821 if (err1 != noErr) {
00822 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00823 printError(err1);
00824 if (strict)
00825 return -1;
00826 }
00827
00828 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00829 if (err1 != noErr) {
00830 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00831 printError(err1);
00832 if (strict)
00833 return -1;
00834 } else {
00835 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00836 }
00837
00838
00839 if (capturing && inchannels > 0) {
00840 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
00841 if (err1 != noErr) {
00842 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00843 printError(err1);
00844 if (strict)
00845 return -1;
00846 }
00847 }
00848
00849 if (playing && outchannels > 0) {
00850 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
00851 if (err1 != noErr) {
00852 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00853 printError(err1);
00854 if (strict)
00855 return -1;
00856 }
00857 }
00858
00859
00860 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00861 SInt32 chanArr[in_nChannels];
00862 for (int i = 0; i < in_nChannels; i++) {
00863 chanArr[i] = -1;
00864 }
00865 for (int i = 0; i < inchannels; i++) {
00866 chanArr[i] = i;
00867 }
00868 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00869 if (err1 != noErr) {
00870 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00871 printError(err1);
00872 }
00873 }
00874
00875 if (playing && outchannels > 0 && outchannels < out_nChannels) {
00876 SInt32 chanArr[out_nChannels];
00877 for (int i = 0; i < out_nChannels; i++) {
00878 chanArr[i] = -1;
00879 }
00880 for (int i = 0; i < outchannels; i++) {
00881 chanArr[i] = i;
00882 }
00883 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00884 if (err1 != noErr) {
00885 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00886 printError(err1);
00887 }
00888 }
00889
00890
00891 jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
00892 srcFormat.mSampleRate = samplerate;
00893 srcFormat.mFormatID = kAudioFormatLinearPCM;
00894 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00895 srcFormat.mBytesPerPacket = sizeof(float);
00896 srcFormat.mFramesPerPacket = 1;
00897 srcFormat.mBytesPerFrame = sizeof(float);
00898 srcFormat.mChannelsPerFrame = outchannels;
00899 srcFormat.mBitsPerChannel = 32;
00900
00901 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
00902 if (err1 != noErr) {
00903 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00904 printError(err1);
00905 }
00906
00907 jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
00908 dstFormat.mSampleRate = samplerate;
00909 dstFormat.mFormatID = kAudioFormatLinearPCM;
00910 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00911 dstFormat.mBytesPerPacket = sizeof(float);
00912 dstFormat.mFramesPerPacket = 1;
00913 dstFormat.mBytesPerFrame = sizeof(float);
00914 dstFormat.mChannelsPerFrame = inchannels;
00915 dstFormat.mBitsPerChannel = 32;
00916
00917 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
00918 if (err1 != noErr) {
00919 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00920 printError(err1);
00921 }
00922
00923
00924 if (inchannels > 0 && outchannels == 0) {
00925 AURenderCallbackStruct output;
00926 output.inputProc = Render;
00927 output.inputProcRefCon = this;
00928 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00929 if (err1 != noErr) {
00930 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
00931 printError(err1);
00932 return -1;
00933 }
00934 } else {
00935 AURenderCallbackStruct output;
00936 output.inputProc = Render;
00937 output.inputProcRefCon = this;
00938 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
00939 if (err1 != noErr) {
00940 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
00941 printError(err1);
00942 return -1;
00943 }
00944 }
00945
00946 return 0;
00947 }
00948
00949 void JackCoreAudioAdapter::CloseAUHAL()
00950 {
00951 AudioUnitUninitialize(fAUHAL);
00952 CloseComponent(fAUHAL);
00953 }
00954
00955 int JackCoreAudioAdapter::Open()
00956 {
00957 return (AudioOutputUnitStart(fAUHAL) != noErr) ? -1 : 0;
00958 }
00959
00960 int JackCoreAudioAdapter::Close()
00961 {
00962 #ifdef JACK_MONITOR
00963 fTable.Save();
00964 #endif
00965 AudioOutputUnitStop(fAUHAL);
00966 DisposeBuffers();
00967 CloseAUHAL();
00968 RemoveListeners();
00969 return 0;
00970 }
00971
00972 int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
00973 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00974 Close();
00975 return Open();
00976 }
00977
00978 int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
00979 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00980 Close();
00981 return Open();
00982 }
00983
00984 }
00985
00986 #ifdef __cplusplus
00987 extern "C"
00988 {
00989 #endif
00990
00991 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00992 {
00993 jack_driver_desc_t *desc;
00994 unsigned int i;
00995 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00996
00997 strcpy(desc->name, "audioadapter");
00998 strcpy(desc->desc, "netjack audio <==> net backend adapter");
00999
01000 desc->nparams = 11;
01001 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
01002
01003 i = 0;
01004 strcpy(desc->params[i].name, "channels");
01005 desc->params[i].character = 'c';
01006 desc->params[i].type = JackDriverParamInt;
01007 desc->params[i].value.ui = 0;
01008 strcpy(desc->params[i].short_desc, "Maximum number of channels");
01009 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01010
01011 i++;
01012 strcpy(desc->params[i].name, "inchannels");
01013 desc->params[i].character = 'i';
01014 desc->params[i].type = JackDriverParamInt;
01015 desc->params[i].value.ui = 0;
01016 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01017 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01018
01019 i++;
01020 strcpy(desc->params[i].name, "outchannels");
01021 desc->params[i].character = 'o';
01022 desc->params[i].type = JackDriverParamInt;
01023 desc->params[i].value.ui = 0;
01024 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01025 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01026
01027 i++;
01028 strcpy(desc->params[i].name, "capture");
01029 desc->params[i].character = 'C';
01030 desc->params[i].type = JackDriverParamString;
01031 strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
01032 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
01033 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01034
01035 i++;
01036 strcpy(desc->params[i].name, "playback");
01037 desc->params[i].character = 'P';
01038 desc->params[i].type = JackDriverParamString;
01039 strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
01040 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
01041 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01042
01043 i++;
01044 strcpy(desc->params[i].name, "rate");
01045 desc->params[i].character = 'r';
01046 desc->params[i].type = JackDriverParamUInt;
01047 desc->params[i].value.ui = 44100U;
01048 strcpy(desc->params[i].short_desc, "Sample rate");
01049 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01050
01051 i++;
01052 strcpy(desc->params[i].name, "periodsize");
01053 desc->params[i].character = 'p';
01054 desc->params[i].type = JackDriverParamUInt;
01055 desc->params[i].value.ui = 512U;
01056 strcpy(desc->params[i].short_desc, "Period size");
01057 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01058
01059 i++;
01060 strcpy(desc->params[i].name, "duplex");
01061 desc->params[i].character = 'D';
01062 desc->params[i].type = JackDriverParamBool;
01063 desc->params[i].value.i = TRUE;
01064 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01065 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01066
01067 i++;
01068 strcpy(desc->params[i].name, "device");
01069 desc->params[i].character = 'd';
01070 desc->params[i].type = JackDriverParamString;
01071 strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
01072 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01073 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01074
01075 i++;
01076 strcpy(desc->params[i].name, "list-devices");
01077 desc->params[i].character = 'l';
01078 desc->params[i].type = JackDriverParamBool;
01079 desc->params[i].value.i = TRUE;
01080 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01081 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01082
01083 i++;
01084 strcpy(desc->params[i].name, "quality");
01085 desc->params[i].character = 'q';
01086 desc->params[i].type = JackDriverParamInt;
01087 desc->params[i].value.ui = 0;
01088 strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)");
01089 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01090
01091 return desc;
01092 }
01093
01094
01095 #ifdef __cplusplus
01096 }
01097 #endif
01098