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