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