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