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