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 "driver_interface.h"
00029 #include <iostream>
00030
00031 namespace Jack
00032 {
00033
00034 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
00035 {
00036 JackLog("- - - - - - - - - - - - - - - - - - - -\n");
00037 JackLog(" Sample Rate:%f\n", inDesc->mSampleRate);
00038 JackLog(" Format ID:%.*s\n", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
00039 JackLog(" Format Flags:%lX\n", inDesc->mFormatFlags);
00040 JackLog(" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
00041 JackLog(" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
00042 JackLog(" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
00043 JackLog(" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
00044 JackLog(" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
00045 JackLog("- - - - - - - - - - - - - - - - - - - -\n");
00046 }
00047
00048 static void printError(OSStatus err)
00049 {
00050 switch (err) {
00051 case kAudioHardwareNoError:
00052 JackLog("error code : kAudioHardwareNoError\n");
00053 break;
00054 case kAudioConverterErr_FormatNotSupported:
00055 JackLog("error code : kAudioConverterErr_FormatNotSupported\n");
00056 break;
00057 case kAudioConverterErr_OperationNotSupported:
00058 JackLog("error code : kAudioConverterErr_OperationNotSupported\n");
00059 break;
00060 case kAudioConverterErr_PropertyNotSupported:
00061 JackLog("error code : kAudioConverterErr_PropertyNotSupported\n");
00062 break;
00063 case kAudioConverterErr_InvalidInputSize:
00064 JackLog("error code : kAudioConverterErr_InvalidInputSize\n");
00065 break;
00066 case kAudioConverterErr_InvalidOutputSize:
00067 JackLog("error code : kAudioConverterErr_InvalidOutputSize\n");
00068 break;
00069 case kAudioConverterErr_UnspecifiedError:
00070 JackLog("error code : kAudioConverterErr_UnspecifiedError\n");
00071 break;
00072 case kAudioConverterErr_BadPropertySizeError:
00073 JackLog("error code : kAudioConverterErr_BadPropertySizeError\n");
00074 break;
00075 case kAudioConverterErr_RequiresPacketDescriptionsError:
00076 JackLog("error code : kAudioConverterErr_RequiresPacketDescriptionsError\n");
00077 break;
00078 case kAudioConverterErr_InputSampleRateOutOfRange:
00079 JackLog("error code : kAudioConverterErr_InputSampleRateOutOfRange\n");
00080 break;
00081 case kAudioConverterErr_OutputSampleRateOutOfRange:
00082 JackLog("error code : kAudioConverterErr_OutputSampleRateOutOfRange\n");
00083 break;
00084 case kAudioHardwareNotRunningError:
00085 JackLog("error code : kAudioHardwareNotRunningError\n");
00086 break;
00087 case kAudioHardwareUnknownPropertyError:
00088 JackLog("error code : kAudioHardwareUnknownPropertyError\n");
00089 break;
00090 case kAudioHardwareIllegalOperationError:
00091 JackLog("error code : kAudioHardwareIllegalOperationError\n");
00092 break;
00093 case kAudioHardwareBadDeviceError:
00094 JackLog("error code : kAudioHardwareBadDeviceError\n");
00095 break;
00096 case kAudioHardwareBadStreamError:
00097 JackLog("error code : kAudioHardwareBadStreamError\n");
00098 break;
00099 case kAudioDeviceUnsupportedFormatError:
00100 JackLog("error code : kAudioDeviceUnsupportedFormatError\n");
00101 break;
00102 case kAudioDevicePermissionsError:
00103 JackLog("error code : kAudioDevicePermissionsError\n");
00104 break;
00105 default:
00106 JackLog("error code : unknown\n");
00107 break;
00108 }
00109 }
00110
00111 static OSStatus DisplayDeviceNames()
00112 {
00113 UInt32 size;
00114 Boolean isWritable;
00115 int i, deviceNum;
00116 OSStatus err;
00117 CFStringRef UIname;
00118
00119 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00120 if (err != noErr)
00121 return err;
00122
00123 deviceNum = size / sizeof(AudioDeviceID);
00124 AudioDeviceID devices[deviceNum];
00125
00126 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00127 if (err != noErr)
00128 return err;
00129
00130 for (i = 0; i < deviceNum; i++) {
00131 char device_name[256];
00132 char internal_name[256];
00133
00134 size = sizeof(CFStringRef);
00135 UIname = NULL;
00136 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00137 if (err == noErr) {
00138 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00139 } else {
00140 goto error;
00141 }
00142
00143 size = 256;
00144 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00145 if (err != noErr)
00146 return err;
00147
00148 printf("Device name = \'%s\', internal_name = \'%s\' (to be used as -C, -P, or -d parameter)\n", device_name, internal_name);
00149 }
00150
00151 return noErr;
00152
00153 error:
00154 if (UIname != NULL)
00155 CFRelease(UIname);
00156 return err;
00157 }
00158
00159 #if IO_CPU
00160
00161 OSStatus JackCoreAudioDriver::Render(void *inRefCon,
00162 AudioUnitRenderActionFlags *ioActionFlags,
00163 const AudioTimeStamp *inTimeStamp,
00164 UInt32 inBusNumber,
00165 UInt32 inNumberFrames,
00166 AudioBufferList *ioData)
00167 {
00168 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
00169 driver->fLastWaitUst = GetMicroSeconds();
00170 memcpy(&driver->fActionFags, ioActionFlags, sizeof(AudioUnitRenderActionFlags));
00171 memcpy(&driver->fCurrentTime, inTimeStamp, sizeof(AudioTimeStamp));
00172 driver->fDriverOutputData = ioData;
00173 float delta;
00174 OSStatus res = driver->Process();
00175 if ((delta = float(GetMicroSeconds() - driver->fLastWaitUst) / float(driver->fEngineControl->fPeriodUsecs)) > 0.1) {
00176 JackLog("IO CPU %f\n", delta);
00177 }
00178 return res;
00179 }
00180
00181 #else
00182
00183 OSStatus JackCoreAudioDriver::Render(void *inRefCon,
00184 AudioUnitRenderActionFlags *ioActionFlags,
00185 const AudioTimeStamp *inTimeStamp,
00186 UInt32 inBusNumber,
00187 UInt32 inNumberFrames,
00188 AudioBufferList *ioData)
00189 {
00190 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
00191 driver->fLastWaitUst = GetMicroSeconds();
00192 memcpy(&driver->fActionFags, ioActionFlags, sizeof(AudioUnitRenderActionFlags));
00193 memcpy(&driver->fCurrentTime, inTimeStamp, sizeof(AudioTimeStamp));
00194 driver->fDriverOutputData = ioData;
00195 return driver->Process();
00196 }
00197
00198 #endif
00199
00200 int JackCoreAudioDriver::Read()
00201 {
00202 AudioUnitRender(fAUHAL, &fActionFags, &fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData);
00203 return 0;
00204 }
00205
00206 int JackCoreAudioDriver::Write()
00207 {
00208 for (int i = 0; i < fPlaybackChannels; i++) {
00209 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00210 float* buffer = GetOutputBuffer(i);
00211 int size = sizeof(float) * fEngineControl->fBufferSize;
00212 memcpy((float*)fDriverOutputData->mBuffers[i].mData, buffer, size);
00213
00214 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0)
00215 memcpy(GetMonitorBuffer(i), buffer, size);
00216 } else {
00217 memset((float*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(float) * fEngineControl->fBufferSize);
00218 }
00219 }
00220 return 0;
00221 }
00222
00223
00224 OSStatus JackCoreAudioDriver::MeasureCallback(AudioDeviceID inDevice,
00225 const AudioTimeStamp* inNow,
00226 const AudioBufferList* inInputData,
00227 const AudioTimeStamp* inInputTime,
00228 AudioBufferList* outOutputData,
00229 const AudioTimeStamp* inOutputTime,
00230 void* inClientData)
00231 {
00232 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00233 AudioDeviceStop(driver->fDeviceID, MeasureCallback);
00234 AudioDeviceRemoveIOProc(driver->fDeviceID, MeasureCallback);
00235 JackLog("JackCoreAudioDriver::MeasureCallback called\n");
00236 JackMachThread::GetParams(&driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
00237 return noErr;
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 if (inPropertyID == kAudioDeviceProcessorOverload) {
00248 JackLog("JackCoreAudioDriver::NotificationCallback kAudioDeviceProcessorOverload\n");
00249 #ifdef DEBUG
00250
00251 #endif
00252
00253 driver->NotifyXRun(GetMicroSeconds());
00254 }
00255 return noErr;
00256 }
00257
00258 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00259 {
00260 UInt32 size = sizeof(AudioValueTranslation);
00261 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00262 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00263
00264 if (inIUD == NULL) {
00265 return kAudioHardwareUnspecifiedError;
00266 } else {
00267 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00268 CFRelease(inIUD);
00269 JackLog("get_device_id_from_uid %s %ld \n", UID, *id);
00270 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00271 }
00272 }
00273
00274 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
00275 {
00276 OSStatus res;
00277 UInt32 theSize = sizeof(UInt32);
00278 AudioDeviceID inDefault;
00279 AudioDeviceID outDefault;
00280
00281 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
00282 &theSize, &inDefault)) != noErr)
00283 return res;
00284
00285 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
00286 &theSize, &outDefault)) != noErr)
00287 return res;
00288
00289 JackLog("GetDefaultDevice: input = %ld output = %ld\n", inDefault, outDefault);
00290
00291
00292 if (inDefault == outDefault) {
00293 *id = inDefault;
00294 return noErr;
00295 } else {
00296 jack_error("Default input and output devices are not the same !!");
00297 return kAudioHardwareBadDeviceError;
00298 }
00299 }
00300
00301 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
00302 {
00303 OSStatus res;
00304 UInt32 theSize = sizeof(UInt32);
00305 AudioDeviceID inDefault;
00306
00307 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice,
00308 &theSize, &inDefault)) != noErr)
00309 return res;
00310
00311 JackLog("GetDefaultInputDevice: input = %ld \n", inDefault);
00312 *id = inDefault;
00313 return noErr;
00314 }
00315
00316 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
00317 {
00318 OSStatus res;
00319 UInt32 theSize = sizeof(UInt32);
00320 AudioDeviceID outDefault;
00321
00322 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice,
00323 &theSize, &outDefault)) != noErr)
00324 return res;
00325
00326 JackLog("GetDefaultOutputDevice: output = %ld\n", outDefault);
00327 *id = outDefault;
00328 return noErr;
00329 }
00330
00331 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
00332 {
00333 UInt32 size = 256;
00334 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00335 }
00336
00337 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, long* channelCount, bool isInput)
00338 {
00339 OSStatus err = noErr;
00340 UInt32 outSize;
00341 Boolean outWritable;
00342 AudioBufferList* bufferList = 0;
00343 AudioStreamID* streamList = 0;
00344 int i, numStream;
00345
00346 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, &outWritable);
00347 if (err == noErr) {
00348 streamList = (AudioStreamID*)malloc(outSize);
00349 numStream = outSize / sizeof(AudioStreamID);
00350 JackLog("GetTotalChannels device stream number = %ld numStream = %ld\n", device, numStream);
00351 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize, streamList);
00352 if (err == noErr) {
00353 AudioStreamBasicDescription streamDesc;
00354 outSize = sizeof(AudioStreamBasicDescription);
00355 for (i = 0; i < numStream; i++) {
00356 err = AudioStreamGetProperty(streamList[i], 0, kAudioDevicePropertyStreamFormat, &outSize, &streamDesc);
00357 JackLog("GetTotalChannels streamDesc mFormatFlags = %ld mChannelsPerFrame = %ld\n", streamDesc.mFormatFlags, streamDesc.mChannelsPerFrame);
00358 }
00359 }
00360 }
00361
00362 *channelCount = 0;
00363 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00364 if (err == noErr) {
00365 bufferList = (AudioBufferList*)malloc(outSize);
00366 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00367 if (err == noErr) {
00368 for (i = 0; i < bufferList->mNumberBuffers; i++)
00369 *channelCount += bufferList->mBuffers[i].mNumberChannels;
00370 }
00371 }
00372
00373 if (streamList)
00374 free(streamList);
00375 if (bufferList)
00376 free(bufferList);
00377
00378 return err;
00379 }
00380
00381 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, JackEngine* engine, JackSynchro** table)
00382 : JackAudioDriver(name, engine, table), fJackInputData(NULL), fDriverOutputData(NULL)
00383 {
00384 #ifdef DEBUG
00385
00386 #endif
00387 }
00388
00389 JackCoreAudioDriver::~JackCoreAudioDriver()
00390 {
00391 #ifdef DEBUG
00392
00393 #endif
00394 }
00395
00396 int JackCoreAudioDriver::Open(jack_nframes_t nframes,
00397 jack_nframes_t samplerate,
00398 int capturing,
00399 int playing,
00400 int inchannels,
00401 int outchannels,
00402 bool monitor,
00403 const char* capture_driver_uid,
00404 const char* playback_driver_uid,
00405 jack_nframes_t capture_latency,
00406 jack_nframes_t playback_latency)
00407 {
00408 OSStatus err = noErr;
00409 ComponentResult err1;
00410 UInt32 outSize;
00411 UInt32 enableIO;
00412 AudioStreamBasicDescription srcFormat, dstFormat, sampleRate;
00413 long in_nChannels = 0;
00414 long out_nChannels = 0;
00415 char capture_driver_name[256];
00416 char playback_driver_name[256];
00417 float iousage;
00418
00419 capture_driver_name[0] = 0;
00420 playback_driver_name[0] = 0;
00421
00422 JackLog("JackCoreAudioDriver::Open nframes = %ld in = %ld out = %ld capture name = %s playback name = %s\n",
00423 nframes, inchannels, outchannels, capture_driver_uid, playback_driver_uid);
00424
00425
00426 if (capture_driver_uid != NULL && playback_driver_uid != NULL) {
00427 JackLog("JackCoreAudioDriver::Open duplex \n");
00428 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00429 if (GetDefaultDevice(&fDeviceID) != noErr) {
00430 jack_error("Cannot open default device");
00431 return -1;
00432 }
00433 }
00434 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00435 jack_error("Cannot get device name from device ID");
00436 return -1;
00437 }
00438
00439
00440 } else if (capture_driver_uid != NULL) {
00441 JackLog("JackCoreAudioDriver::Open capture only \n");
00442 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00443 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00444 jack_error("Cannot open default device");
00445 return -1;
00446 }
00447 }
00448 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00449 jack_error("Cannot get device name from device ID");
00450 return -1;
00451 }
00452
00453
00454 } else if (playback_driver_uid != NULL) {
00455 JackLog("JackCoreAudioDriver::Open playback only \n");
00456 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00457 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00458 jack_error("Cannot open default device");
00459 return -1;
00460 }
00461 }
00462 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00463 jack_error("Cannot get device name from device ID");
00464 return -1;
00465 }
00466
00467
00468 } else {
00469 JackLog("JackCoreAudioDriver::Open default driver \n");
00470 if (GetDefaultDevice(&fDeviceID) != noErr) {
00471 jack_error("Cannot open default device");
00472 return -1;
00473 }
00474 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00475 jack_error("Cannot get device name from device ID");
00476 return -1;
00477 }
00478 }
00479
00480
00481 if (JackAudioDriver::Open(nframes, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) {
00482 return -1;
00483 }
00484
00485 if (capturing) {
00486 err = GetTotalChannels(fDeviceID, &in_nChannels, true);
00487 if (err != noErr) {
00488 jack_error("Cannot get input channel number");
00489 printError(err);
00490 return -1;
00491 }
00492 }
00493
00494 if (playing) {
00495 err = GetTotalChannels(fDeviceID, &out_nChannels, false);
00496 if (err != noErr) {
00497 jack_error("Cannot get output channel number");
00498 printError(err);
00499 return -1;
00500 }
00501 }
00502
00503 if (inchannels > in_nChannels) {
00504 jack_error("This device hasn't required input channels inchannels = %ld in_nChannels = %ld", inchannels, in_nChannels);
00505 return -1;
00506 }
00507
00508 if (outchannels > out_nChannels) {
00509 jack_error("This device hasn't required output channels outchannels = %ld out_nChannels = %ld", outchannels, out_nChannels);
00510 return -1;
00511 }
00512
00513 if (inchannels == 0) {
00514 JackLog("Setup max in channels = %ld\n", in_nChannels);
00515 inchannels = in_nChannels;
00516 }
00517
00518 if (outchannels == 0) {
00519 JackLog("Setup max out channels = %ld\n", out_nChannels);
00520 outchannels = out_nChannels;
00521 }
00522
00523
00524 outSize = sizeof(UInt32);
00525 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &fEngineControl->fBufferSize);
00526 if (err != noErr) {
00527 jack_error("Cannot set buffer size %ld", nframes);
00528 printError(err);
00529 return -1;
00530 }
00531
00532
00533 if (capturing && inchannels > 0) {
00534 outSize = sizeof(AudioStreamBasicDescription);
00535 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate);
00536 if (err != noErr) {
00537 jack_error("Cannot get current sample rate");
00538 printError(err);
00539 return -1;
00540 }
00541
00542 if (samplerate != (unsigned long)sampleRate.mSampleRate) {
00543 sampleRate.mSampleRate = (Float64)samplerate;
00544 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, true, kAudioDevicePropertyStreamFormat, outSize, &sampleRate);
00545 if (err != noErr) {
00546 jack_error("Cannot set sample rate = %ld", samplerate);
00547 printError(err);
00548 return -1;
00549 }
00550 }
00551 }
00552
00553 if (playing && outchannels > 0) {
00554 outSize = sizeof(AudioStreamBasicDescription);
00555 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyStreamFormat, &outSize, &sampleRate);
00556 if (err != noErr) {
00557 jack_error("Cannot get current sample rate");
00558 printError(err);
00559 return -1;
00560 }
00561
00562 if (samplerate != (unsigned long)sampleRate.mSampleRate) {
00563 sampleRate.mSampleRate = (Float64)samplerate;
00564 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyStreamFormat, outSize, &sampleRate);
00565 if (err != noErr) {
00566 jack_error("Cannot set sample rate = %ld", samplerate);
00567 printError(err);
00568 return -1;
00569 }
00570 }
00571 }
00572
00573
00574 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
00575 Component HALOutput = FindNextComponent(NULL, &cd);
00576
00577 err1 = OpenAComponent(HALOutput, &fAUHAL);
00578 if (err1 != noErr) {
00579 jack_error("Error calling OpenAComponent");
00580 printError(err1);
00581 goto error;
00582 }
00583
00584 err1 = AudioUnitInitialize(fAUHAL);
00585 if (err1 != noErr) {
00586 jack_error("Cannot initialize AUHAL unit");
00587 printError(err1);
00588 goto error;
00589 }
00590
00591
00592 enableIO = 1;
00593 if (capturing && inchannels > 0) {
00594 JackLog("Setup AUHAL input\n");
00595 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
00596 if (err1 != noErr) {
00597 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
00598 printError(err1);
00599 goto error;
00600 }
00601 }
00602
00603 if (playing && outchannels > 0) {
00604 JackLog("Setup AUHAL output\n");
00605 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
00606 if (err1 != noErr) {
00607 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
00608 printError(err1);
00609 goto error;
00610 }
00611 }
00612
00613
00614 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
00615 if (err1 != noErr) {
00616 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
00617 printError(err1);
00618 goto error;
00619 }
00620
00621
00622 if (capturing && inchannels > 0) {
00623 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*) & nframes, sizeof(UInt32));
00624 if (err1 != noErr) {
00625 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00626 printError(err1);
00627 goto error;
00628 }
00629 }
00630
00631 if (playing && outchannels > 0) {
00632 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*) & nframes, sizeof(UInt32));
00633 if (err1 != noErr) {
00634 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
00635 printError(err1);
00636 goto error;
00637 }
00638 }
00639
00640
00641 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
00642 SInt32 chanArr[in_nChannels];
00643 for (int i = 0; i < in_nChannels; i++) {
00644 chanArr[i] = -1;
00645 }
00646 for (int i = 0; i < inchannels; i++) {
00647 chanArr[i] = i;
00648 }
00649 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
00650 if (err1 != noErr) {
00651 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
00652 printError(err1);
00653 }
00654 }
00655
00656 if (playing && outchannels > 0 && outchannels < out_nChannels) {
00657 SInt32 chanArr[out_nChannels];
00658 for (int i = 0; i < out_nChannels; i++) {
00659 chanArr[i] = -1;
00660 }
00661 for (int i = 0; i < outchannels; i++) {
00662 chanArr[i] = i;
00663 }
00664 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
00665 if (err1 != noErr) {
00666 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
00667 printError(err1);
00668 }
00669 }
00670
00671
00672 if (capturing && inchannels > 0) {
00673 srcFormat.mSampleRate = samplerate;
00674 srcFormat.mFormatID = kAudioFormatLinearPCM;
00675 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00676 srcFormat.mBytesPerPacket = sizeof(float);
00677 srcFormat.mFramesPerPacket = 1;
00678 srcFormat.mBytesPerFrame = sizeof(float);
00679 srcFormat.mChannelsPerFrame = outchannels;
00680 srcFormat.mBitsPerChannel = 32;
00681
00682 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &srcFormat, sizeof(AudioStreamBasicDescription));
00683 if (err1 != noErr) {
00684 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
00685 printError(err1);
00686 }
00687 }
00688
00689 if (playing && outchannels > 0) {
00690 dstFormat.mSampleRate = samplerate;
00691 dstFormat.mFormatID = kAudioFormatLinearPCM;
00692 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
00693 dstFormat.mBytesPerPacket = sizeof(float);
00694 dstFormat.mFramesPerPacket = 1;
00695 dstFormat.mBytesPerFrame = sizeof(float);
00696 dstFormat.mChannelsPerFrame = inchannels;
00697 dstFormat.mBitsPerChannel = 32;
00698
00699 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &dstFormat, sizeof(AudioStreamBasicDescription));
00700 if (err1 != noErr) {
00701 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
00702 printError(err1);
00703 }
00704 }
00705
00706
00707 if (inchannels > 0 && outchannels == 0) {
00708 AURenderCallbackStruct output;
00709 output.inputProc = Render;
00710 output.inputProcRefCon = this;
00711 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
00712 if (err1 != noErr) {
00713 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
00714 printError(err1);
00715 goto error;
00716 }
00717 } else {
00718 AURenderCallbackStruct output;
00719 output.inputProc = Render;
00720 output.inputProcRefCon = this;
00721 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
00722 if (err1 != noErr) {
00723 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
00724 printError(err1);
00725 goto error;
00726 }
00727 }
00728
00729
00730 if (capturing && inchannels > 0) {
00731 fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
00732 if (fJackInputData == 0) {
00733 jack_error("Cannot allocate memory for input buffers");
00734 goto error;
00735 }
00736 fJackInputData->mNumberBuffers = inchannels;
00737 for (int i = 0; i < fCaptureChannels; i++) {
00738 fJackInputData->mBuffers[i].mNumberChannels = 1;
00739 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
00740 }
00741 }
00742
00743
00744 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
00745 if (err != noErr) {
00746 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
00747 printError(err1);
00748 goto error;
00749 }
00750
00751 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
00752 if (err != noErr) {
00753 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
00754 printError(err1);
00755 goto error;
00756 }
00757
00758 fDriverOutputData = 0;
00759
00760 #if IO_CPU
00761
00762 outSize = sizeof(float);
00763 iousage = 0.4f;
00764 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &iousage);
00765 if (err != noErr) {
00766 jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
00767 printError(err);
00768 }
00769 #endif
00770
00771
00772 fCaptureChannels = inchannels;
00773 fPlaybackChannels = outchannels;
00774 return 0;
00775
00776 error:
00777 AudioUnitUninitialize(fAUHAL);
00778 CloseComponent(fAUHAL);
00779 return -1;
00780 }
00781
00782 int JackCoreAudioDriver::Close()
00783 {
00784 JackAudioDriver::Close();
00785
00786 AudioDeviceStop(fDeviceID, MeasureCallback);
00787 AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback);
00788 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
00789 free(fJackInputData);
00790 AudioUnitUninitialize(fAUHAL);
00791 CloseComponent(fAUHAL);
00792 return 0;
00793 }
00794
00795 int JackCoreAudioDriver::Attach()
00796 {
00797 OSStatus err;
00798 JackPort* port;
00799 jack_port_id_t port_index;
00800 UInt32 size;
00801 Boolean isWritable;
00802 char channel_name[64];
00803 char buf[JACK_PORT_NAME_SIZE];
00804 unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
00805
00806 JackLog("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld\n", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
00807
00808 for (int i = 0; i < fCaptureChannels; i++) {
00809
00810 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
00811 if (err != noErr)
00812 JackLog("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error \n");
00813 if (err == noErr && size > 0) {
00814 err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
00815 if (err != noErr)
00816 JackLog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
00817 snprintf(buf, sizeof(buf) - 1, "%s:%s:out_%s%u", fClientControl->fName, fCaptureDriverName, channel_name, i + 1);
00818 } else {
00819 snprintf(buf, sizeof(buf) - 1, "%s:%s:out%u", fClientControl->fName, fCaptureDriverName, i + 1);
00820 }
00821
00822 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
00823 jack_error("Cannot register port for %s", buf);
00824 return -1;
00825 }
00826
00827 port = fGraphManager->GetPort(port_index);
00828 port->SetLatency(fEngineControl->fBufferSize + fCaptureLatency);
00829 fCapturePortList[i] = port_index;
00830 }
00831
00832 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
00833
00834 for (int i = 0; i < fPlaybackChannels; i++) {
00835
00836 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
00837 if (err != noErr)
00838 JackLog("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error \n");
00839 if (err == noErr && size > 0) {
00840 err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
00841 if (err != noErr)
00842 JackLog("AudioDeviceGetProperty kAudioDevicePropertyChannelName error \n");
00843 snprintf(buf, sizeof(buf) - 1, "%s:%s:in_%s%u", fClientControl->fName, fPlaybackDriverName, channel_name, i + 1);
00844 } else {
00845 snprintf(buf, sizeof(buf) - 1, "%s:%s:in%u", fClientControl->fName, fPlaybackDriverName, i + 1);
00846 }
00847
00848 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, (JackPortFlags)port_flags)) == NO_PORT) {
00849 jack_error("Cannot register port for %s", buf);
00850 return -1;
00851 }
00852
00853 port = fGraphManager->GetPort(port_index);
00854 port->SetLatency(fEngineControl->fBufferSize + fPlaybackLatency);
00855 fPlaybackPortList[i] = port_index;
00856
00857
00858 if (fWithMonitorPorts) {
00859 JackLog("Create monitor port \n");
00860 snprintf(buf, sizeof(buf) - 1, "%s:%s:monitor_%u", fClientControl->fName, fPlaybackDriverName, i + 1);
00861 if ((port_index = fGraphManager->AllocatePort(fClientControl->fRefNum, buf, JackPortIsOutput)) == NO_PORT) {
00862 jack_error("Cannot register monitor port for %s", buf);
00863 return -1;
00864 } else {
00865 port = fGraphManager->GetPort(port_index);
00866 port->SetLatency(fEngineControl->fBufferSize);
00867 fMonitorPortList[i] = port_index;
00868 }
00869 }
00870 }
00871
00872
00873 for (int i = 0; i < fCaptureChannels; i++) {
00874 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
00875 }
00876
00877 return 0;
00878 }
00879
00880 int JackCoreAudioDriver::Start()
00881 {
00882 OSStatus err;
00883 JackLog("JackCoreAudioDriver::Start\n");
00884 JackAudioDriver::Start();
00885
00886 err = AudioDeviceAddIOProc(fDeviceID, MeasureCallback, this);
00887 if (err != noErr)
00888 return -1;
00889
00890 err = AudioOutputUnitStart(fAUHAL);
00891 if (err != noErr)
00892 return -1;
00893
00894 if ((err = AudioDeviceStart(fDeviceID, MeasureCallback)) != noErr) {
00895 jack_error("Cannot start MeasureCallback");
00896 printError(err);
00897 return -1;
00898 }
00899
00900 return 0;
00901 }
00902
00903 int JackCoreAudioDriver::Stop()
00904 {
00905 AudioDeviceStop(fDeviceID, MeasureCallback);
00906 AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback);
00907 JackLog("JackCoreAudioDriver::Stop\n");
00908 return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
00909 }
00910
00911 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
00912 {
00913 OSStatus err;
00914 UInt32 outSize = sizeof(UInt32);
00915
00916 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
00917 if (err != noErr) {
00918 jack_error("Cannot set buffer size %ld", buffer_size);
00919 printError(err);
00920 return -1;
00921 }
00922
00923 fEngineControl->fBufferSize = buffer_size;
00924 fEngineControl->fPeriodUsecs = jack_time_t(1000000.f / fEngineControl->fSampleRate * fEngineControl->fBufferSize);
00925
00926
00927 for (int i = 0; i < fCaptureChannels; i++) {
00928 fJackInputData->mBuffers[i].mNumberChannels = 1;
00929 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
00930 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
00931 }
00932
00933 return 0;
00934 }
00935
00936 void JackCoreAudioDriver::PrintState()
00937 {
00938 std::cout << "JackCoreAudioDriver state" << std::endl;
00939
00940 jack_port_id_t port_index;
00941
00942 std::cout << "Input ports" << std::endl;
00943
00944 for (int i = 0; i < fPlaybackChannels; i++) {
00945 port_index = fCapturePortList[i];
00946 JackPort* port = fGraphManager->GetPort(port_index);
00947 std::cout << port->GetName() << std::endl;
00948 if (fGraphManager->GetConnectionsNum(port_index)) {}
00949 }
00950
00951 std::cout << "Output ports" << std::endl;
00952
00953 for (int i = 0; i < fCaptureChannels; i++) {
00954 port_index = fPlaybackPortList[i];
00955 JackPort* port = fGraphManager->GetPort(port_index);
00956 std::cout << port->GetName() << std::endl;
00957 if (fGraphManager->GetConnectionsNum(port_index)) {}
00958 }
00959 }
00960
00961 }
00962
00963
00964 #ifdef __cplusplus
00965 extern "C"
00966 {
00967 #endif
00968
00969 jack_driver_desc_t* driver_get_descriptor() {
00970 jack_driver_desc_t *desc;
00971 unsigned int i;
00972 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
00973
00974 strcpy(desc->name, "coreaudio");
00975 desc->nparams = 13;
00976 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
00977
00978 i = 0;
00979 strcpy(desc->params[i].name, "channels");
00980 desc->params[i].character = 'c';
00981 desc->params[i].type = JackDriverParamInt;
00982 desc->params[i].value.ui = 0;
00983 strcpy(desc->params[i].short_desc, "Maximum number of channels");
00984 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00985
00986 i++;
00987 strcpy(desc->params[i].name, "inchannels");
00988 desc->params[i].character = 'i';
00989 desc->params[i].type = JackDriverParamInt;
00990 desc->params[i].value.ui = 0;
00991 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
00992 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
00993
00994 i++;
00995 strcpy(desc->params[i].name, "outchannels");
00996 desc->params[i].character = 'o';
00997 desc->params[i].type = JackDriverParamInt;
00998 desc->params[i].value.ui = 0;
00999 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01000 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01001
01002 i++;
01003 strcpy(desc->params[i].name, "capture");
01004 desc->params[i].character = 'C';
01005 desc->params[i].type = JackDriverParamString;
01006 strcpy(desc->params[i].value.str, "will take default CoreAudio input device");
01007 strcpy(desc->params[i].short_desc, "Provide capture ports. Optionally set CoreAudio device name");
01008 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01009
01010 i++;
01011 strcpy(desc->params[i].name, "playback");
01012 desc->params[i].character = 'P';
01013 desc->params[i].type = JackDriverParamString;
01014 strcpy(desc->params[i].value.str, "will take default CoreAudio output device");
01015 strcpy(desc->params[i].short_desc, "Provide playback ports. Optionally set CoreAudio device name");
01016 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01017
01018 i++;
01019 strcpy (desc->params[i].name, "monitor");
01020 desc->params[i].character = 'm';
01021 desc->params[i].type = JackDriverParamBool;
01022 desc->params[i].value.i = 0;
01023 strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
01024 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01025
01026 i++;
01027 strcpy(desc->params[i].name, "duplex");
01028 desc->params[i].character = 'D';
01029 desc->params[i].type = JackDriverParamBool;
01030 desc->params[i].value.i = TRUE;
01031 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01032 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01033
01034 i++;
01035 strcpy(desc->params[i].name, "rate");
01036 desc->params[i].character = 'r';
01037 desc->params[i].type = JackDriverParamUInt;
01038 desc->params[i].value.ui = 44100U;
01039 strcpy(desc->params[i].short_desc, "Sample rate");
01040 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01041
01042 i++;
01043 strcpy(desc->params[i].name, "period");
01044 desc->params[i].character = 'p';
01045 desc->params[i].type = JackDriverParamUInt;
01046 desc->params[i].value.ui = 128U;
01047 strcpy(desc->params[i].short_desc, "Frames per period");
01048 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01049
01050 i++;
01051 strcpy(desc->params[i].name, "device");
01052 desc->params[i].character = 'd';
01053 desc->params[i].type = JackDriverParamString;
01054 desc->params[i].value.ui = 128U;
01055 strcpy(desc->params[i].value.str, "will take default CoreAudio device name");
01056 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01057 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01058
01059 i++;
01060 strcpy(desc->params[i].name, "input-latency");
01061 desc->params[i].character = 'I';
01062 desc->params[i].type = JackDriverParamUInt;
01063 desc->params[i].value.i = 0;
01064 strcpy(desc->params[i].short_desc, "Extra input latency");
01065 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01066
01067 i++;
01068 strcpy(desc->params[i].name, "output-latency");
01069 desc->params[i].character = 'O';
01070 desc->params[i].type = JackDriverParamUInt;
01071 desc->params[i].value.i = 0;
01072 strcpy(desc->params[i].short_desc, "Extra output latency");
01073 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01074
01075 i++;
01076 strcpy(desc->params[i].name, "list-devices");
01077 desc->params[i].character = 'l';
01078 desc->params[i].type = JackDriverParamBool;
01079 desc->params[i].value.i = TRUE;
01080 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01081 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01082
01083 return desc;
01084 }
01085
01086 Jack::JackDriverClientInterface* driver_initialize(Jack::JackEngine* engine, Jack::JackSynchro** table, const JSList* params) {
01087 jack_nframes_t srate = 44100;
01088 jack_nframes_t frames_per_interrupt = 128;
01089 int capture = FALSE;
01090 int playback = FALSE;
01091 int chan_in = 0;
01092 int chan_out = 0;
01093 bool monitor = false;
01094 char* capture_pcm_name = "";
01095 char* playback_pcm_name = "";
01096 const JSList *node;
01097 const jack_driver_param_t *param;
01098 jack_nframes_t systemic_input_latency = 0;
01099 jack_nframes_t systemic_output_latency = 0;
01100
01101 for (node = params; node; node = jack_slist_next(node)) {
01102 param = (const jack_driver_param_t *) node->data;
01103
01104 switch (param->character) {
01105
01106 case 'd':
01107 capture_pcm_name = strdup(param->value.str);
01108 playback_pcm_name = strdup(param->value.str);
01109 break;
01110
01111 case 'D':
01112 capture = TRUE;
01113 playback = TRUE;
01114 break;
01115
01116 case 'c':
01117 chan_in = chan_out = (int) param->value.ui;
01118 break;
01119
01120 case 'i':
01121 chan_in = (int) param->value.ui;
01122 break;
01123
01124 case 'o':
01125 chan_out = (int) param->value.ui;
01126 break;
01127
01128 case 'C':
01129 capture = TRUE;
01130 if (strcmp(param->value.str, "none") != 0) {
01131 capture_pcm_name = strdup(param->value.str);
01132 }
01133 break;
01134
01135 case 'P':
01136 playback = TRUE;
01137 if (strcmp(param->value.str, "none") != 0) {
01138 playback_pcm_name = strdup(param->value.str);
01139 }
01140 break;
01141
01142 case 'm':
01143 monitor = param->value.i;
01144 break;
01145
01146 case 'r':
01147 srate = param->value.ui;
01148 break;
01149
01150 case 'p':
01151 frames_per_interrupt = (unsigned int) param->value.ui;
01152 break;
01153
01154 case 'I':
01155 systemic_input_latency = param->value.ui;
01156 break;
01157
01158 case 'O':
01159 systemic_output_latency = param->value.ui;
01160 break;
01161
01162 case 'l':
01163 Jack::DisplayDeviceNames();
01164 break;
01165 }
01166 }
01167
01168
01169 if (!capture && !playback) {
01170 capture = TRUE;
01171 playback = TRUE;
01172 }
01173
01174 Jack::JackDriverClientInterface* driver = new Jack::JackCoreAudioDriver("coreaudio", engine, table);
01175 if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_pcm_name, playback_pcm_name, systemic_input_latency, systemic_output_latency) == 0) {
01176 return driver;
01177 } else {
01178 delete driver;
01179 return NULL;
01180 }
01181 }
01182
01183 #ifdef __cplusplus
01184 }
01185 #endif
01186
01187