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 {}
00414
00415 JackCoreAudioDriver::~JackCoreAudioDriver()
00416 {}
00417
00418 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
00419 {
00420 OSStatus osErr = noErr;
00421 AudioObjectPropertyAddress pluginAOPA;
00422 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
00423 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00424 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00425 UInt32 outDataSize;
00426
00427 if (fPluginID > 0) {
00428
00429 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
00430 if (osErr != noErr) {
00431 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
00432 printError(osErr);
00433 return osErr;
00434 }
00435
00436 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
00437 if (osErr != noErr) {
00438 jack_error("JackCoreAudioDriver::DestroyAggregateDevice : AudioObjectGetPropertyData error");
00439 printError(osErr);
00440 return osErr;
00441 }
00442
00443 }
00444
00445 return noErr;
00446 }
00447
00448 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00449 {
00450 OSStatus err = noErr;
00451 AudioObjectID sub_device[32];
00452 UInt32 outSize = sizeof(sub_device);
00453
00454 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00455 vector<AudioDeviceID> captureDeviceIDArray;
00456
00457 if (err != noErr) {
00458 jack_log("Input device does not have subdevices");
00459 captureDeviceIDArray.push_back(captureDeviceID);
00460 } else {
00461 int num_devices = outSize / sizeof(AudioObjectID);
00462 jack_log("Input device has %d subdevices", num_devices);
00463 for (int i = 0; i < num_devices; i++) {
00464 captureDeviceIDArray.push_back(sub_device[i]);
00465 }
00466 }
00467
00468 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00469 vector<AudioDeviceID> playbackDeviceIDArray;
00470
00471 if (err != noErr) {
00472 jack_log("Output device does not have subdevices");
00473 playbackDeviceIDArray.push_back(playbackDeviceID);
00474 } else {
00475 int num_devices = outSize / sizeof(AudioObjectID);
00476 jack_log("Output device has %d subdevices", num_devices);
00477 for (int i = 0; i < num_devices; i++) {
00478 playbackDeviceIDArray.push_back(sub_device[i]);
00479 }
00480 }
00481
00482 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
00483 }
00484
00485 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00486 {
00487 OSStatus osErr = noErr;
00488 UInt32 outSize;
00489 Boolean outWritable;
00490
00491
00492
00493 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00494 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00495 UInt32 theQualifierDataSize = sizeof(AudioObjectID);
00496 AudioClassID inClass = kAudioSubDeviceClassID;
00497 void* theQualifierData = &inClass;
00498 UInt32 subDevicesNum = 0;
00499
00500
00501
00502
00503 UInt32 keptclockdomain = 0;
00504 UInt32 clockdomain = 0;
00505 outSize = sizeof(UInt32);
00506 bool need_clock_drift_compensation = false;
00507
00508 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00509 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
00510 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of input device");
00511 } else {
00512
00513 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00514 if (osErr != 0) {
00515 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
00516 printError(osErr);
00517 } else {
00518 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00519 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input clockdomain = %d", clockdomain);
00520 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00521 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
00522 need_clock_drift_compensation = true;
00523 }
00524 }
00525 }
00526 }
00527
00528 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00529 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
00530 jack_error("JackCoreAudioDriver::CreateAggregateDevice : cannot set SR of output device");
00531 } else {
00532
00533 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00534 if (osErr != 0) {
00535 jack_error("JackCoreAudioDriver::CreateAggregateDevice : kAudioDevicePropertyClockDomain error");
00536 printError(osErr);
00537 } else {
00538 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00539 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output clockdomain = %d", clockdomain);
00540 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00541 jack_error("JackCoreAudioDriver::CreateAggregateDevice : devices do not share the same clock!! clock drift compensation would be needed...");
00542 need_clock_drift_compensation = true;
00543 }
00544 }
00545 }
00546 }
00547
00548
00549 if (keptclockdomain == 0) {
00550 need_clock_drift_compensation = true;
00551 }
00552
00553
00554
00555
00556
00557 char device_name[256];
00558 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00559 GetDeviceNameFromID(captureDeviceID[i], device_name);
00560 jack_info("Separated input = '%s' ", device_name);
00561 }
00562
00563 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00564 GetDeviceNameFromID(playbackDeviceID[i], device_name);
00565 jack_info("Separated output = '%s' ", device_name);
00566 }
00567
00568 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
00569 if (osErr != noErr) {
00570 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
00571 printError(osErr);
00572 return osErr;
00573 }
00574
00575 AudioValueTranslation pluginAVT;
00576
00577 CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
00578
00579 pluginAVT.mInputData = &inBundleRef;
00580 pluginAVT.mInputDataSize = sizeof(inBundleRef);
00581 pluginAVT.mOutputData = &fPluginID;
00582 pluginAVT.mOutputDataSize = sizeof(fPluginID);
00583
00584 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
00585 if (osErr != noErr) {
00586 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
00587 printError(osErr);
00588 return osErr;
00589 }
00590
00591
00592
00593
00594
00595 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
00596
00597 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
00598 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
00599
00600
00601 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
00602
00603
00604 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
00605
00606
00607 int value = 1;
00608 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
00609
00610 SInt32 system;
00611 Gestalt(gestaltSystemVersion, &system);
00612
00613 jack_log("JackCoreAudioDriver::CreateAggregateDevice : system version = %x limit = %x", system, 0x00001054);
00614
00615
00616 if (system < 0x00001054) {
00617 jack_log("JackCoreAudioDriver::CreateAggregateDevice : public aggregate device....");
00618 } else {
00619 jack_log("JackCoreAudioDriver::CreateAggregateDevice : private aggregate device....");
00620 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
00621 }
00622
00623
00624 CFMutableArrayRef subDevicesArrayClock = NULL;
00625
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 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
00668
00669 vector<CFStringRef> captureDeviceUID;
00670 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00671 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
00672 if (ref == NULL)
00673 return -1;
00674 captureDeviceUID.push_back(ref);
00675
00676 CFArrayAppendValue(subDevicesArray, ref);
00677 }
00678
00679 vector<CFStringRef> playbackDeviceUID;
00680 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00681 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
00682 if (ref == NULL)
00683 return -1;
00684 playbackDeviceUID.push_back(ref);
00685
00686 CFArrayAppendValue(subDevicesArray, ref);
00687 }
00688
00689
00690
00691
00692
00693 AudioObjectPropertyAddress pluginAOPA;
00694 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
00695 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00696 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00697 UInt32 outDataSize;
00698
00699 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
00700 if (osErr != noErr) {
00701 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyDataSize error");
00702 printError(osErr);
00703 goto error;
00704 }
00705
00706 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
00707 if (osErr != noErr) {
00708 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectGetPropertyData error");
00709 printError(osErr);
00710 goto error;
00711 }
00712
00713
00714
00715 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
00716
00717
00718
00719
00720
00721 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
00722 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00723 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00724 outDataSize = sizeof(CFMutableArrayRef);
00725 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
00726 if (osErr != noErr) {
00727 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for sub-device list error");
00728 printError(osErr);
00729 goto error;
00730 }
00731
00732
00733 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
00734
00735
00736
00737
00738
00739
00740
00741 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
00742 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00743 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00744 outDataSize = sizeof(CFStringRef);
00745 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
00746 if (osErr != noErr) {
00747 jack_error("JackCoreAudioDriver::CreateAggregateDevice : AudioObjectSetPropertyData for master device error");
00748 printError(osErr);
00749 goto error;
00750 }
00751
00752
00753 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
00754
00755
00756
00757
00758 if (fClockDriftCompensate) {
00759 if (need_clock_drift_compensation) {
00760 jack_info("Clock drift compensation activated...");
00761
00762
00763 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
00764 if (osErr != noErr) {
00765 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
00766 printError(osErr);
00767 }
00768
00769
00770 subDevicesNum = outSize / sizeof(AudioObjectID);
00771 jack_info("JackCoreAudioDriver::CreateAggregateDevice clock drift compensation, number of sub-devices = %d", subDevicesNum);
00772 AudioObjectID subDevices[subDevicesNum];
00773 outSize = sizeof(subDevices);
00774
00775 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
00776 if (osErr != noErr) {
00777 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioObjectPropertyOwnedObjects error");
00778 printError(osErr);
00779 }
00780
00781
00782 for (UInt32 index = 0; index < subDevicesNum; ++index) {
00783 UInt32 theDriftCompensationValue = 1;
00784 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
00785 if (osErr != noErr) {
00786 jack_error("JackCoreAudioDriver::CreateAggregateDevice kAudioSubDevicePropertyDriftCompensation error");
00787 printError(osErr);
00788 }
00789 }
00790 } else {
00791 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
00792 }
00793 }
00794
00795
00796 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
00797
00798
00799
00800
00801
00802
00803 CFRelease(AggregateDeviceNumberRef);
00804
00805
00806 CFRelease(aggDeviceDict);
00807 CFRelease(subDevicesArray);
00808
00809 if (subDevicesArrayClock)
00810 CFRelease(subDevicesArrayClock);
00811
00812
00813 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
00814 CFRelease(captureDeviceUID[i]);
00815 }
00816
00817 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
00818 CFRelease(playbackDeviceUID[i]);
00819 }
00820
00821 jack_log("New aggregate device %ld", *outAggregateDevice);
00822 return noErr;
00823
00824 error:
00825 DestroyAggregateDevice();
00826 return -1;
00827 }
00828
00829 int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
00830 const char* playback_driver_uid,
00831 char* capture_driver_name,
00832 char* playback_driver_name,
00833 jack_nframes_t samplerate)
00834 {
00835 capture_driver_name[0] = 0;
00836 playback_driver_name[0] = 0;
00837
00838
00839 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
00840 jack_log("JackCoreAudioDriver::Open duplex");
00841
00842
00843 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
00844
00845 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00846 jack_log("Will take default in/out");
00847 if (GetDefaultDevice(&fDeviceID) != noErr) {
00848 jack_error("Cannot open default device");
00849 return -1;
00850 }
00851 }
00852 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00853 jack_error("Cannot get device name from device ID");
00854 return -1;
00855 }
00856
00857 } else {
00858
00859
00860 AudioDeviceID captureID, playbackID;
00861
00862 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
00863 jack_log("Will take default input");
00864 if (GetDefaultInputDevice(&captureID) != noErr) {
00865 jack_error("Cannot open default device");
00866 return -1;
00867 }
00868 }
00869
00870 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
00871 jack_log("Will take default output");
00872 if (GetDefaultOutputDevice(&playbackID) != noErr) {
00873 jack_error("Cannot open default device");
00874 return -1;
00875 }
00876 }
00877
00878 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr)
00879 return -1;
00880 }
00881
00882
00883 } else if (strcmp(capture_driver_uid, "") != 0) {
00884 jack_log("JackCoreAudioDriver::Open capture only");
00885 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
00886 jack_log("Will take default input");
00887 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
00888 jack_error("Cannot open default device");
00889 return -1;
00890 }
00891 }
00892 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
00893 jack_error("Cannot get device name from device ID");
00894 return -1;
00895 }
00896
00897
00898 } else if (strcmp(playback_driver_uid, "") != 0) {
00899 jack_log("JackCoreAudioDriver::Open playback only");
00900 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
00901 jack_log("Will take default output");
00902 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
00903 jack_error("Cannot open default device");
00904 return -1;
00905 }
00906 }
00907 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00908 jack_error("Cannot get device name from device ID");
00909 return -1;
00910 }
00911
00912
00913 } else {
00914 jack_log("JackCoreAudioDriver::Open default driver");
00915 if (GetDefaultDevice(&fDeviceID) != noErr) {
00916 jack_error("Cannot open default device");
00917 return -1;
00918 }
00919 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
00920 jack_error("Cannot get device name from device ID");
00921 return -1;
00922 }
00923 }
00924
00925 if (fHogged) {
00926 if (TakeHog()) {
00927 jack_info("Device = %ld has been hogged", fDeviceID);
00928 } else {
00929 jack_error("Cannot hog device = %ld", fDeviceID);
00930 }
00931 }
00932
00933 return 0;
00934 }
00935
00936
00937
00938
00939 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_nChannels, int& out_nChannels, bool strict)
00940 {
00941 OSStatus err = noErr;
00942
00943 if (capturing) {
00944 err = GetTotalChannels(fDeviceID, in_nChannels, true);
00945 if (err != noErr) {
00946 jack_error("Cannot get input channel number");
00947 printError(err);
00948 return -1;
00949 } else {
00950 jack_log("Max input channels : %d", in_nChannels);
00951 }
00952 }
00953
00954 if (playing) {
00955 err = GetTotalChannels(fDeviceID, out_nChannels, false);
00956 if (err != noErr) {
00957 jack_error("Cannot get output channel number");
00958 printError(err);
00959 return -1;
00960 } else {
00961 jack_log("Max output channels : %d", out_nChannels);
00962 }
00963 }
00964
00965 if (inchannels > in_nChannels) {
00966 jack_error("This device hasn't required input channels inchannels = %d in_nChannels = %d", inchannels, in_nChannels);
00967 if (strict)
00968 return -1;
00969 }
00970
00971 if (outchannels > out_nChannels) {
00972 jack_error("This device hasn't required output channels outchannels = %d out_nChannels = %d", outchannels, out_nChannels);
00973 if (strict)
00974 return -1;
00975 }
00976
00977 if (inchannels == -1) {
00978 jack_log("Setup max in channels = %d", in_nChannels);
00979 inchannels = in_nChannels;
00980 }
00981
00982 if (outchannels == -1) {
00983 jack_log("Setup max out channels = %d", out_nChannels);
00984 outchannels = out_nChannels;
00985 }
00986
00987 return 0;
00988 }
00989
00990 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
00991 {
00992
00993 UInt32 outSize = sizeof(UInt32);
00994 OSStatus err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
00995 if (err != noErr) {
00996 jack_error("Cannot set buffer size %ld", buffer_size);
00997 printError(err);
00998 return -1;
00999 }
01000
01001 return 0;
01002 }
01003
01004 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t samplerate)
01005 {
01006 return SetupSampleRateAux(fDeviceID, samplerate);
01007 }
01008
01009 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t samplerate)
01010 {
01011 OSStatus err = noErr;
01012 UInt32 outSize;
01013 Float64 sampleRate;
01014
01015
01016 outSize = sizeof(Float64);
01017 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &sampleRate);
01018 if (err != noErr) {
01019 jack_error("Cannot get current sample rate");
01020 printError(err);
01021 return -1;
01022 }
01023
01024
01025 if (samplerate != (jack_nframes_t)sampleRate) {
01026 sampleRate = (Float64)samplerate;
01027
01028
01029 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
01030 if (err != noErr) {
01031 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01032 printError(err);
01033 return -1;
01034 }
01035 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &sampleRate);
01036 if (err != noErr) {
01037 jack_error("Cannot set sample rate = %ld", samplerate);
01038 printError(err);
01039 return -1;
01040 }
01041
01042
01043 int count = 0;
01044 while (!fState && count++ < WAIT_COUNTER) {
01045 usleep(100000);
01046 jack_log("Wait count = %d", count);
01047 }
01048
01049
01050 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
01051 }
01052
01053 return 0;
01054 }
01055
01056 int JackCoreAudioDriver::OpenAUHAL(bool capturing,
01057 bool playing,
01058 int inchannels,
01059 int outchannels,
01060 int in_nChannels,
01061 int out_nChannels,
01062 jack_nframes_t buffer_size,
01063 jack_nframes_t samplerate)
01064 {
01065 ComponentResult err1;
01066 UInt32 enableIO;
01067 AudioStreamBasicDescription srcFormat, dstFormat;
01068 AudioDeviceID currAudioDeviceID;
01069 UInt32 size;
01070
01071 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);
01072
01073 if (inchannels == 0 && outchannels == 0) {
01074 jack_error("No input and output channels...");
01075 return -1;
01076 }
01077
01078
01079 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
01080 Component HALOutput = FindNextComponent(NULL, &cd);
01081
01082 err1 = OpenAComponent(HALOutput, &fAUHAL);
01083 if (err1 != noErr) {
01084 jack_error("Error calling OpenAComponent");
01085 printError(err1);
01086 goto error;
01087 }
01088
01089 err1 = AudioUnitInitialize(fAUHAL);
01090 if (err1 != noErr) {
01091 jack_error("Cannot initialize AUHAL unit");
01092 printError(err1);
01093 goto error;
01094 }
01095
01096
01097 if (capturing && inchannels > 0) {
01098 enableIO = 1;
01099 jack_log("Setup AUHAL input on");
01100 } else {
01101 enableIO = 0;
01102 jack_log("Setup AUHAL input off");
01103 }
01104
01105 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
01106 if (err1 != noErr) {
01107 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
01108 printError(err1);
01109 goto error;
01110 }
01111
01112 if (playing && outchannels > 0) {
01113 enableIO = 1;
01114 jack_log("Setup AUHAL output on");
01115 } else {
01116 enableIO = 0;
01117 jack_log("Setup AUHAL output off");
01118 }
01119
01120 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
01121 if (err1 != noErr) {
01122 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO,kAudioUnitScope_Output");
01123 printError(err1);
01124 goto error;
01125 }
01126
01127 size = sizeof(AudioDeviceID);
01128 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
01129 if (err1 != noErr) {
01130 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
01131 printError(err1);
01132 goto error;
01133 } else {
01134 jack_log("AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
01135 }
01136
01137
01138 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
01139 if (err1 != noErr) {
01140 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
01141 printError(err1);
01142 goto error;
01143 }
01144
01145
01146 if (capturing && inchannels > 0) {
01147 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
01148 if (err1 != noErr) {
01149 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01150 printError(err1);
01151 goto error;
01152 }
01153 }
01154
01155 if (playing && outchannels > 0) {
01156 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
01157 if (err1 != noErr) {
01158 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01159 printError(err1);
01160 goto error;
01161 }
01162 }
01163
01164
01165 if (capturing && inchannels > 0 && inchannels < in_nChannels) {
01166 SInt32 chanArr[in_nChannels];
01167 for (int i = 0; i < in_nChannels; i++) {
01168 chanArr[i] = -1;
01169 }
01170 for (int i = 0; i < inchannels; i++) {
01171 chanArr[i] = i;
01172 }
01173 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_nChannels);
01174 if (err1 != noErr) {
01175 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 1");
01176 printError(err1);
01177 goto error;
01178 }
01179 }
01180
01181 if (playing && outchannels > 0 && outchannels < out_nChannels) {
01182 SInt32 chanArr[out_nChannels];
01183 for (int i = 0; i < out_nChannels; i++) {
01184 chanArr[i] = -1;
01185 }
01186 for (int i = 0; i < outchannels; i++) {
01187 chanArr[i] = i;
01188 }
01189 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_nChannels);
01190 if (err1 != noErr) {
01191 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap 0");
01192 printError(err1);
01193 goto error;
01194 }
01195 }
01196
01197
01198 if (capturing && inchannels > 0) {
01199
01200 size = sizeof(AudioStreamBasicDescription);
01201 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &srcFormat, &size);
01202 if (err1 != noErr) {
01203 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01204 printError(err1);
01205 goto error;
01206 }
01207 PrintStreamDesc(&srcFormat);
01208
01209 jack_log("Setup AUHAL input stream converter SR = %ld", samplerate);
01210 srcFormat.mSampleRate = samplerate;
01211 srcFormat.mFormatID = kAudioFormatLinearPCM;
01212 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01213 srcFormat.mBytesPerPacket = sizeof(float);
01214 srcFormat.mFramesPerPacket = 1;
01215 srcFormat.mBytesPerFrame = sizeof(float);
01216 srcFormat.mChannelsPerFrame = inchannels;
01217 srcFormat.mBitsPerChannel = 32;
01218 PrintStreamDesc(&srcFormat);
01219
01220 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
01221
01222 if (err1 != noErr) {
01223 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01224 printError(err1);
01225 goto error;
01226 }
01227 }
01228
01229 if (playing && outchannels > 0) {
01230
01231 size = sizeof(AudioStreamBasicDescription);
01232 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &dstFormat, &size);
01233 if (err1 != noErr) {
01234 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01235 printError(err1);
01236 goto error;
01237 }
01238 PrintStreamDesc(&dstFormat);
01239
01240 jack_log("Setup AUHAL output stream converter SR = %ld", samplerate);
01241 dstFormat.mSampleRate = samplerate;
01242 dstFormat.mFormatID = kAudioFormatLinearPCM;
01243 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01244 dstFormat.mBytesPerPacket = sizeof(float);
01245 dstFormat.mFramesPerPacket = 1;
01246 dstFormat.mBytesPerFrame = sizeof(float);
01247 dstFormat.mChannelsPerFrame = outchannels;
01248 dstFormat.mBitsPerChannel = 32;
01249 PrintStreamDesc(&dstFormat);
01250
01251 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
01252
01253 if (err1 != noErr) {
01254 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01255 printError(err1);
01256 goto error;
01257 }
01258 }
01259
01260
01261 if (inchannels > 0 && outchannels == 0) {
01262 AURenderCallbackStruct output;
01263 output.inputProc = Render;
01264 output.inputProcRefCon = this;
01265 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
01266 if (err1 != noErr) {
01267 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
01268 printError(err1);
01269 goto error;
01270 }
01271 } else {
01272 AURenderCallbackStruct output;
01273 output.inputProc = Render;
01274 output.inputProcRefCon = this;
01275 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
01276 if (err1 != noErr) {
01277 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
01278 printError(err1);
01279 goto error;
01280 }
01281 }
01282
01283 return 0;
01284
01285 error:
01286 CloseAUHAL();
01287 return -1;
01288 }
01289
01290 int JackCoreAudioDriver::SetupBuffers(int inchannels)
01291 {
01292
01293 fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
01294 fJackInputData->mNumberBuffers = inchannels;
01295 for (int i = 0; i < fCaptureChannels; i++) {
01296 fJackInputData->mBuffers[i].mNumberChannels = 1;
01297 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
01298 }
01299 return 0;
01300 }
01301
01302 void JackCoreAudioDriver::DisposeBuffers()
01303 {
01304 if (fJackInputData) {
01305 free(fJackInputData);
01306 fJackInputData = 0;
01307 }
01308 }
01309
01310 void JackCoreAudioDriver::CloseAUHAL()
01311 {
01312 AudioUnitUninitialize(fAUHAL);
01313 CloseComponent(fAUHAL);
01314 }
01315
01316 int JackCoreAudioDriver::AddListeners()
01317 {
01318 OSStatus err = noErr;
01319
01320
01321 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
01322 if (err != noErr) {
01323 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
01324 printError(err);
01325 return -1;
01326 }
01327
01328 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback, this);
01329 if (err != noErr) {
01330 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioHardwarePropertyDevices");
01331 printError(err);
01332 return -1;
01333 }
01334
01335 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
01336 if (err != noErr) {
01337 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01338 printError(err);
01339 return -1;
01340 }
01341
01342 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
01343 if (err != noErr) {
01344 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
01345 printError(err);
01346 return -1;
01347 }
01348
01349 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01350 if (err != noErr) {
01351 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01352 printError(err);
01353 return -1;
01354 }
01355
01356 err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01357 if (err != noErr) {
01358 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01359 printError(err);
01360 return -1;
01361 }
01362
01363 if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
01364 UInt32 outSize = sizeof(float);
01365 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
01366 if (err != noErr) {
01367 jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
01368 printError(err);
01369 }
01370 }
01371
01372 return 0;
01373 }
01374
01375 void JackCoreAudioDriver::RemoveListeners()
01376 {
01377 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
01378 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioHardwarePropertyDevices, DeviceNotificationCallback);
01379 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
01380 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
01381 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
01382 AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
01383 }
01384
01385 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
01386 jack_nframes_t samplerate,
01387 bool capturing,
01388 bool playing,
01389 int inchannels,
01390 int outchannels,
01391 bool monitor,
01392 const char* capture_driver_uid,
01393 const char* playback_driver_uid,
01394 jack_nframes_t capture_latency,
01395 jack_nframes_t playback_latency,
01396 int async_output_latency,
01397 int computation_grain,
01398 bool hogged,
01399 bool clock_drift)
01400 {
01401 int in_nChannels = 0;
01402 int out_nChannels = 0;
01403 char capture_driver_name[256];
01404 char playback_driver_name[256];
01405
01406
01407 fCapturing = capturing;
01408 fPlaying = playing;
01409 fInChannels = inchannels;
01410 fOutChannels = outchannels;
01411 fMonitor = monitor;
01412 strcpy(fCaptureUID, capture_driver_uid);
01413 strcpy(fPlaybackUID, playback_driver_uid);
01414 fCaptureLatency = capture_latency;
01415 fPlaybackLatency = playback_latency;
01416 fIOUsage = float(async_output_latency) / 100.f;
01417 fComputationGrain = float(computation_grain) / 100.f;
01418 fHogged = hogged;
01419 fClockDriftCompensate = clock_drift;
01420
01421 SInt32 major;
01422 SInt32 minor;
01423 Gestalt(gestaltSystemVersionMajor, &major);
01424 Gestalt(gestaltSystemVersionMinor, &minor);
01425
01426
01427 if (major == 10 && minor >= 6) {
01428 CFRunLoopRef theRunLoop = NULL;
01429 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
01430 OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
01431 if (osErr != noErr) {
01432 jack_error("JackCoreAudioDriver::Open kAudioHardwarePropertyRunLoop error");
01433 printError(osErr);
01434 }
01435 }
01436
01437 if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, samplerate) < 0)
01438 goto error;
01439
01440
01441 if (JackAudioDriver::Open(buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0)
01442 goto error;
01443
01444 if (SetupChannels(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, true) < 0)
01445 goto error;
01446
01447 if (SetupBufferSize(buffer_size) < 0)
01448 goto error;
01449
01450 if (SetupSampleRate(samplerate) < 0)
01451 goto error;
01452
01453 if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_nChannels, out_nChannels, buffer_size, samplerate) < 0)
01454 goto error;
01455
01456 if (capturing && inchannels > 0)
01457 if (SetupBuffers(inchannels) < 0)
01458 goto error;
01459
01460 if (AddListeners() < 0)
01461 goto error;
01462
01463
01464 fCaptureChannels = inchannels;
01465 fPlaybackChannels = outchannels;
01466 return noErr;
01467
01468 error:
01469 Close();
01470 return -1;
01471 }
01472
01473 int JackCoreAudioDriver::Close()
01474 {
01475 jack_log("JackCoreAudioDriver::Close");
01476 Stop();
01477 JackAudioDriver::Close();
01478 RemoveListeners();
01479 DisposeBuffers();
01480 CloseAUHAL();
01481 DestroyAggregateDevice();
01482 return 0;
01483 }
01484
01485 int JackCoreAudioDriver::Attach()
01486 {
01487 OSStatus err;
01488 JackPort* port;
01489 jack_port_id_t port_index;
01490 UInt32 size;
01491 Boolean isWritable;
01492 char channel_name[64];
01493 char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
01494 char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
01495 unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
01496
01497 jack_log("JackCoreAudioDriver::Attach fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
01498
01499 for (int i = 0; i < fCaptureChannels; i++) {
01500
01501 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
01502 if (err != noErr)
01503 jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error ");
01504 if (err == noErr && size > 0) {
01505 err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
01506 if (err != noErr)
01507 jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error ");
01508 snprintf(alias, sizeof(alias) - 1, "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
01509 } else {
01510 snprintf(alias, sizeof(alias) - 1, "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
01511 }
01512
01513 snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1);
01514
01515 if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
01516 jack_error("Cannot register port for %s", name);
01517 return -1;
01518 }
01519
01520 size = sizeof(UInt32);
01521 UInt32 value1 = 0;
01522 UInt32 value2 = 0;
01523 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
01524 if (err != noErr)
01525 jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error ");
01526 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
01527 if (err != noErr)
01528 jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error ");
01529
01530 port = fGraphManager->GetPort(port_index);
01531 port->SetAlias(alias);
01532 port->SetLatency(fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency);
01533 fCapturePortList[i] = port_index;
01534 }
01535
01536 port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
01537
01538 for (int i = 0; i < fPlaybackChannels; i++) {
01539
01540 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
01541 if (err != noErr)
01542 jack_log("AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error ");
01543 if (err == noErr && size > 0) {
01544 err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
01545 if (err != noErr)
01546 jack_log("AudioDeviceGetProperty kAudioDevicePropertyChannelName error ");
01547 snprintf(alias, sizeof(alias) - 1, "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
01548 } else {
01549 snprintf(alias, sizeof(alias) - 1, "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
01550 }
01551
01552 snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1);
01553
01554 if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) {
01555 jack_error("Cannot register port for %s", name);
01556 return -1;
01557 }
01558
01559 size = sizeof(UInt32);
01560 UInt32 value1 = 0;
01561 UInt32 value2 = 0;
01562 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
01563 if (err != noErr)
01564 jack_log("AudioDeviceGetProperty kAudioDevicePropertyLatency error ");
01565 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
01566 if (err != noErr)
01567 jack_log("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error ");
01568
01569 port = fGraphManager->GetPort(port_index);
01570 port->SetAlias(alias);
01571
01572 port->SetLatency(fEngineControl->fBufferSize + ((fEngineControl->fSyncMode) ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency);
01573 fPlaybackPortList[i] = port_index;
01574
01575
01576 if (fWithMonitorPorts) {
01577 jack_log("Create monitor port ");
01578 snprintf(name, sizeof(name) - 1, "%s:monitor_%u", fClientControl.fName, i + 1);
01579 if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, fEngineControl->fBufferSize)) == NO_PORT) {
01580 jack_error("Cannot register monitor port for %s", name);
01581 return -1;
01582 } else {
01583 port = fGraphManager->GetPort(port_index);
01584 port->SetAlias(alias);
01585 port->SetLatency(fEngineControl->fBufferSize);
01586 fMonitorPortList[i] = port_index;
01587 }
01588 }
01589 }
01590
01591
01592 for (int i = 0; i < fCaptureChannels; i++) {
01593 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
01594 }
01595
01596 return 0;
01597 }
01598
01599 int JackCoreAudioDriver::Start()
01600 {
01601 jack_log("JackCoreAudioDriver::Start");
01602 JackAudioDriver::Start();
01603
01604
01605
01606
01607
01608
01609
01610 OSStatus err = AudioDeviceAddIOProc(fDeviceID, MeasureCallback, this);
01611
01612 if (err != noErr)
01613 return -1;
01614
01615 err = AudioOutputUnitStart(fAUHAL);
01616 if (err != noErr)
01617 return -1;
01618
01619 if ((err = AudioDeviceStart(fDeviceID, MeasureCallback)) != noErr) {
01620 jack_error("Cannot start MeasureCallback");
01621 printError(err);
01622 return -1;
01623 }
01624
01625
01626 fState = false;
01627 int count = 0;
01628 while (!fState && count++ < WAIT_COUNTER) {
01629 usleep(100000);
01630 jack_log("JackCoreAudioDriver::Start wait count = %d", count);
01631 }
01632
01633 if (count < WAIT_COUNTER) {
01634 jack_info("CoreAudio driver is running...");
01635 return 0;
01636 } else {
01637 jack_error("CoreAudio driver cannot start...");
01638 return -1;
01639 }
01640 }
01641
01642 int JackCoreAudioDriver::Stop()
01643 {
01644 jack_log("JackCoreAudioDriver::Stop");
01645 AudioDeviceStop(fDeviceID, MeasureCallback);
01646
01647
01648
01649
01650
01651
01652
01653 AudioDeviceRemoveIOProc(fDeviceID, MeasureCallback);
01654 return (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
01655 }
01656
01657 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
01658 {
01659 OSStatus err;
01660 UInt32 outSize = sizeof(UInt32);
01661
01662 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, outSize, &buffer_size);
01663 if (err != noErr) {
01664 jack_error("Cannot set buffer size %ld", buffer_size);
01665 printError(err);
01666 return -1;
01667 }
01668
01669 JackAudioDriver::SetBufferSize(buffer_size);
01670
01671
01672 for (int i = 0; i < fCaptureChannels; i++) {
01673 fJackInputData->mBuffers[i].mNumberChannels = 1;
01674 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(float);
01675 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
01676 }
01677
01678 return 0;
01679 }
01680
01681 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
01682 {
01683 pid_t hog_pid;
01684 OSStatus err;
01685
01686 UInt32 propSize = sizeof(hog_pid);
01687 err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
01688 if (err) {
01689 jack_error("Cannot read hog state...");
01690 printError(err);
01691 }
01692
01693 if (hog_pid != getpid()) {
01694 hog_pid = getpid();
01695 err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
01696 if (err != noErr) {
01697 jack_error("Can't hog device = %d because it's being hogged by another program", deviceID);
01698 return false;
01699 }
01700 }
01701
01702 return true;
01703 }
01704
01705 bool JackCoreAudioDriver::TakeHog()
01706 {
01707 OSStatus err = noErr;
01708 AudioObjectID sub_device[32];
01709 UInt32 outSize = sizeof(sub_device);
01710 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
01711
01712 if (err != noErr) {
01713 jack_log("Device does not have subdevices");
01714 return TakeHogAux(fDeviceID, true);
01715 } else {
01716 int num_devices = outSize / sizeof(AudioObjectID);
01717 jack_log("Device does has %d subdevices", num_devices);
01718 for (int i = 0; i < num_devices; i++) {
01719 if (!TakeHogAux(sub_device[i], true)) {
01720 return false;
01721 }
01722 }
01723 return true;
01724 }
01725 }
01726
01727 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
01728 {
01729 UInt32 deviceType, outSize = sizeof(UInt32);
01730 OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
01731
01732 if (err != noErr) {
01733 jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
01734 return false;
01735 } else {
01736 return (deviceType == kAudioDeviceTransportTypeAggregate);
01737 }
01738 }
01739
01740
01741 }
01742
01743
01744 #ifdef __cplusplus
01745 extern "C"
01746 {
01747 #endif
01748
01749 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
01750 {
01751 jack_driver_desc_t *desc;
01752 unsigned int i;
01753 desc = (jack_driver_desc_t*)calloc(1, sizeof(jack_driver_desc_t));
01754
01755 strcpy(desc->name, "coreaudio");
01756 strcpy(desc->desc, "Apple CoreAudio API based audio backend");
01757
01758 desc->nparams = 17;
01759 desc->params = (jack_driver_param_desc_t*)calloc(desc->nparams, sizeof(jack_driver_param_desc_t));
01760
01761 i = 0;
01762 strcpy(desc->params[i].name, "channels");
01763 desc->params[i].character = 'c';
01764 desc->params[i].type = JackDriverParamInt;
01765 desc->params[i].value.ui = -1;
01766 strcpy(desc->params[i].short_desc, "Maximum number of channels");
01767 strcpy(desc->params[i].long_desc, "Maximum number of channels. If -1, max possible number of channels will be used");
01768
01769 i++;
01770 strcpy(desc->params[i].name, "inchannels");
01771 desc->params[i].character = 'i';
01772 desc->params[i].type = JackDriverParamInt;
01773 desc->params[i].value.ui = -1;
01774 strcpy(desc->params[i].short_desc, "Maximum number of input channels");
01775 strcpy(desc->params[i].long_desc, "Maximum number of input channels. If -1, max possible number of input channels will be used");
01776
01777 i++;
01778 strcpy(desc->params[i].name, "outchannels");
01779 desc->params[i].character = 'o';
01780 desc->params[i].type = JackDriverParamInt;
01781 desc->params[i].value.ui = -1;
01782 strcpy(desc->params[i].short_desc, "Maximum number of output channels");
01783 strcpy(desc->params[i].long_desc, "Maximum number of output channels. If -1, max possible number of output channels will be used");
01784
01785 i++;
01786 strcpy(desc->params[i].name, "capture");
01787 desc->params[i].character = 'C';
01788 desc->params[i].type = JackDriverParamString;
01789 strcpy(desc->params[i].short_desc, "Input CoreAudio device name");
01790 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01791
01792 i++;
01793 strcpy(desc->params[i].name, "playback");
01794 desc->params[i].character = 'P';
01795 desc->params[i].type = JackDriverParamString;
01796 strcpy(desc->params[i].short_desc, "Output CoreAudio device name");
01797 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01798
01799 i++;
01800 strcpy (desc->params[i].name, "monitor");
01801 desc->params[i].character = 'm';
01802 desc->params[i].type = JackDriverParamBool;
01803 desc->params[i].value.i = 0;
01804 strcpy(desc->params[i].short_desc, "Provide monitor ports for the output");
01805 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01806
01807 i++;
01808 strcpy(desc->params[i].name, "duplex");
01809 desc->params[i].character = 'D';
01810 desc->params[i].type = JackDriverParamBool;
01811 desc->params[i].value.i = TRUE;
01812 strcpy(desc->params[i].short_desc, "Provide both capture and playback ports");
01813 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01814
01815 i++;
01816 strcpy(desc->params[i].name, "rate");
01817 desc->params[i].character = 'r';
01818 desc->params[i].type = JackDriverParamUInt;
01819 desc->params[i].value.ui = 44100U;
01820 strcpy(desc->params[i].short_desc, "Sample rate");
01821 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01822
01823 i++;
01824 strcpy(desc->params[i].name, "period");
01825 desc->params[i].character = 'p';
01826 desc->params[i].type = JackDriverParamUInt;
01827 desc->params[i].value.ui = 128U;
01828 strcpy(desc->params[i].short_desc, "Frames per period");
01829 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01830
01831 i++;
01832 strcpy(desc->params[i].name, "device");
01833 desc->params[i].character = 'd';
01834 desc->params[i].type = JackDriverParamString;
01835 strcpy(desc->params[i].short_desc, "CoreAudio device name");
01836 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01837
01838 i++;
01839 strcpy(desc->params[i].name, "input-latency");
01840 desc->params[i].character = 'I';
01841 desc->params[i].type = JackDriverParamUInt;
01842 desc->params[i].value.i = 0;
01843 strcpy(desc->params[i].short_desc, "Extra input latency (frames)");
01844 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01845
01846 i++;
01847 strcpy(desc->params[i].name, "output-latency");
01848 desc->params[i].character = 'O';
01849 desc->params[i].type = JackDriverParamUInt;
01850 desc->params[i].value.i = 0;
01851 strcpy(desc->params[i].short_desc, "Extra output latency (frames)");
01852 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01853
01854 i++;
01855 strcpy(desc->params[i].name, "list-devices");
01856 desc->params[i].character = 'l';
01857 desc->params[i].type = JackDriverParamBool;
01858 desc->params[i].value.i = FALSE;
01859 strcpy(desc->params[i].short_desc, "Display available CoreAudio devices");
01860 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01861
01862 i++;
01863 strcpy(desc->params[i].name, "hog");
01864 desc->params[i].character = 'H';
01865 desc->params[i].type = JackDriverParamBool;
01866 desc->params[i].value.i = FALSE;
01867 strcpy(desc->params[i].short_desc, "Take exclusive access of the audio device");
01868 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01869
01870 i++;
01871 strcpy(desc->params[i].name, "async-latency");
01872 desc->params[i].character = 'L';
01873 desc->params[i].type = JackDriverParamUInt;
01874 desc->params[i].value.i = 100;
01875 strcpy(desc->params[i].short_desc, "Extra output latency in asynchronous mode (percent)");
01876 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01877
01878 i++;
01879 strcpy(desc->params[i].name, "grain");
01880 desc->params[i].character = 'G';
01881 desc->params[i].type = JackDriverParamUInt;
01882 desc->params[i].value.i = 100;
01883 strcpy(desc->params[i].short_desc, "Computation grain in RT thread (percent)");
01884 strcpy(desc->params[i].long_desc, desc->params[i].short_desc);
01885
01886 i++;
01887 strcpy(desc->params[i].name, "clock-drift");
01888 desc->params[i].character = 's';
01889 desc->params[i].type = JackDriverParamBool;
01890 desc->params[i].value.i = FALSE;
01891 strcpy(desc->params[i].short_desc, "Clock drift compensation");
01892 strcpy(desc->params[i].long_desc, "Whether to compensate clock drift in dynamically created aggregate device");
01893
01894 return desc;
01895 }
01896
01897 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
01898 {
01899 jack_nframes_t srate = 44100;
01900 jack_nframes_t frames_per_interrupt = 128;
01901 bool capture = false;
01902 bool playback = false;
01903 int chan_in = -1;
01904 int chan_out = -1;
01905 bool monitor = false;
01906 const char* capture_driver_uid = "";
01907 const char* playback_driver_uid = "";
01908 const JSList *node;
01909 const jack_driver_param_t *param;
01910 jack_nframes_t systemic_input_latency = 0;
01911 jack_nframes_t systemic_output_latency = 0;
01912 int async_output_latency = 100;
01913 int computation_grain = -1;
01914 bool hogged = false;
01915 bool clock_drift = false;
01916
01917 for (node = params; node; node = jack_slist_next(node)) {
01918 param = (const jack_driver_param_t *) node->data;
01919
01920 switch (param->character) {
01921
01922 case 'd':
01923 capture_driver_uid = strdup(param->value.str);
01924 playback_driver_uid = strdup(param->value.str);
01925 break;
01926
01927 case 'D':
01928 capture = true;
01929 playback = true;
01930 break;
01931
01932 case 'c':
01933 chan_in = chan_out = (int)param->value.ui;
01934 break;
01935
01936 case 'i':
01937 chan_in = (int)param->value.ui;
01938 break;
01939
01940 case 'o':
01941 chan_out = (int)param->value.ui;
01942 break;
01943
01944 case 'C':
01945 capture = true;
01946 if (strcmp(param->value.str, "none") != 0) {
01947 capture_driver_uid = strdup(param->value.str);
01948 }
01949 break;
01950
01951 case 'P':
01952 playback = true;
01953 if (strcmp(param->value.str, "none") != 0) {
01954 playback_driver_uid = strdup(param->value.str);
01955 }
01956 break;
01957
01958 case 'm':
01959 monitor = param->value.i;
01960 break;
01961
01962 case 'r':
01963 srate = param->value.ui;
01964 break;
01965
01966 case 'p':
01967 frames_per_interrupt = (unsigned int)param->value.ui;
01968 break;
01969
01970 case 'I':
01971 systemic_input_latency = param->value.ui;
01972 break;
01973
01974 case 'O':
01975 systemic_output_latency = param->value.ui;
01976 break;
01977
01978 case 'l':
01979 Jack::DisplayDeviceNames();
01980 break;
01981
01982 case 'H':
01983 hogged = true;
01984 break;
01985
01986 case 'L':
01987 async_output_latency = param->value.ui;
01988 break;
01989
01990 case 'G':
01991 computation_grain = param->value.ui;
01992 break;
01993
01994 case 's':
01995 clock_drift = true;
01996 break;
01997 }
01998 }
01999
02000
02001 if (!capture && !playback) {
02002 capture = true;
02003 playback = true;
02004 }
02005
02006 Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
02007 if (driver->Open(frames_per_interrupt, srate, capture, playback, chan_in, chan_out, monitor, capture_driver_uid,
02008 playback_driver_uid, systemic_input_latency, systemic_output_latency, async_output_latency, computation_grain, hogged, clock_drift) == 0) {
02009 return driver;
02010 } else {
02011 delete driver;
02012 return NULL;
02013 }
02014 }
02015
02016 #ifdef __cplusplus
02017 }
02018 #endif
02019
02020