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 "JackTools.h"
00029 #include "JackCompilerDeps.h"
00030 #include "JackLockedEngine.h"
00031
00032 #include <sstream>
00033 #include <iostream>
00034 #include <CoreServices/CoreServices.h>
00035 #include <CoreFoundation/CFNumber.h>
00036
00037 namespace Jack
00038 {
00039
00040 static void Print4CharCode(const char* msg, long c)
00041 {
00042 UInt32 __4CC_number = (c);
00043 char __4CC_string[5];
00044 *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
00045 __4CC_string[4] = 0;
00046 jack_log("%s'%s'", (msg), __4CC_string);
00047 }
00048
00049 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
00050 {
00051 jack_log("- - - - - - - - - - - - - - - - - - - -");
00052 jack_log(" Sample Rate:%f", inDesc->mSampleRate);
00053 jack_log(" Format ID:%.*s", (int) sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
00054 jack_log(" Format Flags:%lX", inDesc->mFormatFlags);
00055 jack_log(" Bytes per Packet:%ld", inDesc->mBytesPerPacket);
00056 jack_log(" Frames per Packet:%ld", inDesc->mFramesPerPacket);
00057 jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame);
00058 jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame);
00059 jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel);
00060 jack_log("- - - - - - - - - - - - - - - - - - - -");
00061 }
00062
00063 static void printError(OSStatus err)
00064 {
00065 switch (err) {
00066 case kAudioHardwareNoError:
00067 jack_log("error code : kAudioHardwareNoError");
00068 break;
00069 case kAudioConverterErr_FormatNotSupported:
00070 jack_log("error code : kAudioConverterErr_FormatNotSupported");
00071 break;
00072 case kAudioConverterErr_OperationNotSupported:
00073 jack_log("error code : kAudioConverterErr_OperationNotSupported");
00074 break;
00075 case kAudioConverterErr_PropertyNotSupported:
00076 jack_log("error code : kAudioConverterErr_PropertyNotSupported");
00077 break;
00078 case kAudioConverterErr_InvalidInputSize:
00079 jack_log("error code : kAudioConverterErr_InvalidInputSize");
00080 break;
00081 case kAudioConverterErr_InvalidOutputSize:
00082 jack_log("error code : kAudioConverterErr_InvalidOutputSize");
00083 break;
00084 case kAudioConverterErr_UnspecifiedError:
00085 jack_log("error code : kAudioConverterErr_UnspecifiedError");
00086 break;
00087 case kAudioConverterErr_BadPropertySizeError:
00088 jack_log("error code : kAudioConverterErr_BadPropertySizeError");
00089 break;
00090 case kAudioConverterErr_RequiresPacketDescriptionsError:
00091 jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
00092 break;
00093 case kAudioConverterErr_InputSampleRateOutOfRange:
00094 jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
00095 break;
00096 case kAudioConverterErr_OutputSampleRateOutOfRange:
00097 jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
00098 break;
00099 case kAudioHardwareNotRunningError:
00100 jack_log("error code : kAudioHardwareNotRunningError");
00101 break;
00102 case kAudioHardwareUnknownPropertyError:
00103 jack_log("error code : kAudioHardwareUnknownPropertyError");
00104 break;
00105 case kAudioHardwareIllegalOperationError:
00106 jack_log("error code : kAudioHardwareIllegalOperationError");
00107 break;
00108 case kAudioHardwareBadDeviceError:
00109 jack_log("error code : kAudioHardwareBadDeviceError");
00110 break;
00111 case kAudioHardwareBadStreamError:
00112 jack_log("error code : kAudioHardwareBadStreamError");
00113 break;
00114 case kAudioDeviceUnsupportedFormatError:
00115 jack_log("error code : kAudioDeviceUnsupportedFormatError");
00116 break;
00117 case kAudioDevicePermissionsError:
00118 jack_log("error code : kAudioDevicePermissionsError");
00119 break;
00120 case kAudioHardwareBadObjectError:
00121 jack_log("error code : kAudioHardwareBadObjectError");
00122 break;
00123 case kAudioHardwareUnsupportedOperationError:
00124 jack_log("error code : kAudioHardwareUnsupportedOperationError");
00125 break;
00126 default:
00127 Print4CharCode("error code : unknown", err);
00128 break;
00129 }
00130 }
00131
00132 static bool CheckAvailableDeviceName(const char* device_name, AudioDeviceID* device_id)
00133 {
00134 UInt32 size;
00135 Boolean isWritable;
00136 int i, deviceNum;
00137 OSStatus err;
00138
00139 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00140 if (err != noErr) {
00141 return false;
00142 }
00143
00144 deviceNum = size / sizeof(AudioDeviceID);
00145 AudioDeviceID devices[deviceNum];
00146
00147 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00148 if (err != noErr) {
00149 return false;
00150 }
00151
00152 for (i = 0; i < deviceNum; i++) {
00153 char device_name_aux[256];
00154
00155 size = 256;
00156 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
00157 if (err != noErr) {
00158 return false;
00159 }
00160
00161 if (strcmp(device_name_aux, device_name) == 0) {
00162 *device_id = devices[i];
00163 return true;
00164 }
00165
00166 }
00167
00168 return false;
00169 }
00170
00171 static bool CheckAvailableDevice(AudioDeviceID device_id)
00172 {
00173 UInt32 size;
00174 Boolean isWritable;
00175 int i, deviceNum;
00176 OSStatus err;
00177
00178 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00179 if (err != noErr) {
00180 return false;
00181 }
00182
00183 deviceNum = size / sizeof(AudioDeviceID);
00184 AudioDeviceID devices[deviceNum];
00185
00186 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00187 if (err != noErr) {
00188 return false;
00189 }
00190
00191 for (i = 0; i < deviceNum; i++) {
00192 if (device_id == devices[i]) {
00193 return true;
00194 }
00195
00196 }
00197
00198 return false;
00199 }
00200
00201
00202 static OSStatus DisplayDeviceNames()
00203 {
00204 UInt32 size;
00205 Boolean isWritable;
00206 int i, deviceNum;
00207 OSStatus err;
00208 CFStringRef UIname;
00209
00210 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00211 if (err != noErr) {
00212 return err;
00213 }
00214
00215 deviceNum = size / sizeof(AudioDeviceID);
00216 AudioDeviceID devices[deviceNum];
00217
00218 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00219 if (err != noErr) {
00220 return err;
00221 }
00222
00223 for (i = 0; i < deviceNum; i++) {
00224 char device_name[256];
00225 char internal_name[256];
00226
00227 size = sizeof(CFStringRef);
00228 UIname = NULL;
00229 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00230 if (err == noErr) {
00231 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00232 } else {
00233 goto error;
00234 }
00235
00236 size = 256;
00237 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00238 if (err != noErr) {
00239 return err;
00240 }
00241
00242 jack_info("Device ID = \'%d\' name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", devices[i], device_name, internal_name);
00243 }
00244
00245 return noErr;
00246
00247 error:
00248 if (UIname != NULL) {
00249 CFRelease(UIname);
00250 }
00251 return err;
00252 }
00253
00254 static CFStringRef GetDeviceName(AudioDeviceID id)
00255 {
00256 UInt32 size = sizeof(CFStringRef);
00257 CFStringRef UIname;
00258 OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00259 return (err == noErr) ? UIname : NULL;
00260 }
00261
00262 static void ParseChannelList(const string& list, vector<int>& result)
00263 {
00264 stringstream ss(list);
00265 string token;
00266 int chan;
00267
00268 while (ss >> token) {
00269 istringstream ins;
00270 ins.str(token);
00271 ins >> chan;
00272 result.push_back(chan);
00273 }
00274 }
00275
00276 OSStatus JackCoreAudioDriver::Render(void* inRefCon,
00277 AudioUnitRenderActionFlags* ioActionFlags,
00278 const AudioTimeStamp* inTimeStamp,
00279 UInt32 inBusNumber,
00280 UInt32 inNumberFrames,
00281 AudioBufferList* ioData)
00282 {
00283 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inRefCon;
00284 driver->fActionFags = ioActionFlags;
00285 driver->fCurrentTime = inTimeStamp;
00286 driver->fDriverOutputData = ioData;
00287
00288
00289 if (set_threaded_log_function()) {
00290
00291 jack_log("set_threaded_log_function");
00292 JackMachThread::GetParams(pthread_self(), &driver->fEngineControl->fPeriod, &driver->fEngineControl->fComputation, &driver->fEngineControl->fConstraint);
00293
00294 if (driver->fComputationGrain > 0) {
00295 jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(driver->fComputationGrain * 100));
00296 driver->fEngineControl->fComputation = driver->fEngineControl->fPeriod * driver->fComputationGrain;
00297 }
00298 }
00299
00300
00301 driver->fState = true;
00302
00303 driver->CycleTakeBeginTime();
00304
00305 if (driver->Process() < 0) {
00306 jack_error("Process error, stopping driver.");
00307 driver->NotifyFailure(JackBackendError, "Process error, stopping driver.");
00308 driver->Stop();
00309 kill(JackTools::GetPID(), SIGINT);
00310 return kAudioHardwareUnsupportedOperationError;
00311 } else {
00312 return noErr;
00313 }
00314 }
00315
00316 int JackCoreAudioDriver::Read()
00317 {
00318 if (fCaptureChannels > 0) {
00319 return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
00320 } else {
00321 return 0;
00322 }
00323 }
00324
00325 int JackCoreAudioDriver::Write()
00326 {
00327 for (int i = 0; i < fPlaybackChannels; i++) {
00328 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00329 jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
00330 int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
00331 memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
00332
00333 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
00334 memcpy(GetMonitorBuffer(i), buffer, size);
00335 }
00336 } else {
00337 memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize);
00338 }
00339 }
00340 return 0;
00341 }
00342
00343 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
00344 UInt32 inChannel,
00345 Boolean isInput,
00346 AudioDevicePropertyID inPropertyID,
00347 void* inClientData)
00348 {
00349 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00350
00351 switch (inPropertyID) {
00352
00353 case kAudioDevicePropertyNominalSampleRate: {
00354 jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
00355
00356 Float64 tmp_sample_rate;
00357 UInt32 outSize = sizeof(Float64);
00358 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
00359 if (err != noErr) {
00360 jack_error("Cannot get current sample rate");
00361 printError(err);
00362 } else {
00363 jack_log("SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
00364 }
00365 driver->fState = true;
00366 break;
00367 }
00368 }
00369
00370 return noErr;
00371 }
00372
00373 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
00374 UInt32 inChannel,
00375 Boolean isInput,
00376 AudioDevicePropertyID inPropertyID,
00377 void* inClientData)
00378 {
00379 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00380
00381 switch (inPropertyID) {
00382
00383 case kAudioDevicePropertyBufferFrameSize: {
00384 jack_log("JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
00385
00386 UInt32 tmp_buffer_size;
00387 UInt32 outSize = sizeof(UInt32);
00388 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
00389 if (err != noErr) {
00390 jack_error("Cannot get current buffer size");
00391 printError(err);
00392 } else {
00393 jack_log("BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
00394 }
00395 driver->fState = true;
00396 break;
00397 }
00398 }
00399
00400 return noErr;
00401 }
00402
00403
00404 OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID, void* inClientData)
00405 {
00406 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00407
00408 switch (inPropertyID) {
00409
00410 case kAudioHardwarePropertyDevices: {
00411 jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
00412 DisplayDeviceNames();
00413 AudioDeviceID captureID, playbackID;
00414 if (CheckAvailableDevice(driver->fDeviceID) ||
00415 (CheckAvailableDeviceName(driver->fCaptureUID, &captureID)
00416 && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {
00417
00418 }
00419 break;
00420 }
00421
00422 }
00423
00424 return noErr;
00425 }
00426
00427 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
00428 UInt32 inChannel,
00429 Boolean isInput,
00430 AudioDevicePropertyID inPropertyID,
00431 void* inClientData)
00432 {
00433 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00434
00435 switch (inPropertyID) {
00436
00437 case kAudioDevicePropertyDeviceIsRunning: {
00438 UInt32 isrunning = 0;
00439 UInt32 outsize = sizeof(UInt32);
00440 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outsize, &isrunning) == noErr) {
00441 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning = %d", isrunning);
00442 }
00443 break;
00444 }
00445
00446 case kAudioDevicePropertyDeviceIsAlive: {
00447 UInt32 isalive = 0;
00448 UInt32 outsize = sizeof(UInt32);
00449 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
00450 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
00451 }
00452 break;
00453 }
00454
00455 case kAudioDevicePropertyDeviceHasChanged: {
00456 UInt32 hachanged = 0;
00457 UInt32 outsize = sizeof(UInt32);
00458 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
00459 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
00460 }
00461 break;
00462 }
00463
00464 case kAudioDeviceProcessorOverload: {
00465 jack_error("JackCoreAudioDriver::DeviceNotificationCallback kAudioDeviceProcessorOverload");
00466 jack_time_t cur_time = GetMicroSeconds();
00467 driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst));
00468 break;
00469 }
00470
00471 case kAudioDevicePropertyStreamConfiguration: {
00472 jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
00473 driver->NotifyFailure(JackBackendError, "Another application has changed the device configuration.");
00474 driver->CloseAUHAL();
00475 kill(JackTools::GetPID(), SIGINT);
00476 return kAudioHardwareUnsupportedOperationError;
00477 }
00478
00479 case kAudioDevicePropertyNominalSampleRate: {
00480 Float64 sample_rate = 0;
00481 UInt32 outsize = sizeof(Float64);
00482 OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
00483 if (err != noErr) {
00484 return kAudioHardwareUnsupportedOperationError;
00485 }
00486
00487 char device_name[256];
00488 const char* digidesign_name = "Digidesign";
00489 driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
00490
00491 if (sample_rate != driver->fEngineControl->fSampleRate) {
00492
00493
00494 if (strncmp(device_name, digidesign_name, 10) == 0) {
00495
00496 jack_log("Digidesign HW = %s", device_name);
00497
00498
00499 sample_rate = driver->fEngineControl->fSampleRate;
00500 err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
00501 if (err != noErr) {
00502 jack_error("Cannot set sample rate = %f", sample_rate);
00503 printError(err);
00504 } else {
00505 jack_log("Set sample rate = %f", sample_rate);
00506 }
00507
00508
00509 outsize = sizeof(Float64);
00510 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
00511 if (err != noErr) {
00512 jack_error("Cannot get current sample rate");
00513 printError(err);
00514 } else {
00515 jack_log("Checked sample rate = %f", sample_rate);
00516 }
00517 return noErr;
00518
00519 } else {
00520 driver->NotifyFailure(JackBackendError, "Another application has changed the sample rate.");
00521 driver->CloseAUHAL();
00522 kill(JackTools::GetPID(), SIGINT);
00523 return kAudioHardwareUnsupportedOperationError;
00524 }
00525 }
00526 }
00527
00528 }
00529 return noErr;
00530 }
00531
00532 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00533 {
00534 UInt32 size = sizeof(AudioValueTranslation);
00535 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00536 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00537
00538 if (inIUD == NULL) {
00539 return kAudioHardwareUnspecifiedError;
00540 } else {
00541 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00542 CFRelease(inIUD);
00543 jack_log("GetDeviceIDFromUID %s %ld", UID, *id);
00544 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00545 }
00546 }
00547
00548 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
00549 {
00550 OSStatus res;
00551 UInt32 theSize = sizeof(UInt32);
00552 AudioDeviceID inDefault;
00553 AudioDeviceID outDefault;
00554
00555 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
00556 return res;
00557 }
00558
00559 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
00560 return res;
00561 }
00562
00563 jack_log("GetDefaultDevice: input = %ld output = %ld", inDefault, outDefault);
00564
00565
00566 if (inDefault != outDefault) {
00567 jack_error("Default input and output devices are not the same !!");
00568 return kAudioHardwareBadDeviceError;
00569 } else if (inDefault == 0) {
00570 jack_error("Default input and output devices are null !!");
00571 return kAudioHardwareBadDeviceError;
00572 } else {
00573 *id = inDefault;
00574 return noErr;
00575 }
00576 }
00577
00578 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
00579 {
00580 OSStatus res;
00581 UInt32 theSize = sizeof(UInt32);
00582 AudioDeviceID inDefault;
00583
00584 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
00585 return res;
00586 }
00587
00588 if (inDefault == 0) {
00589 jack_error("Error: default input device is 0, please select a correct one !!");
00590 return -1;
00591 }
00592 jack_log("GetDefaultInputDevice: input = %ld ", inDefault);
00593 *id = inDefault;
00594 return noErr;
00595 }
00596
00597 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
00598 {
00599 OSStatus res;
00600 UInt32 theSize = sizeof(UInt32);
00601 AudioDeviceID outDefault;
00602
00603 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
00604 return res;
00605 }
00606
00607 if (outDefault == 0) {
00608 jack_error("Error: default output device is 0, please select a correct one !!");
00609 return -1;
00610 }
00611 jack_log("GetDefaultOutputDevice: output = %ld", outDefault);
00612 *id = outDefault;
00613 return noErr;
00614 }
00615
00616 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
00617 {
00618 UInt32 size = 256;
00619 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00620 }
00621
00622 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
00623 {
00624 OSStatus err = noErr;
00625 UInt32 outSize;
00626 Boolean outWritable;
00627
00628 channelCount = 0;
00629 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00630 if (err == noErr) {
00631 int stream_count = outSize / sizeof(AudioBufferList);
00632 AudioBufferList bufferList[stream_count];
00633 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00634 if (err == noErr) {
00635 for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
00636 channelCount += bufferList->mBuffers[i].mNumberChannels;
00637
00638 }
00639 }
00640 }
00641 return err;
00642 }
00643
00644 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
00645 {
00646 OSStatus err = noErr;
00647 UInt32 outSize1, outSize2, outSize3;
00648 Boolean outWritable;
00649
00650 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
00651 if (err == noErr) {
00652 int stream_count = outSize1 / sizeof(UInt32);
00653 AudioStreamID streamIDs[stream_count];
00654 AudioBufferList bufferList[stream_count];
00655 UInt32 streamLatency;
00656 outSize2 = sizeof(UInt32);
00657
00658 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
00659 if (err != noErr) {
00660 jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
00661 return err;
00662 }
00663
00664 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
00665 if (err != noErr) {
00666 jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
00667 return err;
00668 }
00669
00670 for (int i = 0; i < stream_count; i++) {
00671 err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
00672 if (err != noErr) {
00673 jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
00674 return err;
00675 }
00676 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
00677 if (err != noErr) {
00678 jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
00679 return err;
00680 }
00681
00682 for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
00683 latencies.push_back(streamLatency);
00684 }
00685 }
00686 }
00687 return err;
00688 }
00689
00690 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
00691 : JackAudioDriver(name, alias, engine, table),
00692 fJackInputData(NULL),
00693 fDriverOutputData(NULL),
00694 fPluginID(0),
00695 fState(false),
00696 fHogged(false),
00697 fIOUsage(1.f),
00698 fComputationGrain(-1.f),
00699 fClockDriftCompensate(false)
00700 {}
00701
00702 JackCoreAudioDriver::~JackCoreAudioDriver()
00703 {}
00704
00705 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
00706 {
00707 OSStatus osErr = noErr;
00708 AudioObjectPropertyAddress pluginAOPA;
00709 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
00710 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00711 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00712 UInt32 outDataSize;
00713
00714 if (fPluginID > 0) {
00715
00716 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
00717 if (osErr != noErr) {
00718 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
00719 printError(osErr);
00720 return osErr;
00721 }
00722
00723 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
00724 if (osErr != noErr) {
00725 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
00726 printError(osErr);
00727 return osErr;
00728 }
00729
00730 }
00731
00732 return noErr;
00733 }
00734
00735 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00736 {
00737 OSStatus err = noErr;
00738 AudioObjectID sub_device[32];
00739 UInt32 outSize = sizeof(sub_device);
00740
00741 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00742 vector<AudioDeviceID> captureDeviceIDArray;
00743
00744 if (err != noErr) {
00745 jack_log("Input device does not have subdevices");
00746 captureDeviceIDArray.push_back(captureDeviceID);
00747 } else {
00748 int num_devices = outSize / sizeof(AudioObjectID);
00749 jack_log("Input device has %d subdevices", num_devices);
00750 for (int i = 0; i < num_devices; i++) {
00751 captureDeviceIDArray.push_back(sub_device[i]);
00752 }
00753 }
00754
00755 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00756 vector<AudioDeviceID> playbackDeviceIDArray;
00757
00758 if (err != noErr) {
00759 jack_log("Output device does not have subdevices");
00760 playbackDeviceIDArray.push_back(playbackDeviceID);
00761 } else {
00762 int num_devices = outSize / sizeof(AudioObjectID);
00763 jack_log("Output device has %d subdevices", num_devices);
00764 for (int i = 0; i < num_devices; i++) {
00765 playbackDeviceIDArray.push_back(sub_device[i]);
00766 }
00767 }
00768
00769 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
00770 }
00771
00772 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00773 {
00774 OSStatus osErr = noErr;
00775 UInt32 outSize;
00776 Boolean outWritable;
00777
00778
00779
00780 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00781 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00782 UInt32 theQualifierDataSize = sizeof(AudioObjectID);
00783 AudioClassID inClass = kAudioSubDeviceClassID;
00784 void* theQualifierData = &inClass;
00785 UInt32 subDevicesNum = 0;
00786
00787
00788
00789
00790 UInt32 keptclockdomain = 0;
00791 UInt32 clockdomain = 0;
00792 outSize = sizeof(UInt32);
00793 bool need_clock_drift_compensation = false;
00794
00795 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00796 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
00797 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
00798 } else {
00799
00800 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00801 if (osErr != 0) {
00802 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
00803 printError(osErr);
00804 } else {
00805 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00806 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
00807 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00808 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
00809 need_clock_drift_compensation = true;
00810 }
00811 }
00812 }
00813 }
00814
00815 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00816 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
00817 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
00818 } else {
00819
00820 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00821 if (osErr != 0) {
00822 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
00823 printError(osErr);
00824 } else {
00825 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00826 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
00827 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00828 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
00829 need_clock_drift_compensation = true;
00830 }
00831 }
00832 }
00833 }
00834
00835
00836 if (keptclockdomain == 0) {
00837 need_clock_drift_compensation = true;
00838 }
00839
00840
00841
00842
00843
00844 char device_name[256];
00845 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00846 GetDeviceNameFromID(captureDeviceID[i], device_name);
00847 jack_info("Separated input = '%s' ", device_name);
00848 }
00849
00850 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00851 GetDeviceNameFromID(playbackDeviceID[i], device_name);
00852 jack_info("Separated output = '%s' ", device_name);
00853 }
00854
00855 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
00856 if (osErr != noErr) {
00857 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
00858 printError(osErr);
00859 return osErr;
00860 }
00861
00862 AudioValueTranslation pluginAVT;
00863
00864 CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
00865
00866 pluginAVT.mInputData = &inBundleRef;
00867 pluginAVT.mInputDataSize = sizeof(inBundleRef);
00868 pluginAVT.mOutputData = &fPluginID;
00869 pluginAVT.mOutputDataSize = sizeof(fPluginID);
00870
00871 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
00872 if (osErr != noErr) {
00873 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
00874 printError(osErr);
00875 return osErr;
00876 }
00877
00878
00879
00880
00881
00882 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
00883
00884 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
00885 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
00886
00887
00888 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
00889
00890
00891 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
00892
00893
00894 int value = 1;
00895 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
00896
00897 SInt32 system;
00898 Gestalt(gestaltSystemVersion, &system);
00899
00900 jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
00901
00902
00903 if (system < 0x00001054) {
00904 jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
00905 } else {
00906 jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
00907 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
00908 }
00909
00910
00911 CFMutableArrayRef subDevicesArrayClock = NULL;
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
00955
00956 vector<CFStringRef> captureDeviceUID;
00957 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00958 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
00959 if (ref == NULL) {
00960 return -1;
00961 }
00962 captureDeviceUID.push_back(ref);
00963
00964 CFArrayAppendValue(subDevicesArray, ref);
00965 }
00966
00967 vector<CFStringRef> playbackDeviceUID;
00968 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00969 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
00970 if (ref == NULL) {
00971 return -1;
00972 }
00973 playbackDeviceUID.push_back(ref);
00974
00975 CFArrayAppendValue(subDevicesArray, ref);
00976 }
00977
00978
00979
00980
00981
00982 AudioObjectPropertyAddress pluginAOPA;
00983 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
00984 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00985 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00986 UInt32 outDataSize;
00987
00988 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
00989 if (osErr != noErr) {
00990 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
00991 printError(osErr);
00992 goto error;
00993 }
00994
00995 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
00996 if (osErr != noErr) {
00997 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
00998 printError(osErr);
00999 goto error;
01000 }
01001
01002
01003
01004 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01005
01006
01007
01008
01009
01010 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
01011 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01012 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01013 outDataSize = sizeof(CFMutableArrayRef);
01014 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
01015 if (osErr != noErr) {
01016 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
01017 printError(osErr);
01018 goto error;
01019 }
01020
01021
01022 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01023
01024
01025
01026
01027
01028
01029
01030 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
01031 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01032 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01033 outDataSize = sizeof(CFStringRef);
01034 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
01035 if (osErr != noErr) {
01036 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
01037 printError(osErr);
01038 goto error;
01039 }
01040
01041
01042 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01043
01044
01045
01046
01047 if (fClockDriftCompensate) {
01048 if (need_clock_drift_compensation) {
01049 jack_info("Clock drift compensation activated...");
01050
01051
01052 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
01053 if (osErr != noErr) {
01054 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01055 printError(osErr);
01056 }
01057
01058
01059 subDevicesNum = outSize / sizeof(AudioObjectID);
01060 jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
01061 AudioObjectID subDevices[subDevicesNum];
01062 outSize = sizeof(subDevices);
01063
01064 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
01065 if (osErr != noErr) {
01066 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
01067 printError(osErr);
01068 }
01069
01070
01071 for (UInt32 index = 0; index < subDevicesNum; ++index) {
01072 UInt32 theDriftCompensationValue = 1;
01073 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
01074 if (osErr != noErr) {
01075 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
01076 printError(osErr);
01077 }
01078 }
01079 } else {
01080 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
01081 }
01082 }
01083
01084
01085 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01086
01087
01088
01089
01090
01091
01092 CFRelease(AggregateDeviceNumberRef);
01093
01094
01095 CFRelease(aggDeviceDict);
01096 CFRelease(subDevicesArray);
01097
01098 if (subDevicesArrayClock) {
01099 CFRelease(subDevicesArrayClock);
01100 }
01101
01102
01103 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
01104 CFRelease(captureDeviceUID[i]);
01105 }
01106
01107 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
01108 CFRelease(playbackDeviceUID[i]);
01109 }
01110
01111 jack_log("New aggregate device %ld", *outAggregateDevice);
01112 return noErr;
01113
01114 error:
01115 DestroyAggregateDevice();
01116 return -1;
01117 }
01118
01119 int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
01120 const char* playback_driver_uid,
01121 char* capture_driver_name,
01122 char* playback_driver_name,
01123 jack_nframes_t samplerate)
01124 {
01125 capture_driver_name[0] = 0;
01126 playback_driver_name[0] = 0;
01127
01128
01129 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
01130 jack_log("JackCoreAudioDriver::Open duplex");
01131
01132
01133 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
01134
01135 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
01136 jack_log("Will take default in/out");
01137 if (GetDefaultDevice(&fDeviceID) != noErr) {
01138 jack_error("Cannot open default device");
01139 return -1;
01140 }
01141 }
01142 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
01143 jack_error("Cannot get device name from device ID");
01144 return -1;
01145 }
01146
01147 } else {
01148
01149
01150 AudioDeviceID captureID, playbackID;
01151
01152 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
01153 jack_log("Will take default input");
01154 if (GetDefaultInputDevice(&captureID) != noErr) {
01155 jack_error("Cannot open default input device");
01156 return -1;
01157 }
01158 }
01159
01160 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
01161 jack_log("Will take default output");
01162 if (GetDefaultOutputDevice(&playbackID) != noErr) {
01163 jack_error("Cannot open default output device");
01164 return -1;
01165 }
01166 }
01167
01168 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
01169 return -1;
01170 }
01171
01172 GetDeviceNameFromID(captureID, fCaptureUID);
01173 GetDeviceNameFromID(playbackID, fPlaybackUID);
01174 }
01175
01176
01177 } else if (strcmp(capture_driver_uid, "") != 0) {
01178 jack_log("JackCoreAudioDriver::Open capture only");
01179 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
01180 jack_log("Will take default input");
01181 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
01182 jack_error("Cannot open default input device");
01183 return -1;
01184 }
01185 }
01186 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
01187 jack_error("Cannot get device name from device ID");
01188 return -1;
01189 }
01190
01191
01192 } else if (strcmp(playback_driver_uid, "") != 0) {
01193 jack_log("JackCoreAudioDriver::Open playback only");
01194 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
01195 jack_log("Will take default output");
01196 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
01197 jack_error("Cannot open default output device");
01198 return -1;
01199 }
01200 }
01201 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
01202 jack_error("Cannot get device name from device ID");
01203 return -1;
01204 }
01205
01206
01207 } else {
01208 jack_log("JackCoreAudioDriver::Open default driver");
01209 if (GetDefaultDevice(&fDeviceID) != noErr) {
01210 jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
01211
01212
01213 AudioDeviceID captureID, playbackID;
01214
01215 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
01216 jack_log("Will take default input");
01217 if (GetDefaultInputDevice(&captureID) != noErr) {
01218 jack_error("Cannot open default input device");
01219 return -1;
01220 }
01221 }
01222
01223 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
01224 jack_log("Will take default output");
01225 if (GetDefaultOutputDevice(&playbackID) != noErr) {
01226 jack_error("Cannot open default output device");
01227 return -1;
01228 }
01229 }
01230
01231 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
01232 return -1;
01233 }
01234
01235 GetDeviceNameFromID(captureID, fCaptureUID);
01236 GetDeviceNameFromID(playbackID, fPlaybackUID);
01237 }
01238 }
01239
01240 if (fHogged) {
01241 if (TakeHog()) {
01242 jack_info("Device = %ld has been hogged", fDeviceID);
01243 }
01244 }
01245
01246 return 0;
01247 }
01248
01249
01250
01251
01252 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_nChannels, int& out_nChannels, bool strict)
01253 {
01254 OSStatus err = noErr;
01255
01256 if (capturing) {
01257 err = GetTotalChannels(fDeviceID, in_nChannels, true);
01258 if (err != noErr) {
01259 jack_error("Cannot get input channel number");
01260 printError(err);
01261 return -1;
01262 } else {
01263 jack_log("Max input channels : %d", in_nChannels);
01264 }
01265 }
01266
01267 if (playing) {
01268 err = GetTotalChannels(fDeviceID, out_nChannels, false);
01269 if (err != noErr) {
01270 jack_error("Cannot get output channel number");
01271 printError(err);
01272 return -1;
01273 } else {
01274 jack_log("Max output channels : %d", out_nChannels);
01275 }
01276 }
01277
01278 if (inchannels > in_nChannels) {
01279 jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels);
01280 if (strict) {
01281 return -1;
01282 }
01283 }
01284
01285 if (outchannels > out_nChannels) {
01286 jack_error("This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels);
01287 if (strict) {
01288 return -1;
01289 }
01290 }
01291
01292 if (inchannels == -1) {
01293 jack_log("Setup max in channels = %d", in_nChannels);
01294 inchannels = in_nChannels;
01295 }
01296
01297 if (outchannels == -1) {
01298 jack_log("Setup max out channels = %d", out_nChannels);
01299 outchannels = out_nChannels;
01300 }
01301
01302 return 0;
01303 }
01304
01305 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
01306 {
01307
01308 OSStatus err = noErr;
01309 UInt32 tmp_buffer_size = buffer_size;
01310 UInt32 outSize = sizeof(UInt32);
01311
01312 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
01313 if (err != noErr) {
01314 jack_error("Cannot get buffer size %ld", buffer_size);
01315 printError(err);
01316 return -1;
01317 } else {
01318 jack_log("Current buffer size = %ld", tmp_buffer_size);
01319 }
01320
01321
01322 if (buffer_size != tmp_buffer_size) {
01323 tmp_buffer_size = buffer_size;
01324
01325
01326 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback, this);
01327 if (err != noErr) {
01328 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
01329 printError(err);
01330 return -1;
01331 }
01332
01333
01334 int count = 0;
01335 fState = false;
01336
01337 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
01338 if (err != noErr) {
01339 jack_error("Cannot set buffer size = %ld", tmp_buffer_size);
01340 printError(err);
01341 goto error;
01342 }
01343
01344 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
01345 usleep(100000);
01346 jack_log("Wait count = %d", count);
01347 }
01348
01349 if (count >= WAIT_NOTIFICATION_COUNTER) {
01350 jack_error("Did not get buffer size notification...");
01351 goto error;
01352 }
01353
01354
01355 outSize = sizeof(UInt32);
01356 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
01357 if (err != noErr) {
01358 jack_error("Cannot get current buffer size");
01359 printError(err);
01360 } else {
01361 jack_log("Checked buffer size = %ld", tmp_buffer_size);
01362 }
01363
01364
01365 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
01366 }
01367
01368 return 0;
01369
01370 error:
01371
01372
01373 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
01374 return -1;
01375
01376 }
01377
01378 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
01379 {
01380 return SetupSampleRateAux(fDeviceID, sample_rate);
01381 }
01382
01383 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
01384 {
01385 OSStatus err = noErr;
01386 UInt32 outSize;
01387 Float64 tmp_sample_rate;
01388
01389
01390 outSize = sizeof(Float64);
01391 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
01392 if (err != noErr) {
01393 jack_error("Cannot get current sample rate");
01394 printError(err);
01395 return -1;
01396 } else {
01397 jack_log("Current sample rate = %f", tmp_sample_rate);
01398 }
01399
01400
01401 if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
01402 tmp_sample_rate = (Float64)sample_rate;
01403
01404
01405 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
01406 if (err != noErr) {
01407 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01408 printError(err);
01409 return -1;
01410 }
01411
01412
01413 int count = 0;
01414 fState = false;
01415
01416 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
01417 if (err != noErr) {
01418 jack_error("Cannot set sample rate = %ld", sample_rate);
01419 printError(err);
01420 goto error;
01421 }
01422
01423 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
01424 usleep(100000);
01425 jack_log("Wait count = %d", count);
01426 }
01427
01428 if (count >= WAIT_NOTIFICATION_COUNTER) {
01429 jack_error("Did not get sample rate notification...");
01430 goto error;
01431 }
01432
01433
01434 outSize = sizeof(Float64);
01435 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
01436 if (err != noErr) {
01437 jack_error("Cannot get current sample rate");
01438 printError(err);
01439 } else {
01440 jack_log("Checked sample rate = %f", tmp_sample_rate);
01441 }
01442
01443
01444 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
01445 }
01446
01447 return 0;
01448
01449 error:
01450
01451
01452 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
01453 return -1;
01454 }
01455
01456 int JackCoreAudioDriver::OpenAUHAL(bool capturing,
01457 bool playing,
01458 int inchannels,
01459 int outchannels,
01460 int in_nChannels,
01461 int out_nChannels,
01462 const vector<int>& chan_in_list,
01463 const vector<int>& chan_out_list,
01464 jack_nframes_t buffer_size,
01465 jack_nframes_t sample_rate)
01466 {
01467 ComponentResult err1;
01468 UInt32 enableIO;
01469 AudioStreamBasicDescription srcFormat, dstFormat;
01470 AudioDeviceID currAudioDeviceID;
01471 UInt32 size;
01472
01473 jack_log("OpenAUHAL capturing = %d playing = %d inchannels = %d outchannels = %d in_nChannels = %d out_nChannels = %d chan_in_list = %d chan_out_list = %d",
01474 capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, chan_in_list.size(), chan_out_list.size());
01475
01476 if (inchannels == 0 && outchannels == 0) {
01477 jack_error("No input and output channels...");
01478 return -1;
01479 }
01480
01481
01482 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
01483 Component HALOutput = FindNextComponent(NULL, &cd);
01484
01485 err1 = OpenAComponent(HALOutput, &fAUHAL);
01486 if (err1 != noErr) {
01487 jack_error("Error calling OpenAComponent");
01488 printError(err1);
01489 goto error;
01490 }
01491
01492 err1 = AudioUnitInitialize(fAUHAL);
01493 if (err1 != noErr) {
01494 jack_error("Cannot initialize AUHAL unit");
01495 printError(err1);
01496 goto error;
01497 }
01498
01499
01500 if (capturing && inchannels > 0) {
01501 enableIO = 1;
01502 jack_log("Setup AUHAL input on");
01503 } else {
01504 enableIO = 0;
01505 jack_log("Setup AUHAL input off");
01506 }
01507
01508 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
01509 if (err1 != noErr) {
01510 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
01511 printError(err1);
01512 goto error;
01513 }
01514
01515 if (playing && outchannels > 0) {
01516 enableIO = 1;
01517 jack_log("Setup AUHAL output on");
01518 } else {
01519 enableIO = 0;
01520 jack_log("Setup AUHAL output off");
01521 }
01522
01523 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
01524 if (err1 != noErr) {
01525 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
01526 printError(err1);
01527 goto error;
01528 }
01529
01530 size = sizeof(AudioDeviceID);
01531 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
01532 if (err1 != noErr) {
01533 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
01534 printError(err1);
01535 goto error;
01536 } else {
01537 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
01538 }
01539
01540
01541 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
01542 if (err1 != noErr) {
01543 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
01544 printError(err1);
01545 goto error;
01546 }
01547
01548
01549 if (capturing && inchannels > 0) {
01550 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
01551 if (err1 != noErr) {
01552 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01553 printError(err1);
01554 goto error;
01555 }
01556 }
01557
01558 if (playing && outchannels > 0) {
01559 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
01560 if (err1 != noErr) {
01561 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01562 printError(err1);
01563 goto error;
01564 }
01565 }
01566
01567
01568 if (capturing && inchannels > 0 && inchannels <= in_nChannels) {
01569 SInt32 chanArr[in_nChannels];
01570 for (int i = 0; i < in_nChannels; i++) {
01571 chanArr[i] = -1;
01572 }
01573
01574 if (chan_in_list.size() > 0) {
01575 for (uint i = 0; i < chan_in_list.size(); i++) {
01576 int chan = chan_in_list[i];
01577 if (chan < out_nChannels) {
01578
01579 chanArr[chan] = i;
01580 jack_info("Input channel = %d ==> JACK input port = %d", chan, i);
01581 } else {
01582 jack_info("Error input channel number is incorrect : %d", chan);
01583 goto error;
01584 }
01585 }
01586 } else {
01587 for (int i = 0; i < inchannels; i++) {
01588 chanArr[i] = i;
01589 jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i);
01590 }
01591 }
01592
01593 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
01594 if (err1 != noErr) {
01595 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
01596 printError(err1);
01597 goto error;
01598 }
01599 }
01600
01601
01602 if (playing && outchannels > 0 && outchannels <= out_nChannels) {
01603 SInt32 chanArr[out_nChannels];
01604 for (int i = 0; i < out_nChannels; i++) {
01605 chanArr[i] = -1;
01606 }
01607
01608 if (chan_out_list.size() > 0) {
01609 for (uint i = 0; i < chan_out_list.size(); i++) {
01610 int chan = chan_out_list[i];
01611 if (chan < out_nChannels) {
01612
01613 chanArr[chan] = i;
01614 jack_info("JACK output port = %d ==> output channel = %d", i, chan);
01615 } else {
01616 jack_info("Error output channel number is incorrect : %d", chan);
01617 goto error;
01618 }
01619 }
01620 } else {
01621 for (int i = 0; i < outchannels; i++) {
01622 chanArr[i] = i;
01623 jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]);
01624 }
01625 }
01626
01627 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
01628 if (err1 != noErr) {
01629 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
01630 printError(err1);
01631 goto error;
01632 }
01633 }
01634
01635
01636 if (capturing && inchannels > 0) {
01637
01638 size = sizeof(AudioStreamBasicDescription);
01639 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
01640 if (err1 != noErr) {
01641 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01642 printError(err1);
01643 goto error;
01644 }
01645 PrintStreamDesc(&srcFormat);
01646
01647 jack_log("Setup AUHAL input stream converter SR = %ld", sample_rate);
01648 srcFormat.mSampleRate = sample_rate;
01649 srcFormat.mFormatID = kAudioFormatLinearPCM;
01650 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01651 srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
01652 srcFormat.mFramesPerPacket = 1;
01653 srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
01654 srcFormat.mChannelsPerFrame = inchannels;
01655 srcFormat.mBitsPerChannel = 32;
01656 PrintStreamDesc(&srcFormat);
01657
01658 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
01659 if (err1 != noErr) {
01660 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01661 printError(err1);
01662 goto error;
01663 }
01664 }
01665
01666 if (playing && outchannels > 0) {
01667
01668 size = sizeof(AudioStreamBasicDescription);
01669 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
01670 if (err1 != noErr) {
01671 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01672 printError(err1);
01673 goto error;
01674 }
01675 PrintStreamDesc(&dstFormat);
01676
01677 jack_log("Setup AUHAL output stream converter SR = %ld", sample_rate);
01678 dstFormat.mSampleRate = sample_rate;
01679 dstFormat.mFormatID = kAudioFormatLinearPCM;
01680 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01681 dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
01682 dstFormat.mFramesPerPacket = 1;
01683 dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
01684 dstFormat.mChannelsPerFrame = outchannels;
01685 dstFormat.mBitsPerChannel = 32;
01686 PrintStreamDesc(&dstFormat);
01687
01688 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
01689 if (err1 != noErr) {
01690 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01691 printError(err1);
01692 goto error;
01693 }
01694 }
01695
01696
01697 if (inchannels > 0 && outchannels == 0) {
01698 AURenderCallbackStruct output;
01699 output.inputProc = Render;
01700 output.inputProcRefCon = this;
01701 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
01702 if (err1 != noErr) {
01703 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
01704 printError(err1);
01705 goto error;
01706 }
01707 } else {
01708 AURenderCallbackStruct output;
01709 output.inputProc = Render;
01710 output.inputProcRefCon = this;
01711 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
01712 if (err1 != noErr) {
01713 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
01714 printError(err1);
01715 goto error;
01716 }
01717 }
01718
01719 return 0;
01720
01721 error:
01722 CloseAUHAL();
01723 return -1;
01724 }
01725
01726 int JackCoreAudioDriver::SetupBuffers(int inchannels)
01727 {
01728
01729 fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
01730 fJackInputData->mNumberBuffers = inchannels;
01731 for (int i = 0; i < inchannels; i++) {
01732 fJackInputData->mBuffers[i].mNumberChannels = 1;
01733 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
01734 }
01735 return 0;
01736 }
01737
01738 void JackCoreAudioDriver::DisposeBuffers()
01739 {
01740 if (fJackInputData) {
01741 free(fJackInputData);
01742 fJackInputData = 0;
01743 }
01744 }
01745
01746 void JackCoreAudioDriver::CloseAUHAL()
01747 {
01748 AudioOutputUnitStop(fAUHAL);
01749 AudioUnitUninitialize(fAUHAL);
01750 CloseComponent(fAUHAL);
01751 }
01752
01753 int JackCoreAudioDriver::AddListeners()
01754 {
01755 OSStatus err = noErr;
01756
01757
01758 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
01759 if (err != noErr) {
01760 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
01761 printError(err);
01762 return -1;
01763 }
01764
01765 err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
01766 if (err != noErr) {
01767 jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
01768 printError(err);
01769 return -1;
01770 }
01771
01772 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
01773 if (err != noErr) {
01774 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01775 printError(err);
01776 return -1;
01777 }
01778
01779 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
01780 if (err != noErr) {
01781 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
01782 printError(err);
01783 return -1;
01784 }
01785
01786 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback, this);
01787 if (err != noErr) {
01788 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
01789 printError(err);
01790 return -1;
01791 }
01792
01793 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback, this);
01794 if (err != noErr) {
01795 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
01796 printError(err);
01797 return -1;
01798 }
01799
01800 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01801 if (err != noErr) {
01802 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01803 printError(err);
01804 return -1;
01805 }
01806
01807 err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01808 if (err != noErr) {
01809 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01810 printError(err);
01811 return -1;
01812 }
01813
01814 if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
01815 UInt32 outSize = sizeof(float);
01816 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
01817 if (err != noErr) {
01818 jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
01819 printError(err);
01820 }
01821 }
01822
01823 return 0;
01824 }
01825
01826 void JackCoreAudioDriver::RemoveListeners()
01827 {
01828 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
01829 AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
01830 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
01831 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
01832 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
01833 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
01834 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
01835 AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
01836 }
01837
01838 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
01839 jack_nframes_t sample_rate,
01840 bool capturing,
01841 bool playing,
01842 int inchannels,
01843 int outchannels,
01844 const char* chan_in_list,
01845 const char* chan_out_list,
01846 bool monitor,
01847 const char* capture_driver_uid,
01848 const char* playback_driver_uid,
01849 jack_nframes_t capture_latency,
01850 jack_nframes_t playback_latency,
01851 int async_output_latency,
01852 int computation_grain,
01853 bool hogged,
01854 bool clock_drift)
01855 {
01856 int in_nChannels = 0;
01857 int out_nChannels = 0;
01858 char capture_driver_name[256];
01859 char playback_driver_name[256];
01860
01861 fCaptureLatency = capture_latency;
01862 fPlaybackLatency = playback_latency;
01863 fIOUsage = float(async_output_latency) / 100.f;
01864 fComputationGrain = float(computation_grain) / 100.f;
01865 fHogged = hogged;
01866 fClockDriftCompensate = clock_drift;
01867
01868 SInt32 major;
01869 SInt32 minor;
01870 Gestalt(gestaltSystemVersionMajor, &major);
01871 Gestalt(gestaltSystemVersionMinor, &minor);
01872
01873 vector<int> parsed_chan_in_list;
01874 vector<int> parsed_chan_out_list;
01875
01876 ParseChannelList(chan_in_list, parsed_chan_in_list);
01877 if (parsed_chan_in_list.size() > 0) {
01878 jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size());
01879 inchannels = parsed_chan_in_list.size();
01880 }
01881
01882 ParseChannelList(chan_out_list, parsed_chan_out_list);
01883 if (parsed_chan_out_list.size() > 0) {
01884 jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size());
01885 outchannels = parsed_chan_out_list.size();
01886 }
01887
01888
01889 if (major == 10 && minor >= 6) {
01890 CFRunLoopRef theRunLoop = NULL;
01891 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01892 OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
01893 if (osErr != noErr) {
01894 jack_error("JackCoreAudioDriver::Open kAudioHardwarePropertyRunLoop error");
01895 printError(osErr);
01896 }
01897 }
01898
01899 if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate) < 0) {
01900 goto error;
01901 }
01902
01903
01904 if (JackAudioDriver::Open(buffer_size, sample_rate,
01905 capturing, playing,
01906 inchannels, outchannels,
01907 monitor,
01908 capture_driver_name,
01909 playback_driver_name,
01910 capture_latency,
01911 playback_latency) != 0) {
01912 goto error;
01913 }
01914
01915 if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0) {
01916 goto error;
01917 }
01918
01919 if (SetupBufferSize(buffer_size) < 0) {
01920 goto error;
01921 }
01922
01923 if (SetupSampleRate(sample_rate) < 0) {
01924 goto error;
01925 }
01926
01927 if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
01928 goto error;
01929 }
01930
01931 if (capturing && inchannels > 0) {
01932 if (SetupBuffers(inchannels) < 0) {
01933 goto error;
01934 }
01935 }
01936
01937 if (AddListeners() < 0) {
01938 goto error;
01939 }
01940
01941
01942 fCaptureChannels = inchannels;
01943 fPlaybackChannels = outchannels;
01944 return noErr;
01945
01946 error:
01947 Close();
01948 return -1;
01949 }
01950
01951 int JackCoreAudioDriver::Close()
01952 {
01953 jack_log("JackCoreAudioDriver::Close");
01954
01955
01956 int res = JackAudioDriver::Close();
01957
01958 RemoveListeners();
01959 DisposeBuffers();
01960 CloseAUHAL();
01961 DestroyAggregateDevice();
01962 return res;
01963 }
01964
01965 void JackCoreAudioDriver::UpdateLatencies()
01966 {
01967 UInt32 size;
01968 OSStatus err;
01969 jack_latency_range_t input_range;
01970 jack_latency_range_t output_range;
01971 jack_latency_range_t monitor_range;
01972
01973
01974 size = sizeof(UInt32);
01975 UInt32 value1 = 0;
01976 UInt32 value2 = 0;
01977 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
01978 if (err != noErr) {
01979 jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
01980 }
01981 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
01982 if (err != noErr) {
01983 jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
01984 }
01985
01986 input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
01987
01988
01989 vector<int> input_latencies;
01990 err = GetStreamLatencies(fDeviceID, true, input_latencies);
01991
01992 for (int i = 0; i < fCaptureChannels; i++) {
01993 if (err != noErr) {
01994 input_range.min += input_latencies[i];
01995 input_range.max += input_latencies[i];
01996 }
01997 fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
01998 }
01999
02000
02001 size = sizeof(UInt32);
02002 value1 = 0;
02003 value2 = 0;
02004 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
02005 if (err != noErr) {
02006 jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
02007 }
02008 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
02009 if (err != noErr) {
02010 jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
02011 }
02012
02013
02014 vector<int> output_latencies;
02015 err = GetStreamLatencies(fDeviceID, false, output_latencies);
02016
02017
02018 output_range.min = output_range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
02019 ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
02020
02021 for (int i = 0; i < fPlaybackChannels; i++) {
02022 if (err != noErr) {
02023 output_range.min += output_latencies[i];
02024 output_range.max += output_latencies[i];
02025 }
02026 fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
02027
02028
02029 if (fWithMonitorPorts) {
02030 monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
02031 fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
02032 }
02033 }
02034 }
02035
02036 int JackCoreAudioDriver::Attach()
02037 {
02038 OSStatus err;
02039 JackPort* port;
02040 jack_port_id_t port_index;
02041 UInt32 size;
02042 Boolean isWritable;
02043 char channel_name[64];
02044 char name[REAL_JACK_PORT_NAME_SIZE];
02045 char alias[REAL_JACK_PORT_NAME_SIZE];
02046
02047 jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
02048
02049 for (int i = 0; i < fCaptureChannels; i++) {
02050
02051 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
02052 if (err != noErr) {
02053 jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
02054 }
02055 if (err == noErr && size > 0) {
02056 err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
02057 if (err != noErr) {
02058 jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
02059 }
02060 snprintf(alias, sizeof(alias), "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
02061 } else {
02062 snprintf(alias, sizeof(alias), "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
02063 }
02064
02065 snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
02066
02067 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02068 jack_error("Cannot register port for %s", name);
02069 return -1;
02070 }
02071
02072 port = fGraphManager->GetPort(port_index);
02073 port->SetAlias(alias);
02074 fCapturePortList[i] = port_index;
02075 }
02076
02077 for (int i = 0; i < fPlaybackChannels; i++) {
02078
02079 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
02080 if (err != noErr) {
02081 jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
02082 }
02083 if (err == noErr && size > 0) {
02084 err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
02085 if (err != noErr) {
02086 jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
02087 }
02088 snprintf(alias, sizeof(alias), "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
02089 } else {
02090 snprintf(alias, sizeof(alias), "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
02091 }
02092
02093 snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
02094
02095 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02096 jack_error("Cannot register port for %s", name);
02097 return -1;
02098 }
02099
02100 port = fGraphManager->GetPort(port_index);
02101 port->SetAlias(alias);
02102 fPlaybackPortList[i] = port_index;
02103
02104
02105 if (fWithMonitorPorts) {
02106 jack_log("Create monitor port");
02107 snprintf(name, sizeof(name), "%s:monitor_%u", fClientControl.fName, i + 1);
02108 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02109 jack_error("Cannot register monitor port for %s", name);
02110 return -1;
02111 } else {
02112 fMonitorPortList[i] = port_index;
02113 }
02114 }
02115 }
02116
02117 UpdateLatencies();
02118
02119
02120 for (int i = 0; i < fCaptureChannels; i++) {
02121 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
02122 }
02123
02124 return 0;
02125 }
02126
02127 int JackCoreAudioDriver::Start()
02128 {
02129 jack_log("JackCoreAudioDriver::Start");
02130 if (JackAudioDriver::Start() == 0) {
02131
02132
02133 fState = false;
02134 int count = 0;
02135
02136 OSStatus err = AudioOutputUnitStart(fAUHAL);
02137 if (err == noErr) {
02138
02139 while (!fState && count++ < WAIT_COUNTER) {
02140 usleep(100000);
02141 jack_log("JackCoreAudioDriver::Start wait count = %d", count);
02142 }
02143
02144 if (count < WAIT_COUNTER) {
02145 jack_info("CoreAudio driver is running...");
02146 return 0;
02147 }
02148
02149 jack_error("CoreAudio driver cannot start...");
02150 }
02151 JackAudioDriver::Stop();
02152 }
02153 return -1;
02154 }
02155
02156 int JackCoreAudioDriver::Stop()
02157 {
02158 jack_log("JackCoreAudioDriver::Stop");
02159 int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
02160 if (JackAudioDriver::Stop() < 0) {
02161 res = -1;
02162 }
02163 return res;
02164 }
02165
02166 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
02167 {
02168 if (SetupBufferSize(buffer_size) < 0) {
02169 return -1;
02170 }
02171
02172 JackAudioDriver::SetBufferSize(buffer_size);
02173
02174
02175 UpdateLatencies();
02176
02177
02178 for (int i = 0; i < fCaptureChannels; i++) {
02179 fJackInputData->mBuffers[i].mNumberChannels = 1;
02180 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
02181 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
02182 }
02183
02184 return 0;
02185 }
02186
02187 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
02188 {
02189 pid_t hog_pid;
02190 OSStatus err;
02191
02192 UInt32 propSize = sizeof(hog_pid);
02193 err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
02194 if (err) {
02195 jack_error("Cannot read hog state...");
02196 printError(err);
02197 }
02198
02199 if (hog_pid != getpid()) {
02200 hog_pid = getpid();
02201 err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
02202 if (err != noErr) {
02203 jack_error("Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
02204 return false;
02205 }
02206 }
02207
02208 return true;
02209 }
02210
02211 bool JackCoreAudioDriver::TakeHog()
02212 {
02213 OSStatus err = noErr;
02214 AudioObjectID sub_device[32];
02215 UInt32 outSize = sizeof(sub_device);
02216 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
02217
02218 if (err != noErr) {
02219 jack_log("Device does not have subdevices");
02220 return TakeHogAux(fDeviceID, true);
02221 } else {
02222 int num_devices = outSize / sizeof(AudioObjectID);
02223 jack_log("Device does has %d subdevices", num_devices);
02224 for (int i = 0; i < num_devices; i++) {
02225 if (!TakeHogAux(sub_device[i], true)) {
02226 return false;
02227 }
02228 }
02229 return true;
02230 }
02231 }
02232
02233 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
02234 {
02235 UInt32 deviceType, outSize = sizeof(UInt32);
02236 OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
02237
02238 if (err != noErr) {
02239 jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
02240 return false;
02241 } else {
02242 return (deviceType == kAudioDeviceTransportTypeAggregate);
02243 }
02244 }
02245
02246
02247 }
02248
02249
02250 #ifdef __cplusplus
02251 extern "C"
02252 {
02253 #endif
02254
02255 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
02256 {
02257 jack_driver_desc_t * desc;
02258 jack_driver_desc_filler_t filler;
02259 jack_driver_param_value_t value;
02260
02261 desc = jack_driver_descriptor_construct("coreaudio", JackDriverMaster, "Apple CoreAudio API based audio backend", &filler);
02262
02263 value.i = -1;
02264 jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used");
02265 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
02266 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");
02267
02268 value.str[0] = 0;
02269 jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list", "List of input channel number to be opened");
02270 jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list", "List of output channel number to be opened");
02271
02272 value.str[0] = 0;
02273 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
02274 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output CoreAudio device name", NULL);
02275
02276 value.i = 0;
02277 jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
02278
02279 value.i = TRUE;
02280 jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
02281
02282 value.ui = 44100U;
02283 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
02284
02285 value.ui = 256U;
02286 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
02287
02288 value.str[0] = 0;
02289 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
02290
02291 value.ui = 0;
02292 jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
02293 jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
02294
02295 value.i = FALSE;
02296 jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
02297
02298 value.i = FALSE;
02299 jack_driver_descriptor_add_parameter(desc, &filler, "hog", 'H', JackDriverParamBool, &value, NULL, "Take exclusive access of the audio device", NULL);
02300
02301 value.ui = 100;
02302 jack_driver_descriptor_add_parameter(desc, &filler, "async-latency", 'L', JackDriverParamUInt, &value, NULL, "Extra output latency in asynchronous mode (percent)", NULL);
02303
02304 value.ui = 100;
02305 jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
02306
02307 value.i = FALSE;
02308 jack_driver_descriptor_add_parameter(desc, &filler, "clock-drift", 's', JackDriverParamBool, &value, NULL, "Clock drift compensation", "Whether to compensate clock drift in dynamically created aggregate device");
02309
02310 return desc;
02311 }
02312
02313 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
02314 {
02315 jack_nframes_t srate = 44100;
02316 jack_nframes_t frames_per_interrupt = 256;
02317 bool capture = false;
02318 bool playback = false;
02319 int chan_in = -1;
02320 int chan_out = -1;
02321 const char* chan_in_list = "";
02322 const char* chan_out_list = "";
02323 bool monitor = false;
02324 const char* capture_driver_uid = "";
02325 const char* playback_driver_uid = "";
02326 const JSList *node;
02327 const jack_driver_param_t *param;
02328 jack_nframes_t systemic_input_latency = 0;
02329 jack_nframes_t systemic_output_latency = 0;
02330 int async_output_latency = 100;
02331 int computation_grain = -1;
02332 bool hogged = false;
02333 bool clock_drift = false;
02334
02335 for (node = params; node; node = jack_slist_next(node)) {
02336 param = (const jack_driver_param_t *) node->data;
02337
02338 switch (param->character) {
02339
02340 case 'd':
02341 capture_driver_uid = param->value.str;
02342 playback_driver_uid = param->value.str;
02343 break;
02344
02345 case 'D':
02346 capture = true;
02347 playback = true;
02348 break;
02349
02350 case 'c':
02351 chan_in = chan_out = param->value.i;
02352 break;
02353
02354 case 'i':
02355 chan_in = param->value.i;
02356 break;
02357
02358 case 'o':
02359 chan_out = param->value.i;
02360 break;
02361
02362 case 'n':
02363 chan_in_list = param->value.str;
02364 break;
02365
02366 case 'N':
02367 chan_out_list = param->value.str;
02368 break;
02369
02370 case 'C':
02371 capture = true;
02372 if (strcmp(param->value.str, "none") != 0) {
02373 capture_driver_uid = param->value.str;
02374 }
02375 break;
02376
02377 case 'P':
02378 playback = true;
02379 if (strcmp(param->value.str, "none") != 0) {
02380 playback_driver_uid = param->value.str;
02381 }
02382 break;
02383
02384 case 'm':
02385 monitor = param->value.i;
02386 break;
02387
02388 case 'r':
02389 srate = param->value.ui;
02390 break;
02391
02392 case 'p':
02393 frames_per_interrupt = (unsigned int)param->value.ui;
02394 break;
02395
02396 case 'I':
02397 systemic_input_latency = param->value.ui;
02398 break;
02399
02400 case 'O':
02401 systemic_output_latency = param->value.ui;
02402 break;
02403
02404 case 'l':
02405 Jack::DisplayDeviceNames();
02406 return NULL;
02407
02408 case 'H':
02409 hogged = true;
02410 break;
02411
02412 case 'L':
02413 async_output_latency = param->value.ui;
02414 break;
02415
02416 case 'G':
02417 computation_grain = param->value.ui;
02418 break;
02419
02420 case 's':
02421 clock_drift = true;
02422 break;
02423 }
02424 }
02425
02426
02427 if (!capture && !playback) {
02428 capture = true;
02429 playback = true;
02430 }
02431
02432 if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) {
02433 printf("Input channel list and in channels are both specified, input channel list will take over...\n");
02434 }
02435
02436 if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) {
02437 printf("Output channel list and out channels are both specified, output channel list will take over...\n");
02438 }
02439
02440 Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
02441 if (driver->Open(frames_per_interrupt,
02442 srate, capture,
02443 playback, chan_in,
02444 chan_out, chan_in_list,
02445 chan_out_list, monitor,
02446 capture_driver_uid,
02447 playback_driver_uid,
02448 systemic_input_latency,
02449 systemic_output_latency,
02450 async_output_latency,
02451 computation_grain,
02452 hogged, clock_drift) == 0) {
02453 return driver;
02454 } else {
02455 delete driver;
02456 return NULL;
02457 }
02458 }
02459
02460 #ifdef __cplusplus
02461 }
02462 #endif
02463
02464