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