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