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