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