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 }
00393
00394
00395 if (!fCapturing && !fPlaying) {
00396 fCapturing = true;
00397 fPlaying = true;
00398 }
00399
00400 int in_nChannels = 0;
00401 int out_nChannels = 0;
00402
00403 if (SetupDevices(fCaptureUID, fPlaybackUID, captureName, playbackName) < 0)
00404 throw -1;
00405
00406 if (SetupChannels(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, true) < 0)
00407 throw -1;
00408
00409 if (SetupBufferSizeAndSampleRate(fAdaptedBufferSize, fAdaptedSampleRate) < 0)
00410 throw -1;
00411
00412 if (fCapturing && fCaptureChannels > 0)
00413 if (SetupBuffers(fCaptureChannels) < 0)
00414 throw -1;
00415
00416 if (OpenAUHAL(fCapturing, fPlaying, fCaptureChannels, fPlaybackChannels, in_nChannels, out_nChannels, fAdaptedBufferSize, fAdaptedSampleRate, true) < 0)
00417 throw -1;
00418
00419 if (AddListeners() < 0)
00420 throw -1;
00421 }
00422
00423 OSStatus JackCoreAudioAdapter::GetDefaultDevice(AudioDeviceID* id)
00424 {
00425 OSStatus res;
00426 UInt32 theSize = sizeof(UInt32);
00427 AudioDeviceID inDefault;
00428 AudioDeviceID outDefault;
00429
00430 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00431 return res;
00432
00433 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00434 return res;
00435
00436 jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
00437
00438
00439 if (inDefault == outDefault) {
00440 *id = inDefault;
00441 return noErr;
00442 } else {
00443 jack_error("Default input and output devices are not the same !!");
00444 return kAudioHardwareBadDeviceError;
00445 }
00446 }
00447
00448 OSStatus JackCoreAudioAdapter::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
00449 {
00450 OSStatus err = noErr;
00451 UInt32 outSize;
00452 Boolean outWritable;
00453 AudioBufferList* bufferList = 0;
00454
00455 channelCount = 0;
00456 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00457 if (err == noErr) {
00458 bufferList = (AudioBufferList*)malloc(outSize);
00459 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00460 if (err == noErr) {
00461 for (unsigned int i = 0; i < bufferList->mNumberBuffers; i++)
00462 channelCount += bufferList->mBuffers[i].mNumberChannels;
00463 }
00464
00465 if (bufferList)
00466 free(bufferList);
00467 }
00468
00469 return err;
00470 }
00471
00472 OSStatus JackCoreAudioAdapter::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00473 {
00474 UInt32 size = sizeof(AudioValueTranslation);
00475 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00476 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00477
00478 if (inIUD == NULL) {
00479 return kAudioHardwareUnspecifiedError;
00480 } else {
00481 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00482 CFRelease(inIUD);
00483 jack_log("GetDeviceIDFromUID %s %ld", UID, *id);
00484 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00485 }
00486 }
00487
00488 OSStatus JackCoreAudioAdapter::GetDefaultInputDevice(AudioDeviceID* id)
00489 {
00490 OSStatus res;
00491 UInt32 theSize = sizeof(UInt32);
00492 AudioDeviceID inDefault;
00493
00494 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr)
00495 return res;
00496
00497 jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
00498 *id = inDefault;
00499 return noErr;
00500 }
00501
00502 OSStatus JackCoreAudioAdapter::GetDefaultOutputDevice(AudioDeviceID* id)
00503 {
00504 OSStatus res;
00505 UInt32 theSize = sizeof(UInt32);
00506 AudioDeviceID outDefault;
00507
00508 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr)
00509 return res;
00510
00511 jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
00512 *id = outDefault;
00513 return noErr;
00514 }
00515
00516 OSStatus JackCoreAudioAdapter::GetDeviceNameFromID(AudioDeviceID id, char* name)
00517 {
00518 UInt32 size = 256;
00519 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00520 }
00521
00522
00523 int JackCoreAudioAdapter::SetupDevices(const char* capture_driver_uid,
00524 const char* playback_driver_uid,
00525 char* capture_driver_name,
00526 char* playback_driver_name)
00527 {
00528 capture_driver_name[0] = 0;
00529 playback_driver_name[0] = 0;
00530
00531
00532 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00533 jack_log("JackCoreAudioAdapter::Open duplex");
00534 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00535 if (GetDefaultDevice(&fDeviceID) != noErr) {
00536 jack_error("Cannot open default device");
00537 return -1;
00538 }
00539 }
00540 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00541 jack_error("Cannot get device name from device ID");
00542 return -1;
00543 }
00544
00545
00546 } else if (strcmp(capture_driver_uid, "") != 0) {
00547 jack_log("JackCoreAudioAdapter::Open capture only");
00548 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00549 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00550 jack_error("Cannot open default device");
00551 return -1;
00552 }
00553 }
00554 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00555 jack_error("Cannot get device name from device ID");
00556 return -1;
00557 }
00558
00559
00560 } else if (strcmp(playback_driver_uid, "") != 0) {
00561 jack_log("JackCoreAudioAdapter::Open playback only");
00562 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00563 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00564 jack_error("Cannot open default device");
00565 return -1;
00566 }
00567 }
00568 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00569 jack_error("Cannot get device name from device ID");
00570 return -1;
00571 }
00572
00573
00574 } else {
00575 jack_log("JackCoreAudioAdapter::Open default driver");
00576 if (GetDefaultDevice(&fDeviceID) != noErr) {
00577 jack_error("Cannot open default device");
00578 return -1;
00579 }
00580 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00581 jack_error("Cannot get device name from device ID");
00582 return -1;
00583 }
00584 }
00585
00586 return 0;
00587 }
00588
00589 int JackCoreAudioAdapter::SetupChannels(bool capturing,
00590 bool playing,
00591 int& inchannels,
00592 int& outchannels,
00593 int& in_nChannels,
00594 int& out_nChannels,
00595 bool strict)
00596 {
00597 OSStatus err = noErr;
00598
00599 if (capturing) {
00600 err = GetTotalChannels(fDeviceID, in_nChannels, true);
00601 if (err != noErr) {
00602 jack_error("Cannot get input channel number");
00603 printError(err);
00604 return -1;
00605 } else {
00606 jack_log("Max input channels : %d", in_nChannels);
00607 }
00608 }
00609
00610 if (playing) {
00611 err = GetTotalChannels(fDeviceID, out_nChannels, false);
00612 if (err != noErr) {
00613 jack_error("Cannot get output channel number");
00614 printError(err);
00615 return -1;
00616 } else {
00617 jack_log("Max output channels : %d", out_nChannels);
00618 }
00619 }
00620
00621 if (inchannels > in_nChannels) {
00622 jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00623 if (strict)
00624 return -1;
00625 }
00626
00627 if (outchannels > out_nChannels) {
00628 jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00629 if (strict)
00630 return -1;
00631 }
00632
00633 if (inchannels == 0) {
00634 jack_log("Setup max in channels = %ld", in_nChannels);
00635 inchannels = in_nChannels;
00636 }
00637
00638 if (outchannels == 0) {
00639 jack_log("Setup max out channels = %ld", out_nChannels);
00640 outchannels = out_nChannels;
00641 }
00642
00643 return 0;
00644 }
00645
00646 int JackCoreAudioAdapter::SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate)
00647 {
00648 OSStatus err = noErr;
00649 UInt32 outSize;
00650 Float64 sampleRate;
00651
00652
00653 outSize = sizeof(UInt32);
00654 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &nframes);
00655 if (err != noErr) {
00656 jack_error("Cannot set buffer size %ld", nframes);
00657 printError(err);
00658 return -1;
00659 }
00660
00661
00662 outSize = sizeof(Float64);
00663 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
00664 if (err != noErr) {
00665 jack_error("Cannot get current sample rate");
00666 printError(err);
00667 return -1;
00668 }
00669
00670
00671 if (samplerate != (jack_nframes_t)sampleRate) {
00672 sampleRate = (Float64)samplerate;
00673
00674
00675 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
00676 if (err != noErr) {
00677 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
00678 printError(err);
00679 return -1;
00680 }
00681 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
00682 if (err != noErr) {
00683 jack_error("Cannot set sample rate = %ld", samplerate);
00684 printError(err);
00685 return -1;
00686 }
00687
00688
00689 int count = 0;
00690 while (!fState && count++ < 100) {
00691 usleep(100000);
00692 jack_log("Wait count = %ld", count);
00693 }
00694
00695
00696 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
00697 }
00698
00699 return 0;
00700 }
00701
00702 int JackCoreAudioAdapter::SetupBuffers(int inchannels)
00703 {
00704 jack_log("JackCoreAudioAdapter::SetupBuffers: input = %ld", inchannels);
00705
00706
00707 fInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00708 if (fInputData == 0) {
00709 jack_error("Cannot allocate memory for input buffers");
00710 return -1;
00711 }
00712 fInputData->mNumberBuffers = inchannels;
00713 for (int i = 0; i < fCaptureChannels; i++) {
00714 fInputData->mBuffers[i].mNumberChannels = 1;
00715 fInputData->mBuffers[i].mDataByteSize = fAdaptedBufferSize * sizeof(float);
00716 fInputData->mBuffers[i].mData = malloc(fAdaptedBufferSize * sizeof(float));
00717 }
00718 return 0;
00719 }
00720
00721 void JackCoreAudioAdapter::DisposeBuffers()
00722 {
00723 if (fInputData) {
00724 for (int i = 0; i < fCaptureChannels; i++)
00725 free(fInputData->mBuffers[i].mData);
00726 free(fInputData);
00727 fInputData = 0;
00728 }
00729 }
00730
00731 int JackCoreAudioAdapter::OpenAUHAL(bool capturing,
00732 bool playing,
00733 int inchannels,
00734 int outchannels,
00735 int in_nChannels,
00736 int out_nChannels,
00737 jack_nframes_t buffer_size,
00738 jack_nframes_t samplerate,
00739 bool strict)
00740 {
00741 ComponentResult err1;
00742 UInt32 enableIO;
00743 AudioStreamBasicDescription srcFormat, dstFormat;
00744
00745 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);
00746
00747 if (inchannels == 0 && outchannels == 0) {
00748 jack_error("No input and output channels...");
00749 return -1;
00750 }
00751
00752
00753 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00754 Component HALOutput = FindNextComponent(NULL, &cd);
00755
00756 err1 = OpenAComponent(HALOutput, &fAUHAL);
00757 if (err1 != noErr) {
00758 jack_error("Error calling OpenAComponent");
00759 printError(err1);
00760 return -1;
00761 }
00762
00763 err1 = AudioUnitInitialize(fAUHAL);
00764 if (err1 != noErr) {
00765 jack_error("Cannot initialize AUHAL unit");
00766 printError(err1);
00767 return -1;
00768 }
00769
00770
00771 if (capturing && inchannels > 0) {
00772 enableIO = 1;
00773 jack_log("Setup AUHAL input on");
00774 } else {
00775 enableIO = 0;
00776 jack_log("Setup AUHAL input off");
00777 }
00778
00779 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00780 if (err1 != noErr) {
00781 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00782 printError(err1);
00783 if (strict)
00784 return -1;
00785 }
00786
00787 if (playing && outchannels > 0) {
00788 enableIO = 1;
00789 jack_log("Setup AUHAL output on");
00790 } else {
00791 enableIO = 0;
00792 jack_log("Setup AUHAL output off");
00793 }
00794
00795 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00796 if (err1 != noErr) {
00797 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00798 printError(err1);
00799 if (strict)
00800 return -1;
00801 }
00802
00803 AudioDeviceID currAudioDeviceID;
00804 UInt32 size = sizeof(AudioDeviceID);
00805 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00806 if (err1 != noErr) {
00807 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00808 printError(err1);
00809 if (strict)
00810 return -1;
00811 } else {
00812 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00813 }
00814
00815
00816 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00817 if (err1 != noErr) {
00818 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00819 printError(err1);
00820 if (strict)
00821 return -1;
00822 }
00823
00824 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
00825 if (err1 != noErr) {
00826 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
00827 printError(err1);
00828 if (strict)
00829 return -1;
00830 } else {
00831 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
00832 }
00833
00834
00835 if (capturing && inchannels > 0) {
00836 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
00837 if (err1 != noErr) {
00838 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00839 printError(err1);
00840 if (strict)
00841 return -1;
00842 }
00843 }
00844
00845 if (playing && outchannels > 0) {
00846 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
00847 if (err1 != noErr) {
00848 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00849 printError(err1);
00850 if (strict)
00851 return -1;
00852 }
00853 }
00854
00855
00856 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00857 SInt32 chanArr[in_nChannels];
00858 for (int i = 0; i < in_nChannels; i++) {
00859 chanArr[i] = -1;
00860 }
00861 for (int i = 0; i < inchannels; i++) {
00862 chanArr[i] = i;
00863 }
00864 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00865 if (err1 != noErr) {
00866 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00867 printError(err1);
00868 }
00869 }
00870
00871 if (playing && outchannels > 0 && outchannels < out_nChannels) {
00872 SInt32 chanArr[out_nChannels];
00873 for (int i = 0; i < out_nChannels; i++) {
00874 chanArr[i] = -1;
00875 }
00876 for (int i = 0; i < outchannels; i++) {
00877 chanArr[i] = i;
00878 }
00879 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00880 if (err1 != noErr) {
00881 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00882 printError(err1);
00883 }
00884 }
00885
00886
00887 jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
00888 srcFormat.mSampleRate = samplerate;
00889 srcFormat.mFormatID = kAudioFormatLinearPCM;
00890 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00891 srcFormat.mBytesPerPacket = sizeof(float);
00892 srcFormat.mFramesPerPacket = 1;
00893 srcFormat.mBytesPerFrame = sizeof(float);
00894 srcFormat.mChannelsPerFrame = outchannels;
00895 srcFormat.mBitsPerChannel = 32;
00896
00897 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
00898 if (err1 != noErr) {
00899 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00900 printError(err1);
00901 }
00902
00903 jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
00904 dstFormat.mSampleRate = samplerate;
00905 dstFormat.mFormatID = kAudioFormatLinearPCM;
00906 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00907 dstFormat.mBytesPerPacket = sizeof(float);
00908 dstFormat.mFramesPerPacket = 1;
00909 dstFormat.mBytesPerFrame = sizeof(float);
00910 dstFormat.mChannelsPerFrame = inchannels;
00911 dstFormat.mBitsPerChannel = 32;
00912
00913 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
00914 if (err1 != noErr) {
00915 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00916 printError(err1);
00917 }
00918
00919
00920 if (inchannels > 0 && outchannels == 0) {
00921 AURenderCallbackStruct output;
00922 output.inputProc = Render;
00923 output.inputProcRefCon = this;
00924 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00925 if (err1 != noErr) {
00926 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
00927 printError(err1);
00928 return -1;
00929 }
00930 } else {
00931 AURenderCallbackStruct output;
00932 output.inputProc = Render;
00933 output.inputProcRefCon = this;
00934 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
00935 if (err1 != noErr) {
00936 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
00937 printError(err1);
00938 return -1;
00939 }
00940 }
00941
00942 return 0;
00943 }
00944
00945 void JackCoreAudioAdapter::CloseAUHAL()
00946 {
00947 AudioUnitUninitialize(fAUHAL);
00948 CloseComponent(fAUHAL);
00949 }
00950
00951 int JackCoreAudioAdapter::Open()
00952 {
00953 return (AudioOutputUnitStart(fAUHAL) != noErr) ? -1 : 0;
00954 }
00955
00956 int JackCoreAudioAdapter::Close()
00957 {
00958 #ifdef JACK_MONITOR
00959 fTable.Save();
00960 #endif
00961 AudioOutputUnitStop(fAUHAL);
00962 DisposeBuffers();
00963 CloseAUHAL();
00964 RemoveListeners();
00965 return 0;
00966 }
00967
00968 int JackCoreAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) {
00969 JackAudioAdapterInterface::SetHostSampleRate ( sample_rate );
00970 Close();
00971 return Open();
00972 }
00973
00974 int JackCoreAudioAdapter::SetBufferSize ( jack_nframes_t buffer_size ) {
00975 JackAudioAdapterInterface::SetHostBufferSize ( buffer_size );
00976 Close();
00977 return Open();
00978 }
00979
00980 }
00981
00982 #ifdef __cplusplus
00983 extern "C"
00984 {
00985 #endif
00986
00987 SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
00988 {
00989 jack_driver_desc_t *desc;
00990 unsigned int i;
00991 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00992
00993 strcpy(desc->name, "audioadapter");
00994 strcpy(desc->desc, "netjack audio <==> net backend adapter");
00995
00996 desc->nparams = 10;
00997 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00998
00999 i = 0;
01000 strcpy(desc->params[i].name, "channels");
01001 desc->params[i].character = 'c';
01002 desc->params[i].type = JackDriverParamInt;
01003 desc->params[i].value.ui = 0;
01004 strcpy(desc->params[i].short_desc, "Maximum number of channels");
01005 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01006
01007 i++;
01008 strcpy(desc->params[i].name, "inchannels");
01009 desc->params[i].character = 'i';
01010 desc->params[i].type = JackDriverParamInt;
01011 desc->params[i].value.ui = 0;
01012 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01013 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01014
01015 i++;
01016 strcpy(desc->params[i].name, "outchannels");
01017 desc->params[i].character = 'o';
01018 desc->params[i].type = JackDriverParamInt;
01019 desc->params[i].value.ui = 0;
01020 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01021 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01022
01023 i++;
01024 strcpy(desc->params[i].name, "capture");
01025 desc->params[i].character = 'C';
01026 desc->params[i].type = JackDriverParamString;
01027 strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
01028 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
01029 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01030
01031 i++;
01032 strcpy(desc->params[i].name, "playback");
01033 desc->params[i].character = 'P';
01034 desc->params[i].type = JackDriverParamString;
01035 strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
01036 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
01037 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01038
01039 i++;
01040 strcpy(desc->params[i].name, "rate");
01041 desc->params[i].character = 'r';
01042 desc->params[i].type = JackDriverParamUInt;
01043 desc->params[i].value.ui = 44100U;
01044 strcpy(desc->params[i].short_desc, "Sample rate");
01045 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01046
01047 i++;
01048 strcpy(desc->params[i].name, "periodsize");
01049 desc->params[i].character = 'p';
01050 desc->params[i].type = JackDriverParamUInt;
01051 desc->params[i].value.ui = 512U;
01052 strcpy(desc->params[i].short_desc, "Period size");
01053 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01054
01055 i++;
01056 strcpy(desc->params[i].name, "duplex");
01057 desc->params[i].character = 'D';
01058 desc->params[i].type = JackDriverParamBool;
01059 desc->params[i].value.i = TRUE;
01060 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01061 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01062
01063 i++;
01064 strcpy(desc->params[i].name, "device");
01065 desc->params[i].character = 'd';
01066 desc->params[i].type = JackDriverParamString;
01067 strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
01068 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01069 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01070
01071 i++;
01072 strcpy(desc->params[i].name, "list-devices");
01073 desc->params[i].character = 'l';
01074 desc->params[i].type = JackDriverParamBool;
01075 desc->params[i].value.i = TRUE;
01076 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01077 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01078
01079 return desc;
01080 }
01081
01082
01083 #ifdef __cplusplus
01084 }
01085 #endif
01086