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 "JackLockedEngine.h"
00030 #include "JackAC3Encoder.h"
00031
00032 #include <sstream>
00033 #include <iostream>
00034 #include <CoreServices/CoreServices.h>
00035 #include <CoreFoundation/CFNumber.h>
00036
00037 namespace Jack
00038 {
00039
00040 static void Print4CharCode(const char* msg, long c)
00041 {
00042 UInt32 __4CC_number = (c);
00043 char __4CC_string[5];
00044 *((SInt32*)__4CC_string) = EndianU32_NtoB(__4CC_number);
00045 __4CC_string[4] = 0;
00046 jack_log("%s'%s'", (msg), __4CC_string);
00047 }
00048
00049 static void PrintStreamDesc(AudioStreamBasicDescription *inDesc)
00050 {
00051 jack_log("- - - - - - - - - - - - - - - - - - - -");
00052 jack_log(" Sample Rate:%f", inDesc->mSampleRate);
00053 jack_log(" Format ID:%.*s", (int)sizeof(inDesc->mFormatID), (char*)&inDesc->mFormatID);
00054 jack_log(" Format Flags:%lX", inDesc->mFormatFlags);
00055 jack_log(" Bytes per Packet:%ld", inDesc->mBytesPerPacket);
00056 jack_log(" Frames per Packet:%ld", inDesc->mFramesPerPacket);
00057 jack_log(" Bytes per Frame:%ld", inDesc->mBytesPerFrame);
00058 jack_log(" Channels per Frame:%ld", inDesc->mChannelsPerFrame);
00059 jack_log(" Bits per Channel:%ld", inDesc->mBitsPerChannel);
00060 jack_log("- - - - - - - - - - - - - - - - - - - -");
00061 }
00062
00063 static void printError(OSStatus err)
00064 {
00065 switch (err) {
00066 case kAudioHardwareNoError:
00067 jack_log("error code : kAudioHardwareNoError");
00068 break;
00069 case kAudioConverterErr_FormatNotSupported:
00070 jack_log("error code : kAudioConverterErr_FormatNotSupported");
00071 break;
00072 case kAudioConverterErr_OperationNotSupported:
00073 jack_log("error code : kAudioConverterErr_OperationNotSupported");
00074 break;
00075 case kAudioConverterErr_PropertyNotSupported:
00076 jack_log("error code : kAudioConverterErr_PropertyNotSupported");
00077 break;
00078 case kAudioConverterErr_InvalidInputSize:
00079 jack_log("error code : kAudioConverterErr_InvalidInputSize");
00080 break;
00081 case kAudioConverterErr_InvalidOutputSize:
00082 jack_log("error code : kAudioConverterErr_InvalidOutputSize");
00083 break;
00084 case kAudioConverterErr_UnspecifiedError:
00085 jack_log("error code : kAudioConverterErr_UnspecifiedError");
00086 break;
00087 case kAudioConverterErr_BadPropertySizeError:
00088 jack_log("error code : kAudioConverterErr_BadPropertySizeError");
00089 break;
00090 case kAudioConverterErr_RequiresPacketDescriptionsError:
00091 jack_log("error code : kAudioConverterErr_RequiresPacketDescriptionsError");
00092 break;
00093 case kAudioConverterErr_InputSampleRateOutOfRange:
00094 jack_log("error code : kAudioConverterErr_InputSampleRateOutOfRange");
00095 break;
00096 case kAudioConverterErr_OutputSampleRateOutOfRange:
00097 jack_log("error code : kAudioConverterErr_OutputSampleRateOutOfRange");
00098 break;
00099 case kAudioHardwareNotRunningError:
00100 jack_log("error code : kAudioHardwareNotRunningError");
00101 break;
00102 case kAudioHardwareUnknownPropertyError:
00103 jack_log("error code : kAudioHardwareUnknownPropertyError");
00104 break;
00105 case kAudioHardwareIllegalOperationError:
00106 jack_log("error code : kAudioHardwareIllegalOperationError");
00107 break;
00108 case kAudioHardwareBadDeviceError:
00109 jack_log("error code : kAudioHardwareBadDeviceError");
00110 break;
00111 case kAudioHardwareBadStreamError:
00112 jack_log("error code : kAudioHardwareBadStreamError");
00113 break;
00114 case kAudioDeviceUnsupportedFormatError:
00115 jack_log("error code : kAudioDeviceUnsupportedFormatError");
00116 break;
00117 case kAudioDevicePermissionsError:
00118 jack_log("error code : kAudioDevicePermissionsError");
00119 break;
00120 case kAudioHardwareBadObjectError:
00121 jack_log("error code : kAudioHardwareBadObjectError");
00122 break;
00123 case kAudioHardwareUnsupportedOperationError:
00124 jack_log("error code : kAudioHardwareUnsupportedOperationError");
00125 break;
00126 default:
00127 Print4CharCode("error code : unknown ", err);
00128 break;
00129 }
00130 }
00131
00132 static bool CheckAvailableDeviceName(const char* device_name, AudioDeviceID* device_id)
00133 {
00134 UInt32 size;
00135 Boolean isWritable;
00136 int i, deviceNum;
00137 OSStatus err;
00138
00139 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00140 if (err != noErr) {
00141 return false;
00142 }
00143
00144 deviceNum = size / sizeof(AudioDeviceID);
00145 AudioDeviceID devices[deviceNum];
00146
00147 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00148 if (err != noErr) {
00149 return false;
00150 }
00151
00152 for (i = 0; i < deviceNum; i++) {
00153 char device_name_aux[256];
00154
00155 size = 256;
00156 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name_aux);
00157 if (err != noErr) {
00158 return false;
00159 }
00160
00161 if (strncmp(device_name_aux, device_name, strlen(device_name)) == 0) {
00162 *device_id = devices[i];
00163 return true;
00164 }
00165 }
00166
00167 return false;
00168 }
00169
00170 static bool CheckAvailableDevice(AudioDeviceID device_id)
00171 {
00172 UInt32 size;
00173 Boolean isWritable;
00174 int i, deviceNum;
00175 OSStatus err;
00176
00177 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00178 if (err != noErr) {
00179 return false;
00180 }
00181
00182 deviceNum = size / sizeof(AudioDeviceID);
00183 AudioDeviceID devices[deviceNum];
00184
00185 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00186 if (err != noErr) {
00187 return false;
00188 }
00189
00190 for (i = 0; i < deviceNum; i++) {
00191 if (device_id == devices[i]) {
00192 return true;
00193 }
00194 }
00195
00196 return false;
00197 }
00198
00199 static OSStatus DisplayDeviceNames()
00200 {
00201 UInt32 size;
00202 Boolean isWritable;
00203 int i, deviceNum;
00204 OSStatus err;
00205 CFStringRef UIname;
00206
00207 err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &size, &isWritable);
00208 if (err != noErr) {
00209 return err;
00210 }
00211
00212 deviceNum = size / sizeof(AudioDeviceID);
00213 AudioDeviceID devices[deviceNum];
00214
00215 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &size, devices);
00216 if (err != noErr) {
00217 return err;
00218 }
00219
00220 for (i = 0; i < deviceNum; i++) {
00221 char device_name[256];
00222 char internal_name[256];
00223
00224 size = sizeof(CFStringRef);
00225 UIname = NULL;
00226 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00227 if (err == noErr) {
00228 CFStringGetCString(UIname, internal_name, 256, CFStringGetSystemEncoding());
00229 } else {
00230 goto error;
00231 }
00232
00233 size = 256;
00234 err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &size, device_name);
00235 if (err != noErr) {
00236 return err;
00237 }
00238
00239 jack_info("Device ID = \'%d\' name = \'%s\', internal name = \'%s\' (to be used as -C, -P, or -d parameter)", devices[i], device_name, internal_name);
00240 }
00241
00242 return noErr;
00243
00244 error:
00245 if (UIname != NULL) {
00246 CFRelease(UIname);
00247 }
00248 return err;
00249 }
00250
00251 static CFStringRef GetDeviceName(AudioDeviceID id)
00252 {
00253 UInt32 size = sizeof(CFStringRef);
00254 CFStringRef UIname;
00255 OSStatus err = AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceUID, &size, &UIname);
00256 return (err == noErr) ? UIname : NULL;
00257 }
00258
00259 static void ParseChannelList(const string& list, vector<int>& result, int max_chan)
00260 {
00261 stringstream ss(list);
00262 string token;
00263 int chan;
00264
00265 while (ss >> token) {
00266 istringstream ins;
00267 ins.str(token);
00268 ins >> chan;
00269 if (chan < 0 || chan >= max_chan) {
00270 jack_error("Ignore incorrect channel mapping value = %d", chan);
00271 } else {
00272 result.push_back(chan);
00273 }
00274 }
00275 }
00276
00277 OSStatus JackCoreAudioDriver::Render(void* inRefCon,
00278 AudioUnitRenderActionFlags* ioActionFlags,
00279 const AudioTimeStamp* inTimeStamp,
00280 UInt32 inBusNumber,
00281 UInt32 inNumberFrames,
00282 AudioBufferList* ioData)
00283 {
00284 return static_cast<JackCoreAudioDriver*>(inRefCon)->Render(ioActionFlags, inTimeStamp, ioData);
00285 }
00286
00287 OSStatus JackCoreAudioDriver::Render(AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, AudioBufferList* ioData)
00288 {
00289 fActionFags = ioActionFlags;
00290 fCurrentTime = inTimeStamp;
00291 fDriverOutputData = ioData;
00292
00293
00294 if (set_threaded_log_function()) {
00295
00296 jack_log("JackCoreAudioDriver::Render : set_threaded_log_function");
00297 JackMachThread::GetParams(pthread_self(), &fEngineControl->fPeriod, &fEngineControl->fComputation, &fEngineControl->fConstraint);
00298
00299 if (fComputationGrain > 0) {
00300 jack_log("JackCoreAudioDriver::Render : RT thread computation setup to %d percent of period", int(fComputationGrain * 100));
00301 fEngineControl->fComputation = fEngineControl->fPeriod * fComputationGrain;
00302 }
00303 }
00304
00305
00306 fState = true;
00307
00308 CycleTakeBeginTime();
00309
00310 if (Process() < 0) {
00311 jack_error("Process error, stopping driver");
00312 NotifyFailure(JackFailure | JackBackendError, "Process error, stopping driver");
00313 Stop();
00314 kill(JackTools::GetPID(), SIGINT);
00315 return kAudioHardwareUnsupportedOperationError;
00316 } else {
00317 return noErr;
00318 }
00319 }
00320
00321 int JackCoreAudioDriver::Read()
00322 {
00323 if (fCaptureChannels > 0) {
00324 return (AudioUnitRender(fAUHAL, fActionFags, fCurrentTime, 1, fEngineControl->fBufferSize, fJackInputData) == noErr) ? 0 : -1;
00325 } else {
00326 return 0;
00327 }
00328 }
00329
00330 int JackCoreAudioDriver::Write()
00331 {
00332 int size = sizeof(jack_default_audio_sample_t) * fEngineControl->fBufferSize;
00333
00334 if (fAC3Encoder) {
00335
00336
00337 jack_default_audio_sample_t* AC3_inputs[MAX_AC3_CHANNELS];
00338 jack_default_audio_sample_t* AC3_outputs[2];
00339 for (int i = 0; i < fPlaybackChannels; i++) {
00340 AC3_inputs[i] = GetOutputBuffer(i);
00341
00342 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) == 0) {
00343 memset(AC3_inputs[i], 0, size);
00344 }
00345 }
00346 AC3_outputs[0] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[0].mData;
00347 AC3_outputs[1] = (jack_default_audio_sample_t*)fDriverOutputData->mBuffers[1].mData;
00348 fAC3Encoder->Process(AC3_inputs, AC3_outputs, fEngineControl->fBufferSize);
00349
00350 } else {
00351
00352
00353 for (int i = 0; i < fPlaybackChannels; i++) {
00354 if (fGraphManager->GetConnectionsNum(fPlaybackPortList[i]) > 0) {
00355 jack_default_audio_sample_t* buffer = GetOutputBuffer(i);
00356 memcpy((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, buffer, size);
00357
00358 if (fWithMonitorPorts && fGraphManager->GetConnectionsNum(fMonitorPortList[i]) > 0) {
00359 memcpy(GetMonitorBuffer(i), buffer, size);
00360 }
00361 } else {
00362 memset((jack_default_audio_sample_t*)fDriverOutputData->mBuffers[i].mData, 0, size);
00363 }
00364 }
00365 }
00366 return 0;
00367 }
00368
00369 OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
00370 UInt32 inChannel,
00371 Boolean isInput,
00372 AudioDevicePropertyID inPropertyID,
00373 void* inClientData)
00374 {
00375 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00376
00377 switch (inPropertyID) {
00378
00379 case kAudioDevicePropertyNominalSampleRate: {
00380 jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
00381
00382 Float64 tmp_sample_rate;
00383 UInt32 outSize = sizeof(Float64);
00384 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
00385 if (err != noErr) {
00386 jack_error("Cannot get current sample rate");
00387 printError(err);
00388 } else {
00389 jack_log("JackCoreAudioDriver::SRNotificationCallback : checked sample rate = %f", tmp_sample_rate);
00390 }
00391 driver->fState = true;
00392 break;
00393 }
00394 }
00395
00396 return noErr;
00397 }
00398
00399 OSStatus JackCoreAudioDriver::BSNotificationCallback(AudioDeviceID inDevice,
00400 UInt32 inChannel,
00401 Boolean isInput,
00402 AudioDevicePropertyID inPropertyID,
00403 void* inClientData)
00404 {
00405 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00406
00407 switch (inPropertyID) {
00408
00409 case kAudioDevicePropertyBufferFrameSize: {
00410 jack_log("JackCoreAudioDriver::BSNotificationCallback kAudioDevicePropertyBufferFrameSize");
00411
00412 UInt32 tmp_buffer_size;
00413 UInt32 outSize = sizeof(UInt32);
00414 OSStatus err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
00415 if (err != noErr) {
00416 jack_error("Cannot get current buffer size");
00417 printError(err);
00418 } else {
00419 jack_log("JackCoreAudioDriver::BSNotificationCallback : checked buffer size = %d", tmp_buffer_size);
00420 }
00421 driver->fState = true;
00422 break;
00423 }
00424 }
00425
00426 return noErr;
00427 }
00428
00429
00430 OSStatus JackCoreAudioDriver::AudioHardwareNotificationCallback(AudioHardwarePropertyID inPropertyID, void* inClientData)
00431 {
00432 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00433
00434 switch (inPropertyID) {
00435
00436 case kAudioHardwarePropertyDevices: {
00437 jack_log("JackCoreAudioDriver::AudioHardwareNotificationCallback kAudioHardwarePropertyDevices");
00438 DisplayDeviceNames();
00439 AudioDeviceID captureID, playbackID;
00440 if (CheckAvailableDevice(driver->fDeviceID) ||
00441 (CheckAvailableDeviceName(driver->fCaptureUID, &captureID)
00442 && CheckAvailableDeviceName(driver->fPlaybackUID, &playbackID))) {
00443
00444 }
00445 break;
00446 }
00447 }
00448
00449 return noErr;
00450 }
00451
00452 OSStatus JackCoreAudioDriver::DeviceNotificationCallback(AudioDeviceID inDevice,
00453 UInt32 inChannel,
00454 Boolean isInput,
00455 AudioDevicePropertyID inPropertyID,
00456 void* inClientData)
00457 {
00458 JackCoreAudioDriver* driver = (JackCoreAudioDriver*)inClientData;
00459
00460 switch (inPropertyID) {
00461
00462 case kAudioDevicePropertyDeviceIsRunning: {
00463 UInt32 isrunning = 0;
00464 UInt32 outsize = sizeof(UInt32);
00465 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsRunning, &outsize, &isrunning) == noErr) {
00466 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsRunning = %d", isrunning);
00467 }
00468 break;
00469 }
00470
00471 case kAudioDevicePropertyDeviceIsAlive: {
00472 UInt32 isalive = 0;
00473 UInt32 outsize = sizeof(UInt32);
00474 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceIsAlive, &outsize, &isalive) == noErr) {
00475 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceIsAlive = %d", isalive);
00476 }
00477 break;
00478 }
00479
00480 case kAudioDevicePropertyDeviceHasChanged: {
00481 UInt32 hachanged = 0;
00482 UInt32 outsize = sizeof(UInt32);
00483 if (AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyDeviceHasChanged, &outsize, &hachanged) == noErr) {
00484 jack_log("JackCoreAudioDriver::DeviceNotificationCallback kAudioDevicePropertyDeviceHasChanged = %d", hachanged);
00485 }
00486 break;
00487 }
00488
00489 case kAudioDeviceProcessorOverload: {
00490 jack_error("DeviceNotificationCallback kAudioDeviceProcessorOverload");
00491 jack_time_t cur_time = GetMicroSeconds();
00492 driver->NotifyXRun(cur_time, float(cur_time - driver->fBeginDateUst));
00493 break;
00494 }
00495
00496 case kAudioDevicePropertyStreamConfiguration: {
00497 jack_error("Cannot handle kAudioDevicePropertyStreamConfiguration : server will quit...");
00498 driver->NotifyFailure(JackFailure | JackBackendError, "Another application has changed the device configuration");
00499 driver->CloseAUHAL();
00500 kill(JackTools::GetPID(), SIGINT);
00501 return kAudioHardwareUnsupportedOperationError;
00502 }
00503
00504 case kAudioDevicePropertyNominalSampleRate: {
00505 Float64 sample_rate = 0;
00506 UInt32 outsize = sizeof(Float64);
00507 OSStatus err = AudioDeviceGetProperty(driver->fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
00508 if (err != noErr) {
00509 return kAudioHardwareUnsupportedOperationError;
00510 }
00511
00512 char device_name[256];
00513 const char* digidesign_name = "Digidesign";
00514 driver->GetDeviceNameFromID(driver->fDeviceID, device_name);
00515
00516 if (sample_rate != driver->fEngineControl->fSampleRate) {
00517
00518
00519 if (strncmp(device_name, digidesign_name, 10) == 0) {
00520
00521 jack_log("JackCoreAudioDriver::DeviceNotificationCallback Digidesign HW = %s", device_name);
00522
00523
00524 sample_rate = driver->fEngineControl->fSampleRate;
00525 err = AudioDeviceSetProperty(driver->fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outsize, &sample_rate);
00526 if (err != noErr) {
00527 jack_error("Cannot set sample rate = %f", sample_rate);
00528 printError(err);
00529 } else {
00530 jack_log("JackCoreAudioDriver::DeviceNotificationCallback : set sample rate = %f", sample_rate);
00531 }
00532
00533
00534 outsize = sizeof(Float64);
00535 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outsize, &sample_rate);
00536 if (err != noErr) {
00537 jack_error("Cannot get current sample rate");
00538 printError(err);
00539 } else {
00540 jack_log("JackCoreAudioDriver::DeviceNotificationCallback : checked sample rate = %f", sample_rate);
00541 }
00542 return noErr;
00543
00544 } else {
00545 driver->NotifyFailure(JackFailure | JackBackendError, "Another application has changed the sample rate");
00546 driver->CloseAUHAL();
00547 kill(JackTools::GetPID(), SIGINT);
00548 return kAudioHardwareUnsupportedOperationError;
00549 }
00550 }
00551 }
00552
00553 }
00554 return noErr;
00555 }
00556
00557 OSStatus JackCoreAudioDriver::GetDeviceIDFromUID(const char* UID, AudioDeviceID* id)
00558 {
00559 UInt32 size = sizeof(AudioValueTranslation);
00560 CFStringRef inIUD = CFStringCreateWithCString(NULL, UID, CFStringGetSystemEncoding());
00561 AudioValueTranslation value = { &inIUD, sizeof(CFStringRef), id, sizeof(AudioDeviceID) };
00562
00563 if (inIUD == NULL) {
00564 return kAudioHardwareUnspecifiedError;
00565 } else {
00566 OSStatus res = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &size, &value);
00567 CFRelease(inIUD);
00568 jack_log("JackCoreAudioDriver::GetDeviceIDFromUID %s %ld", UID, *id);
00569 return (*id == kAudioDeviceUnknown) ? kAudioHardwareBadDeviceError : res;
00570 }
00571 }
00572
00573 OSStatus JackCoreAudioDriver::GetDefaultDevice(AudioDeviceID* id)
00574 {
00575 OSStatus res;
00576 UInt32 theSize = sizeof(UInt32);
00577 AudioDeviceID inDefault;
00578 AudioDeviceID outDefault;
00579
00580 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
00581 return res;
00582 }
00583
00584 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
00585 return res;
00586 }
00587
00588 jack_log("JackCoreAudioDriver::GetDefaultDevice : input = %ld output = %ld", inDefault, outDefault);
00589
00590
00591 if (inDefault != outDefault) {
00592 jack_error("Default input and output devices are not the same !!");
00593 return kAudioHardwareBadDeviceError;
00594 } else if (inDefault == 0) {
00595 jack_error("Default input and output devices are null !!");
00596 return kAudioHardwareBadDeviceError;
00597 } else {
00598 *id = inDefault;
00599 return noErr;
00600 }
00601 }
00602
00603 OSStatus JackCoreAudioDriver::GetDefaultInputDevice(AudioDeviceID* id)
00604 {
00605 OSStatus res;
00606 UInt32 theSize = sizeof(UInt32);
00607 AudioDeviceID inDefault;
00608
00609 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &theSize, &inDefault)) != noErr) {
00610 return res;
00611 }
00612
00613 if (inDefault == 0) {
00614 jack_error("Error default input device is 0, will take 'Built-in'...");
00615 if (CheckAvailableDeviceName("Built-in Microphone", id)
00616 || CheckAvailableDeviceName("Built-in Line", id)) {
00617 jack_log("JackCoreAudioDriver::GetDefaultInputDevice : output = %ld", *id);
00618 return noErr;
00619 } else {
00620 jack_error("Cannot find any input device to use...");
00621 return -1;
00622 }
00623 }
00624 jack_log("JackCoreAudioDriver::GetDefaultInputDevice : input = %ld ", inDefault);
00625 *id = inDefault;
00626 return noErr;
00627 }
00628
00629 OSStatus JackCoreAudioDriver::GetDefaultOutputDevice(AudioDeviceID* id)
00630 {
00631 OSStatus res;
00632 UInt32 theSize = sizeof(UInt32);
00633 AudioDeviceID outDefault;
00634
00635 if ((res = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &theSize, &outDefault)) != noErr) {
00636 return res;
00637 }
00638
00639 if (outDefault == 0) {
00640 jack_error("Error default ouput device is 0, will take 'Built-in'...");
00641 if (CheckAvailableDeviceName("Built-in Output", id)) {
00642 jack_log("JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", *id);
00643 return noErr;
00644 } else {
00645 jack_error("Cannot find any output device to use...");
00646 return -1;
00647 }
00648 }
00649 jack_log("JackCoreAudioDriver::GetDefaultOutputDevice : output = %ld", outDefault);
00650 *id = outDefault;
00651 return noErr;
00652 }
00653
00654 OSStatus JackCoreAudioDriver::GetDeviceNameFromID(AudioDeviceID id, char* name)
00655 {
00656 UInt32 size = 256;
00657 return AudioDeviceGetProperty(id, 0, false, kAudioDevicePropertyDeviceName, &size, name);
00658 }
00659
00660 OSStatus JackCoreAudioDriver::GetTotalChannels(AudioDeviceID device, int& channelCount, bool isInput)
00661 {
00662 OSStatus err = noErr;
00663 UInt32 outSize;
00664 Boolean outWritable;
00665
00666 channelCount = 0;
00667 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, &outWritable);
00668 if (err == noErr) {
00669 int stream_count = outSize / sizeof(AudioBufferList);
00670 jack_log("JackCoreAudioDriver::GetTotalChannels stream_count = %d", stream_count);
00671 AudioBufferList bufferList[stream_count];
00672 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize, bufferList);
00673 if (err == noErr) {
00674 for (uint i = 0; i < bufferList->mNumberBuffers; i++) {
00675 channelCount += bufferList->mBuffers[i].mNumberChannels;
00676 jack_log("JackCoreAudioDriver::GetTotalChannels stream = %d channels = %d", i, bufferList->mBuffers[i].mNumberChannels);
00677 }
00678 }
00679 }
00680 return err;
00681 }
00682
00683 OSStatus JackCoreAudioDriver::GetStreamLatencies(AudioDeviceID device, bool isInput, vector<int>& latencies)
00684 {
00685 OSStatus err = noErr;
00686 UInt32 outSize1, outSize2, outSize3;
00687 Boolean outWritable;
00688
00689 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, &outWritable);
00690 if (err == noErr) {
00691 int stream_count = outSize1 / sizeof(UInt32);
00692 AudioStreamID streamIDs[stream_count];
00693 AudioBufferList bufferList[stream_count];
00694 UInt32 streamLatency;
00695 outSize2 = sizeof(UInt32);
00696
00697 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreams, &outSize1, streamIDs);
00698 if (err != noErr) {
00699 jack_error("GetStreamLatencies kAudioDevicePropertyStreams err = %d", err);
00700 return err;
00701 }
00702
00703 err = AudioDeviceGetPropertyInfo(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, &outWritable);
00704 if (err != noErr) {
00705 jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
00706 return err;
00707 }
00708
00709 for (int i = 0; i < stream_count; i++) {
00710 err = AudioStreamGetProperty(streamIDs[i], 0, kAudioStreamPropertyLatency, &outSize2, &streamLatency);
00711 if (err != noErr) {
00712 jack_error("GetStreamLatencies kAudioStreamPropertyLatency err = %d", err);
00713 return err;
00714 }
00715 err = AudioDeviceGetProperty(device, 0, isInput, kAudioDevicePropertyStreamConfiguration, &outSize3, bufferList);
00716 if (err != noErr) {
00717 jack_error("GetStreamLatencies kAudioDevicePropertyStreamConfiguration err = %d", err);
00718 return err;
00719 }
00720
00721 for (uint k = 0; k < bufferList->mBuffers[i].mNumberChannels; k++) {
00722 latencies.push_back(streamLatency);
00723 }
00724 }
00725 }
00726 return err;
00727 }
00728
00729 bool JackCoreAudioDriver::IsDigitalDevice(AudioDeviceID device)
00730 {
00731 OSStatus err = noErr;
00732 UInt32 outSize1;
00733 bool is_digital = false;
00734
00735
00736 AudioObjectPropertyAddress streamsAddress = { kAudioDevicePropertyStreams, kAudioDevicePropertyScopeOutput, kAudioObjectPropertyElementMaster };
00737 err = AudioObjectGetPropertyDataSize(device, &streamsAddress, 0, NULL, &outSize1);
00738 if (err != noErr) {
00739 jack_error("IsDigitalDevice kAudioDevicePropertyStreams err = %d", err);
00740 return false;
00741 }
00742
00743 int stream_count = outSize1 / sizeof(AudioStreamID);
00744 AudioStreamID streamIDs[stream_count];
00745
00746 err = AudioObjectGetPropertyData(device, &streamsAddress, 0, NULL, &outSize1, streamIDs);
00747
00748 if (err != noErr) {
00749 jack_error("IsDigitalDevice kAudioDevicePropertyStreams list err = %d", err);
00750 return false;
00751 }
00752
00753 AudioObjectPropertyAddress physicalFormatsAddress = { kAudioStreamPropertyAvailablePhysicalFormats, kAudioObjectPropertyScopeGlobal, 0 };
00754
00755 for (int i = 0; i < stream_count ; i++) {
00756
00757
00758 int format_num = 0;
00759
00760
00761 err = AudioObjectGetPropertyDataSize(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1);
00762
00763 if (err != noErr) {
00764 jack_error("IsDigitalDevice kAudioStreamPropertyAvailablePhysicalFormats err = %d", err);
00765 return false;
00766 }
00767
00768 format_num = outSize1 / sizeof(AudioStreamRangedDescription);
00769 AudioStreamRangedDescription format_list[format_num];
00770
00771 err = AudioObjectGetPropertyData(streamIDs[i], &physicalFormatsAddress, 0, NULL, &outSize1, format_list);
00772
00773 if (err != noErr) {
00774 jack_error("IsDigitalDevice could not get the list of streamformats err = %d", err);
00775 return false;
00776 }
00777
00778
00779 for (int j = 0; j < format_num; j++) {
00780
00781 PrintStreamDesc(&format_list[j].mFormat);
00782
00783 if (format_list[j].mFormat.mFormatID == 'IAC3' ||
00784 format_list[j].mFormat.mFormatID == 'iac3' ||
00785 format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
00786 format_list[j].mFormat.mFormatID == kAudioFormatAC3)
00787 {
00788 is_digital = true;
00789 break;
00790 }
00791 }
00792 }
00793
00794 return is_digital;
00795 }
00796
00797 JackCoreAudioDriver::JackCoreAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table)
00798 : JackAudioDriver(name, alias, engine, table),
00799 fAC3Encoder(NULL),
00800 fJackInputData(NULL),
00801 fDriverOutputData(NULL),
00802 fPluginID(0),
00803 fState(false),
00804 fHogged(false),
00805 fIOUsage(1.f),
00806 fComputationGrain(-1.f),
00807 fClockDriftCompensate(false),
00808 fDigitalPlayback(false)
00809 {}
00810
00811 JackCoreAudioDriver::~JackCoreAudioDriver()
00812 {
00813 delete fAC3Encoder;
00814 }
00815
00816 OSStatus JackCoreAudioDriver::DestroyAggregateDevice()
00817 {
00818 OSStatus osErr = noErr;
00819 AudioObjectPropertyAddress pluginAOPA;
00820 pluginAOPA.mSelector = kAudioPlugInDestroyAggregateDevice;
00821 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
00822 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
00823 UInt32 outDataSize;
00824
00825 if (fPluginID > 0) {
00826
00827 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
00828 if (osErr != noErr) {
00829 jack_error("DestroyAggregateDevice : AudioObjectGetPropertyDataSize error");
00830 printError(osErr);
00831 return osErr;
00832 }
00833
00834 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, 0, NULL, &outDataSize, &fDeviceID);
00835 if (osErr != noErr) {
00836 jack_error("DestroyAggregateDevice : AudioObjectGetPropertyData error");
00837 printError(osErr);
00838 return osErr;
00839 }
00840
00841 }
00842
00843 return noErr;
00844 }
00845
00846 OSStatus JackCoreAudioDriver::CreateAggregateDevice(AudioDeviceID captureDeviceID, AudioDeviceID playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00847 {
00848 OSStatus err = noErr;
00849 AudioObjectID sub_device[32];
00850 UInt32 outSize = sizeof(sub_device);
00851
00852 err = AudioDeviceGetProperty(captureDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00853 vector<AudioDeviceID> captureDeviceIDArray;
00854
00855 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device %d", captureDeviceID);
00856
00857 if (err != noErr) {
00858 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device does not have subdevices");
00859 captureDeviceIDArray.push_back(captureDeviceID);
00860 } else {
00861 int num_devices = outSize / sizeof(AudioObjectID);
00862 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input device has %d subdevices", num_devices);
00863 for (int i = 0; i < num_devices; i++) {
00864 jack_log("JackCoreAudioDriver::CreateAggregateDevice : input sub_device %d", sub_device[i]);
00865 captureDeviceIDArray.push_back(sub_device[i]);
00866 }
00867 }
00868
00869 outSize = sizeof(sub_device);
00870 err = AudioDeviceGetProperty(playbackDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
00871 vector<AudioDeviceID> playbackDeviceIDArray;
00872
00873 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device %d", playbackDeviceID);
00874
00875 if (err != noErr) {
00876 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device does not have subdevices");
00877 playbackDeviceIDArray.push_back(playbackDeviceID);
00878 } else {
00879 int num_devices = outSize / sizeof(AudioObjectID);
00880 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output device has %d subdevices", num_devices);
00881 for (int i = 0; i < num_devices; i++) {
00882 jack_log("JackCoreAudioDriver::CreateAggregateDevice : output sub_device %d", sub_device[i]);
00883 playbackDeviceIDArray.push_back(sub_device[i]);
00884 }
00885 }
00886
00887 return CreateAggregateDeviceAux(captureDeviceIDArray, playbackDeviceIDArray, samplerate, outAggregateDevice);
00888 }
00889
00890 OSStatus JackCoreAudioDriver::CreateAggregateDeviceAux(vector<AudioDeviceID> captureDeviceID, vector<AudioDeviceID> playbackDeviceID, jack_nframes_t samplerate, AudioDeviceID* outAggregateDevice)
00891 {
00892 OSStatus osErr = noErr;
00893 UInt32 outSize;
00894 Boolean outWritable;
00895
00896
00897
00898 AudioObjectPropertyAddress theAddressOwned = { kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00899 AudioObjectPropertyAddress theAddressDrift = { kAudioSubDevicePropertyDriftCompensation, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
00900 UInt32 theQualifierDataSize = sizeof(AudioObjectID);
00901 AudioClassID inClass = kAudioSubDeviceClassID;
00902 void* theQualifierData = &inClass;
00903 UInt32 subDevicesNum = 0;
00904
00905
00906
00907
00908 UInt32 keptclockdomain = 0;
00909 UInt32 clockdomain = 0;
00910 outSize = sizeof(UInt32);
00911 bool need_clock_drift_compensation = false;
00912
00913 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00914 if (SetupSampleRateAux(captureDeviceID[i], samplerate) < 0) {
00915 jack_error("CreateAggregateDeviceAux : cannot set SR of input device");
00916 } else {
00917
00918 osErr = AudioDeviceGetProperty(captureDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00919 if (osErr != 0) {
00920 jack_error("CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
00921 printError(osErr);
00922 } else {
00923 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00924 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : input clockdomain = %d", clockdomain);
00925 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00926 jack_error("CreateAggregateDeviceAux : devices do not share the same clock!! clock drift compensation would be needed...");
00927 need_clock_drift_compensation = true;
00928 }
00929 }
00930 }
00931 }
00932
00933 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00934 if (SetupSampleRateAux(playbackDeviceID[i], samplerate) < 0) {
00935 jack_error("CreateAggregateDeviceAux : cannot set SR of output device");
00936 } else {
00937
00938 osErr = AudioDeviceGetProperty(playbackDeviceID[i], 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyClockDomain, &outSize, &clockdomain);
00939 if (osErr != 0) {
00940 jack_error("CreateAggregateDeviceAux : kAudioDevicePropertyClockDomain error");
00941 printError(osErr);
00942 } else {
00943 keptclockdomain = (keptclockdomain == 0) ? clockdomain : keptclockdomain;
00944 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : output clockdomain = %d", clockdomain);
00945 if (clockdomain != 0 && clockdomain != keptclockdomain) {
00946 jack_error("CreateAggregateDeviceAux : devices do not share the same clock!! clock drift compensation would be needed...");
00947 need_clock_drift_compensation = true;
00948 }
00949 }
00950 }
00951 }
00952
00953
00954 if (keptclockdomain == 0) {
00955 need_clock_drift_compensation = true;
00956 }
00957
00958
00959
00960
00961
00962 char device_name[256];
00963 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
00964 GetDeviceNameFromID(captureDeviceID[i], device_name);
00965 jack_info("Separated input = '%s' ", device_name);
00966 }
00967
00968 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
00969 GetDeviceNameFromID(playbackDeviceID[i], device_name);
00970 jack_info("Separated output = '%s' ", device_name);
00971 }
00972
00973 osErr = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyPlugInForBundleID, &outSize, &outWritable);
00974 if (osErr != noErr) {
00975 jack_error("CreateAggregateDeviceAux : AudioHardwareGetPropertyInfo kAudioHardwarePropertyPlugInForBundleID error");
00976 printError(osErr);
00977 return osErr;
00978 }
00979
00980 AudioValueTranslation pluginAVT;
00981
00982 CFStringRef inBundleRef = CFSTR("com.apple.audio.CoreAudio");
00983
00984 pluginAVT.mInputData = &inBundleRef;
00985 pluginAVT.mInputDataSize = sizeof(inBundleRef);
00986 pluginAVT.mOutputData = &fPluginID;
00987 pluginAVT.mOutputDataSize = sizeof(fPluginID);
00988
00989 osErr = AudioHardwareGetProperty(kAudioHardwarePropertyPlugInForBundleID, &outSize, &pluginAVT);
00990 if (osErr != noErr) {
00991 jack_error("CreateAggregateDeviceAux : AudioHardwareGetProperty kAudioHardwarePropertyPlugInForBundleID error");
00992 printError(osErr);
00993 return osErr;
00994 }
00995
00996
00997
00998
00999
01000 CFMutableDictionaryRef aggDeviceDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
01001
01002 CFStringRef AggregateDeviceNameRef = CFSTR("JackDuplex");
01003 CFStringRef AggregateDeviceUIDRef = CFSTR("com.grame.JackDuplex");
01004
01005
01006 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceNameKey), AggregateDeviceNameRef);
01007
01008
01009 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceUIDKey), AggregateDeviceUIDRef);
01010
01011
01012 int value = 1;
01013 CFNumberRef AggregateDeviceNumberRef = CFNumberCreate(NULL, kCFNumberIntType, &value);
01014
01015 SInt32 system;
01016 Gestalt(gestaltSystemVersion, &system);
01017
01018 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : system version = %x limit = %x", system, 0x00001054);
01019
01020
01021 if (system < 0x00001054) {
01022 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : public aggregate device....");
01023 } else {
01024 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : private aggregate device....");
01025 CFDictionaryAddValue(aggDeviceDict, CFSTR(kAudioAggregateDeviceIsPrivateKey), AggregateDeviceNumberRef);
01026 }
01027
01028
01029 CFMutableArrayRef subDevicesArrayClock = NULL;
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072 CFMutableArrayRef subDevicesArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
01073
01074 vector<CFStringRef> captureDeviceUID;
01075 for (UInt32 i = 0; i < captureDeviceID.size(); i++) {
01076 CFStringRef ref = GetDeviceName(captureDeviceID[i]);
01077 if (ref == NULL) {
01078 return -1;
01079 }
01080 captureDeviceUID.push_back(ref);
01081
01082 CFArrayAppendValue(subDevicesArray, ref);
01083 }
01084
01085 vector<CFStringRef> playbackDeviceUID;
01086 for (UInt32 i = 0; i < playbackDeviceID.size(); i++) {
01087 CFStringRef ref = GetDeviceName(playbackDeviceID[i]);
01088 if (ref == NULL) {
01089 return -1;
01090 }
01091 playbackDeviceUID.push_back(ref);
01092
01093 CFArrayAppendValue(subDevicesArray, ref);
01094 }
01095
01096
01097
01098
01099
01100 AudioObjectPropertyAddress pluginAOPA;
01101 pluginAOPA.mSelector = kAudioPlugInCreateAggregateDevice;
01102 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01103 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01104 UInt32 outDataSize;
01105
01106 osErr = AudioObjectGetPropertyDataSize(fPluginID, &pluginAOPA, 0, NULL, &outDataSize);
01107 if (osErr != noErr) {
01108 jack_error("CreateAggregateDeviceAux : AudioObjectGetPropertyDataSize error");
01109 printError(osErr);
01110 goto error;
01111 }
01112
01113 osErr = AudioObjectGetPropertyData(fPluginID, &pluginAOPA, sizeof(aggDeviceDict), &aggDeviceDict, &outDataSize, outAggregateDevice);
01114 if (osErr != noErr) {
01115 jack_error("CreateAggregateDeviceAux : AudioObjectGetPropertyData error");
01116 printError(osErr);
01117 goto error;
01118 }
01119
01120
01121
01122 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01123
01124
01125
01126
01127
01128 pluginAOPA.mSelector = kAudioAggregateDevicePropertyFullSubDeviceList;
01129 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01130 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01131 outDataSize = sizeof(CFMutableArrayRef);
01132 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &subDevicesArray);
01133 if (osErr != noErr) {
01134 jack_error("CreateAggregateDeviceAux : AudioObjectSetPropertyData for sub-device list error");
01135 printError(osErr);
01136 goto error;
01137 }
01138
01139
01140 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01141
01142
01143
01144
01145
01146
01147
01148 pluginAOPA.mSelector = kAudioAggregateDevicePropertyMasterSubDevice;
01149 pluginAOPA.mScope = kAudioObjectPropertyScopeGlobal;
01150 pluginAOPA.mElement = kAudioObjectPropertyElementMaster;
01151 outDataSize = sizeof(CFStringRef);
01152 osErr = AudioObjectSetPropertyData(*outAggregateDevice, &pluginAOPA, 0, NULL, outDataSize, &captureDeviceUID[0]);
01153 if (osErr != noErr) {
01154 jack_error("CreateAggregateDeviceAux : AudioObjectSetPropertyData for master device error");
01155 printError(osErr);
01156 goto error;
01157 }
01158
01159
01160 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01161
01162
01163
01164
01165 if (fClockDriftCompensate) {
01166 if (need_clock_drift_compensation) {
01167 jack_info("Clock drift compensation activated...");
01168
01169
01170 osErr = AudioObjectGetPropertyDataSize(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize);
01171 if (osErr != noErr) {
01172 jack_error("CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
01173 printError(osErr);
01174 }
01175
01176
01177 subDevicesNum = outSize / sizeof(AudioObjectID);
01178 jack_info("JackCoreAudioDriver::CreateAggregateDeviceAux clock drift compensation, number of sub-devices = %d", subDevicesNum);
01179 AudioObjectID subDevices[subDevicesNum];
01180 outSize = sizeof(subDevices);
01181
01182 osErr = AudioObjectGetPropertyData(*outAggregateDevice, &theAddressOwned, theQualifierDataSize, theQualifierData, &outSize, subDevices);
01183 if (osErr != noErr) {
01184 jack_error("CreateAggregateDeviceAux kAudioObjectPropertyOwnedObjects error");
01185 printError(osErr);
01186 }
01187
01188
01189 for (UInt32 index = 0; index < subDevicesNum; ++index) {
01190 UInt32 theDriftCompensationValue = 1;
01191 osErr = AudioObjectSetPropertyData(subDevices[index], &theAddressDrift, 0, NULL, sizeof(UInt32), &theDriftCompensationValue);
01192 if (osErr != noErr) {
01193 jack_error("CreateAggregateDeviceAux kAudioSubDevicePropertyDriftCompensation error");
01194 printError(osErr);
01195 }
01196 }
01197 } else {
01198 jack_info("Clock drift compensation was asked but is not needed (devices use the same clock domain)");
01199 }
01200 }
01201
01202
01203 CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, false);
01204
01205
01206
01207
01208
01209
01210 CFRelease(AggregateDeviceNumberRef);
01211
01212
01213 CFRelease(aggDeviceDict);
01214 CFRelease(subDevicesArray);
01215
01216 if (subDevicesArrayClock) {
01217 CFRelease(subDevicesArrayClock);
01218 }
01219
01220
01221 for (UInt32 i = 0; i < captureDeviceUID.size(); i++) {
01222 CFRelease(captureDeviceUID[i]);
01223 }
01224
01225 for (UInt32 i = 0; i < playbackDeviceUID.size(); i++) {
01226 CFRelease(playbackDeviceUID[i]);
01227 }
01228
01229 jack_log("JackCoreAudioDriver::CreateAggregateDeviceAux : new aggregate device %ld", *outAggregateDevice);
01230 return noErr;
01231
01232 error:
01233 DestroyAggregateDevice();
01234 return -1;
01235 }
01236
01237 int JackCoreAudioDriver::SetupDevices(const char* capture_driver_uid,
01238 const char* playback_driver_uid,
01239 char* capture_driver_name,
01240 char* playback_driver_name,
01241 jack_nframes_t samplerate,
01242 bool ac3_encoding)
01243 {
01244 capture_driver_name[0] = 0;
01245 playback_driver_name[0] = 0;
01246
01247
01248 if (strcmp(capture_driver_uid, "") != 0 && strcmp(playback_driver_uid, "") != 0) {
01249 jack_log("JackCoreAudioDriver::SetupDevices : duplex");
01250
01251
01252 if (strcmp(capture_driver_uid, playback_driver_uid) == 0) {
01253
01254 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
01255 jack_log("JackCoreAudioDriver::SetupDevices : will take default in/out");
01256 if (GetDefaultDevice(&fDeviceID) != noErr) {
01257 jack_error("Cannot open default device");
01258 return -1;
01259 }
01260 }
01261
01262 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr || GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
01263 jack_error("Cannot get device name from device ID");
01264 return -1;
01265 }
01266
01267 if (fHogged) {
01268 if (!TakeHogAux(fDeviceID, false)) {
01269 jack_error("Cannot take hog mode");
01270 }
01271 if (ac3_encoding) {
01272 fDigitalPlayback = IsDigitalDevice(fDeviceID);
01273 }
01274 }
01275
01276 } else {
01277
01278
01279 AudioDeviceID captureID = -1;
01280 AudioDeviceID playbackID = -1;
01281
01282 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
01283 jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
01284 if (GetDefaultInputDevice(&captureID) != noErr) {
01285 jack_error("Cannot open default input device");
01286 return -1;
01287 }
01288 }
01289
01290 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
01291 jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
01292 if (GetDefaultOutputDevice(&playbackID) != noErr) {
01293 jack_error("Cannot open default output device");
01294 return -1;
01295 }
01296 }
01297
01298 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
01299 return -1;
01300 }
01301
01302 GetDeviceNameFromID(captureID, fCaptureUID);
01303 GetDeviceNameFromID(playbackID, fPlaybackUID);
01304
01305 if (fHogged) {
01306 if (!TakeHogAux(captureID, true)) {
01307 jack_error("Cannot take hog mode for capture device");
01308 }
01309 if (!TakeHogAux(playbackID, false)) {
01310 jack_error("Cannot take hog mode for playback device");
01311 }
01312 if (ac3_encoding) {
01313 fDigitalPlayback = IsDigitalDevice(playbackID);
01314 }
01315 }
01316
01317 }
01318
01319
01320 } else if (strcmp(capture_driver_uid, "") != 0) {
01321
01322 jack_log("JackCoreAudioDriver::SetupDevices : capture only");
01323 if (GetDeviceIDFromUID(capture_driver_uid, &fDeviceID) != noErr) {
01324 jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
01325 if (GetDefaultInputDevice(&fDeviceID) != noErr) {
01326 jack_error("Cannot open default input device");
01327 return -1;
01328 }
01329 }
01330
01331 if (GetDeviceNameFromID(fDeviceID, capture_driver_name) != noErr) {
01332 jack_error("Cannot get device name from device ID");
01333 return -1;
01334 }
01335
01336 if (fHogged) {
01337 if (!TakeHogAux(fDeviceID, true)) {
01338 jack_error("Cannot take hog mode for capture device");
01339 }
01340 }
01341
01342
01343 } else if (strcmp(playback_driver_uid, "") != 0) {
01344
01345 jack_log("JackCoreAudioDriver::SetupDevices : playback only");
01346 if (GetDeviceIDFromUID(playback_driver_uid, &fDeviceID) != noErr) {
01347 jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
01348 if (GetDefaultOutputDevice(&fDeviceID) != noErr) {
01349 jack_error("Cannot open default output device");
01350 return -1;
01351 }
01352 }
01353
01354 if (GetDeviceNameFromID(fDeviceID, playback_driver_name) != noErr) {
01355 jack_error("Cannot get device name from device ID");
01356 return -1;
01357 }
01358
01359 if (fHogged) {
01360 if (!TakeHogAux(fDeviceID, false)) {
01361 jack_error("Cannot take hog mode for playback device");
01362 }
01363 if (ac3_encoding) {
01364 fDigitalPlayback = IsDigitalDevice(fDeviceID);
01365 }
01366 }
01367
01368
01369 } else {
01370 jack_log("JackCoreAudioDriver::SetupDevices : default driver");
01371 if (GetDefaultDevice(&fDeviceID) != noErr) {
01372 jack_error("Cannot open default device in duplex mode, so aggregate default input and default output");
01373
01374
01375 AudioDeviceID captureID = -1;
01376 AudioDeviceID playbackID = -1;
01377
01378 if (GetDeviceIDFromUID(capture_driver_uid, &captureID) != noErr) {
01379 jack_log("JackCoreAudioDriver::SetupDevices : will take default input");
01380 if (GetDefaultInputDevice(&captureID) != noErr) {
01381 jack_error("Cannot open default input device");
01382 return -1;
01383 }
01384 }
01385
01386 if (GetDeviceIDFromUID(playback_driver_uid, &playbackID) != noErr) {
01387 jack_log("JackCoreAudioDriver::SetupDevices : will take default output");
01388 if (GetDefaultOutputDevice(&playbackID) != noErr) {
01389 jack_error("Cannot open default output device");
01390 return -1;
01391 }
01392 }
01393
01394 if (CreateAggregateDevice(captureID, playbackID, samplerate, &fDeviceID) != noErr) {
01395 return -1;
01396 }
01397
01398 GetDeviceNameFromID(captureID, fCaptureUID);
01399 GetDeviceNameFromID(playbackID, fPlaybackUID);
01400
01401 if (fHogged) {
01402 if (!TakeHogAux(captureID, true)) {
01403 jack_error("Cannot take hog mode for capture device");
01404 }
01405 if (!TakeHogAux(playbackID, false)) {
01406 jack_error("Cannot take hog mode for playback device");
01407 }
01408 if (ac3_encoding) {
01409 fDigitalPlayback = IsDigitalDevice(playbackID);
01410 }
01411 }
01412 }
01413 }
01414
01415 return 0;
01416 }
01417
01418
01419
01420
01421 int JackCoreAudioDriver::SetupChannels(bool capturing, bool playing, int& inchannels, int& outchannels, int& in_maxChannels, int& out_maxChannels, bool strict)
01422 {
01423 OSStatus err = noErr;
01424
01425 jack_log("JackCoreAudioDriver::SetupChannels : fDeviceID = %d", fDeviceID);
01426
01427 if (capturing) {
01428 err = GetTotalChannels(fDeviceID, in_maxChannels, true);
01429 if (err != noErr) {
01430 jack_error("SetupChannels : cannot get input channel number");
01431 printError(err);
01432 return -1;
01433 } else {
01434 jack_log("JackCoreAudioDriver::SetupChannels : max input channels : %d", in_maxChannels);
01435 }
01436 }
01437
01438 if (playing) {
01439 err = GetTotalChannels(fDeviceID, out_maxChannels, false);
01440 if (err != noErr) {
01441 jack_error("Cannot get output channel number");
01442 printError(err);
01443 return -1;
01444 } else {
01445 jack_log("JackCoreAudioDriver::SetupChannels : max output channels : %d", out_maxChannels);
01446 }
01447 }
01448
01449 if (inchannels > in_maxChannels) {
01450 jack_error("This device hasn't required input channels inchannels = %d in_maxChannels = %d", inchannels, in_maxChannels);
01451 if (strict) {
01452 return -1;
01453 }
01454 }
01455
01456 if (outchannels > out_maxChannels) {
01457 jack_error("This device hasn't required output channels outchannels = %d out_maxChannels = %d", outchannels, out_maxChannels);
01458 if (strict) {
01459 return -1;
01460 }
01461 }
01462
01463 if (inchannels == -1) {
01464 jack_log("JackCoreAudioDriver::SetupChannels : setup max in channels = %d", in_maxChannels);
01465 inchannels = in_maxChannels;
01466 }
01467
01468 if (outchannels == -1) {
01469 jack_log("JackCoreAudioDriver::SetupChannels : setup max out channels = %d", out_maxChannels);
01470 outchannels = out_maxChannels;
01471 }
01472
01473 return 0;
01474 }
01475
01476 int JackCoreAudioDriver::SetupBufferSize(jack_nframes_t buffer_size)
01477 {
01478
01479 OSStatus err = noErr;
01480 UInt32 tmp_buffer_size = buffer_size;
01481 UInt32 outSize = sizeof(UInt32);
01482
01483 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
01484 if (err != noErr) {
01485 jack_error("Cannot get buffer size %ld", buffer_size);
01486 printError(err);
01487 return -1;
01488 } else {
01489 jack_log("JackCoreAudioDriver::SetupBufferSize : current buffer size = %ld", tmp_buffer_size);
01490 }
01491
01492
01493 if (buffer_size != tmp_buffer_size) {
01494 tmp_buffer_size = buffer_size;
01495
01496
01497 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback, this);
01498 if (err != noErr) {
01499 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyBufferFrameSize");
01500 printError(err);
01501 return -1;
01502 }
01503
01504
01505 int count = 0;
01506 fState = false;
01507
01508 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, outSize, &tmp_buffer_size);
01509 if (err != noErr) {
01510 jack_error("SetupBufferSize : cannot set buffer size = %ld", tmp_buffer_size);
01511 printError(err);
01512 goto error;
01513 }
01514
01515 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
01516 usleep(100000);
01517 jack_log("JackCoreAudioDriver::SetupBufferSize : wait count = %d", count);
01518 }
01519
01520 if (count >= WAIT_NOTIFICATION_COUNTER) {
01521 jack_error("Did not get buffer size notification...");
01522 goto error;
01523 }
01524
01525
01526 outSize = sizeof(UInt32);
01527 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyBufferFrameSize, &outSize, &tmp_buffer_size);
01528 if (err != noErr) {
01529 jack_error("Cannot get current buffer size");
01530 printError(err);
01531 } else {
01532 jack_log("JackCoreAudioDriver::SetupBufferSize : checked buffer size = %ld", tmp_buffer_size);
01533 }
01534
01535
01536 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
01537 }
01538
01539 return 0;
01540
01541 error:
01542
01543
01544 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyBufferFrameSize, BSNotificationCallback);
01545 return -1;
01546 }
01547
01548 int JackCoreAudioDriver::SetupSampleRate(jack_nframes_t sample_rate)
01549 {
01550 return SetupSampleRateAux(fDeviceID, sample_rate);
01551 }
01552
01553 int JackCoreAudioDriver::SetupSampleRateAux(AudioDeviceID inDevice, jack_nframes_t sample_rate)
01554 {
01555 OSStatus err = noErr;
01556 UInt32 outSize;
01557 Float64 tmp_sample_rate;
01558
01559
01560 outSize = sizeof(Float64);
01561 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
01562 if (err != noErr) {
01563 jack_error("Cannot get current sample rate");
01564 printError(err);
01565 return -1;
01566 } else {
01567 jack_log("JackCoreAudioDriver::SetupSampleRateAux : current sample rate = %f", tmp_sample_rate);
01568 }
01569
01570
01571 if (sample_rate != (jack_nframes_t)tmp_sample_rate) {
01572 tmp_sample_rate = (Float64)sample_rate;
01573
01574
01575 err = AudioDeviceAddPropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback, this);
01576 if (err != noErr) {
01577 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01578 printError(err);
01579 return -1;
01580 }
01581
01582
01583 int count = 0;
01584 fState = false;
01585
01586 err = AudioDeviceSetProperty(inDevice, NULL, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, outSize, &tmp_sample_rate);
01587 if (err != noErr) {
01588 jack_error("Cannot set sample rate = %ld", sample_rate);
01589 printError(err);
01590 goto error;
01591 }
01592
01593 while (!fState && count++ < WAIT_NOTIFICATION_COUNTER) {
01594 usleep(100000);
01595 jack_log("JackCoreAudioDriver::SetupSampleRateAux : wait count = %d", count);
01596 }
01597
01598 if (count >= WAIT_NOTIFICATION_COUNTER) {
01599 jack_error("Did not get sample rate notification...");
01600 goto error;
01601 }
01602
01603
01604 outSize = sizeof(Float64);
01605 err = AudioDeviceGetProperty(inDevice, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyNominalSampleRate, &outSize, &tmp_sample_rate);
01606 if (err != noErr) {
01607 jack_error("Cannot get current sample rate");
01608 printError(err);
01609 } else {
01610 jack_log("JackCoreAudioDriver::SetupSampleRateAux : checked sample rate = %f", tmp_sample_rate);
01611 }
01612
01613
01614 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
01615 }
01616
01617 return 0;
01618
01619 error:
01620
01621
01622 AudioDeviceRemovePropertyListener(inDevice, 0, true, kAudioDevicePropertyNominalSampleRate, SRNotificationCallback);
01623 return -1;
01624 }
01625
01626 int JackCoreAudioDriver::OpenAUHAL(bool capturing,
01627 bool playing,
01628 int inchannels,
01629 int outchannels,
01630 int in_maxChannels,
01631 int out_maxChannels,
01632 const vector<int>& chan_in_list,
01633 const vector<int>& chan_out_list,
01634 jack_nframes_t buffer_size,
01635 jack_nframes_t sample_rate)
01636 {
01637 ComponentResult err1;
01638 UInt32 enableIO;
01639 AudioStreamBasicDescription srcFormat, dstFormat;
01640 AudioDeviceID currAudioDeviceID;
01641 UInt32 size;
01642
01643 jack_log("JackCoreAudioDriver::OpenAUHAL : capturing = %d playing = %d inchannels = %d outchannels = %d in_maxChannels = %d out_maxChannels = %d chan_in_list = %d chan_out_list = %d",
01644 capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, chan_in_list.size(), chan_out_list.size());
01645
01646 if (inchannels == 0 && outchannels == 0) {
01647 jack_error("No input and output channels...");
01648 return -1;
01649 }
01650
01651
01652 #ifdef MAC_OS_X_VERSION_10_5
01653 ComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
01654 Component HALOutput = FindNextComponent(NULL, &cd);
01655 err1 = OpenAComponent(HALOutput, &fAUHAL);
01656 if (err1 != noErr) {
01657 jack_error("Error calling OpenAComponent");
01658 printError(err1);
01659 goto error;
01660 }
01661 #else
01662 AudioComponentDescription cd = {kAudioUnitType_Output, kAudioUnitSubType_HALOutput, kAudioUnitManufacturer_Apple, 0, 0};
01663 AudioComponent HALOutput = AudioComponentFindNext(NULL, &cd);
01664 err1 = AudioComponentInstanceNew(HALOutput, &fAUHAL);
01665 if (err1 != noErr) {
01666 jack_error("Error calling AudioComponentInstanceNew");
01667 printError(err1);
01668 goto error;
01669 }
01670 #endif
01671
01672 err1 = AudioUnitInitialize(fAUHAL);
01673 if (err1 != noErr) {
01674 jack_error("Cannot initialize AUHAL unit");
01675 printError(err1);
01676 goto error;
01677 }
01678
01679
01680 if (capturing && inchannels > 0) {
01681 enableIO = 1;
01682 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input on");
01683 } else {
01684 enableIO = 0;
01685 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input off");
01686 }
01687
01688 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(enableIO));
01689 if (err1 != noErr) {
01690 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input");
01691 printError(err1);
01692 goto error;
01693 }
01694
01695 if (playing && outchannels > 0) {
01696 enableIO = 1;
01697 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output on");
01698 } else {
01699 enableIO = 0;
01700 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output off");
01701 }
01702
01703 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(enableIO));
01704 if (err1 != noErr) {
01705 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output");
01706 printError(err1);
01707 goto error;
01708 }
01709
01710 size = sizeof(AudioDeviceID);
01711 err1 = AudioUnitGetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &currAudioDeviceID, &size);
01712 if (err1 != noErr) {
01713 jack_error("Error calling AudioUnitGetProperty - kAudioOutputUnitProperty_CurrentDevice");
01714 printError(err1);
01715 goto error;
01716 } else {
01717 jack_log("JackCoreAudioDriver::OpenAUHAL : AudioUnitGetPropertyCurrentDevice = %d", currAudioDeviceID);
01718 }
01719
01720
01721 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &fDeviceID, sizeof(AudioDeviceID));
01722 if (err1 != noErr) {
01723 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_CurrentDevice");
01724 printError(err1);
01725 goto error;
01726 }
01727
01728
01729 if (capturing && inchannels > 0) {
01730 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 1, (UInt32*)&buffer_size, sizeof(UInt32));
01731 if (err1 != noErr) {
01732 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01733 printError(err1);
01734 goto error;
01735 }
01736 }
01737
01738 if (playing && outchannels > 0) {
01739 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, (UInt32*)&buffer_size, sizeof(UInt32));
01740 if (err1 != noErr) {
01741 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_MaximumFramesPerSlice");
01742 printError(err1);
01743 goto error;
01744 }
01745 }
01746
01747
01748 if (capturing && inchannels > 0 && inchannels <= in_maxChannels) {
01749 SInt32 chanArr[in_maxChannels];
01750 for (int i = 0; i < in_maxChannels; i++) {
01751 chanArr[i] = -1;
01752 }
01753
01754 if (chan_in_list.size() > 0) {
01755 for (uint i = 0; i < chan_in_list.size(); i++) {
01756 int chan = chan_in_list[i];
01757 if (chan < in_maxChannels) {
01758
01759 chanArr[chan] = i;
01760 jack_info("Input channel = %d ==> JACK input port = %d", chan, i);
01761 } else {
01762 jack_info("Error input channel number is incorrect : %d", chan);
01763 goto error;
01764 }
01765 }
01766 } else {
01767 for (int i = 0; i < inchannels; i++) {
01768 chanArr[i] = i;
01769 jack_info("Input channel = %d ==> JACK input port = %d", chanArr[i], i);
01770 }
01771 }
01772
01773 AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap , kAudioUnitScope_Input, 1, chanArr, sizeof(SInt32) * in_maxChannels);
01774 if (err1 != noErr) {
01775 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for input");
01776 printError(err1);
01777 goto error;
01778 }
01779 }
01780
01781
01782 if (playing && outchannels > 0 && outchannels <= out_maxChannels) {
01783 SInt32 chanArr[out_maxChannels];
01784 for (int i = 0; i < out_maxChannels; i++) {
01785 chanArr[i] = -1;
01786 }
01787
01788 if (chan_out_list.size() > 0) {
01789 for (uint i = 0; i < chan_out_list.size(); i++) {
01790 int chan = chan_out_list[i];
01791 if (chan < out_maxChannels) {
01792
01793 chanArr[chan] = i;
01794 jack_info("JACK output port = %d ==> output channel = %d", i, chan);
01795 } else {
01796 jack_info("Error output channel number is incorrect : %d", chan);
01797 goto error;
01798 }
01799 }
01800 } else {
01801 for (int i = 0; i < outchannels; i++) {
01802 chanArr[i] = i;
01803 jack_info("JACK output port = %d ==> output channel = %d", i, chanArr[i]);
01804 }
01805 }
01806
01807 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_ChannelMap, kAudioUnitScope_Output, 0, chanArr, sizeof(SInt32) * out_maxChannels);
01808 if (err1 != noErr) {
01809 jack_error("Error calling AudioUnitSetProperty - kAudioOutputUnitProperty_ChannelMap for output");
01810 printError(err1);
01811 goto error;
01812 }
01813 }
01814
01815
01816 if (capturing && inchannels > 0) {
01817
01818 size = sizeof(AudioStreamBasicDescription);
01819 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, &size);
01820 if (err1 != noErr) {
01821 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01822 printError(err1);
01823 goto error;
01824 }
01825 PrintStreamDesc(&srcFormat);
01826
01827 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL input stream converter SR = %ld", sample_rate);
01828 srcFormat.mSampleRate = sample_rate;
01829 srcFormat.mFormatID = kAudioFormatLinearPCM;
01830 srcFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01831 srcFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
01832 srcFormat.mFramesPerPacket = 1;
01833 srcFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
01834 srcFormat.mChannelsPerFrame = inchannels;
01835 srcFormat.mBitsPerChannel = 32;
01836 PrintStreamDesc(&srcFormat);
01837
01838 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &srcFormat, sizeof(AudioStreamBasicDescription));
01839 if (err1 != noErr) {
01840 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Output");
01841 printError(err1);
01842 goto error;
01843 }
01844 }
01845
01846 if (playing && outchannels > 0) {
01847
01848 size = sizeof(AudioStreamBasicDescription);
01849 err1 = AudioUnitGetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, &size);
01850 if (err1 != noErr) {
01851 jack_error("Error calling AudioUnitGetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01852 printError(err1);
01853 goto error;
01854 }
01855 PrintStreamDesc(&dstFormat);
01856
01857 jack_log("JackCoreAudioDriver::OpenAUHAL : setup AUHAL output stream converter SR = %ld", sample_rate);
01858 dstFormat.mSampleRate = sample_rate;
01859 dstFormat.mFormatID = kAudioFormatLinearPCM;
01860 dstFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked | kLinearPCMFormatFlagIsNonInterleaved;
01861 dstFormat.mBytesPerPacket = sizeof(jack_default_audio_sample_t);
01862 dstFormat.mFramesPerPacket = 1;
01863 dstFormat.mBytesPerFrame = sizeof(jack_default_audio_sample_t);
01864 dstFormat.mChannelsPerFrame = outchannels;
01865 dstFormat.mBitsPerChannel = 32;
01866 PrintStreamDesc(&dstFormat);
01867
01868 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(AudioStreamBasicDescription));
01869 if (err1 != noErr) {
01870 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_StreamFormat kAudioUnitScope_Input");
01871 printError(err1);
01872 goto error;
01873 }
01874 }
01875
01876
01877 if (inchannels > 0 && outchannels == 0) {
01878 AURenderCallbackStruct output;
01879 output.inputProc = Render;
01880 output.inputProcRefCon = this;
01881 err1 = AudioUnitSetProperty(fAUHAL, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &output, sizeof(output));
01882 if (err1 != noErr) {
01883 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 1");
01884 printError(err1);
01885 goto error;
01886 }
01887 } else {
01888 AURenderCallbackStruct output;
01889 output.inputProc = Render;
01890 output.inputProcRefCon = this;
01891 err1 = AudioUnitSetProperty(fAUHAL, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &output, sizeof(output));
01892 if (err1 != noErr) {
01893 jack_error("Error calling AudioUnitSetProperty - kAudioUnitProperty_SetRenderCallback 0");
01894 printError(err1);
01895 goto error;
01896 }
01897 }
01898
01899 return 0;
01900
01901 error:
01902 CloseAUHAL();
01903 return -1;
01904 }
01905
01906 int JackCoreAudioDriver::SetupBuffers(int inchannels)
01907 {
01908
01909 fJackInputData = (AudioBufferList*)malloc(sizeof(UInt32) + inchannels * sizeof(AudioBuffer));
01910 fJackInputData->mNumberBuffers = inchannels;
01911 for (int i = 0; i < inchannels; i++) {
01912 fJackInputData->mBuffers[i].mNumberChannels = 1;
01913 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
01914 }
01915 return 0;
01916 }
01917
01918 void JackCoreAudioDriver::DisposeBuffers()
01919 {
01920 if (fJackInputData) {
01921 free(fJackInputData);
01922 fJackInputData = 0;
01923 }
01924 }
01925
01926 void JackCoreAudioDriver::CloseAUHAL()
01927 {
01928 AudioOutputUnitStop(fAUHAL);
01929 AudioUnitUninitialize(fAUHAL);
01930 CloseComponent(fAUHAL);
01931 }
01932
01933 int JackCoreAudioDriver::AddListeners()
01934 {
01935 OSStatus err = noErr;
01936
01937
01938 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback, this);
01939 if (err != noErr) {
01940 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDeviceProcessorOverload");
01941 printError(err);
01942 return -1;
01943 }
01944
01945 err = AudioHardwareAddPropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback, this);
01946 if (err != noErr) {
01947 jack_error("Error calling AudioHardwareAddPropertyListener with kAudioHardwarePropertyDevices");
01948 printError(err);
01949 return -1;
01950 }
01951
01952 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback, this);
01953 if (err != noErr) {
01954 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyNominalSampleRate");
01955 printError(err);
01956 return -1;
01957 }
01958
01959 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback, this);
01960 if (err != noErr) {
01961 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsRunning");
01962 printError(err);
01963 return -1;
01964 }
01965
01966 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback, this);
01967 if (err != noErr) {
01968 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceIsAlive");
01969 printError(err);
01970 return -1;
01971 }
01972
01973 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback, this);
01974 if (err != noErr) {
01975 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyDeviceHasChanged");
01976 printError(err);
01977 return -1;
01978 }
01979
01980 err = AudioDeviceAddPropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01981 if (err != noErr) {
01982 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01983 printError(err);
01984 return -1;
01985 }
01986
01987 err = AudioDeviceAddPropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback, this);
01988 if (err != noErr) {
01989 jack_error("Error calling AudioDeviceAddPropertyListener with kAudioDevicePropertyStreamConfiguration");
01990 printError(err);
01991 return -1;
01992 }
01993
01994 if (!fEngineControl->fSyncMode && fIOUsage != 1.f) {
01995 UInt32 outSize = sizeof(float);
01996 err = AudioDeviceSetProperty(fDeviceID, NULL, 0, false, kAudioDevicePropertyIOCycleUsage, outSize, &fIOUsage);
01997 if (err != noErr) {
01998 jack_error("Error calling AudioDeviceSetProperty kAudioDevicePropertyIOCycleUsage");
01999 printError(err);
02000 }
02001 }
02002
02003 return 0;
02004 }
02005
02006 void JackCoreAudioDriver::RemoveListeners()
02007 {
02008 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDeviceProcessorOverload, DeviceNotificationCallback);
02009 AudioHardwareRemovePropertyListener(kAudioHardwarePropertyDevices, AudioHardwareNotificationCallback);
02010 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyNominalSampleRate, DeviceNotificationCallback);
02011 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsRunning, DeviceNotificationCallback);
02012 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceIsAlive, DeviceNotificationCallback);
02013 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyDeviceHasChanged, DeviceNotificationCallback);
02014 AudioDeviceRemovePropertyListener(fDeviceID, 0, true, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
02015 AudioDeviceRemovePropertyListener(fDeviceID, 0, false, kAudioDevicePropertyStreamConfiguration, DeviceNotificationCallback);
02016 }
02017
02018 int JackCoreAudioDriver::Open(jack_nframes_t buffer_size,
02019 jack_nframes_t sample_rate,
02020 bool capturing,
02021 bool playing,
02022 int inchannels,
02023 int outchannels,
02024 const char* chan_in_list,
02025 const char* chan_out_list,
02026 bool monitor,
02027 const char* capture_driver_uid,
02028 const char* playback_driver_uid,
02029 jack_nframes_t capture_latency,
02030 jack_nframes_t playback_latency,
02031 int async_output_latency,
02032 int computation_grain,
02033 bool hogged,
02034 bool clock_drift,
02035 bool ac3_encoding,
02036 int ac3_bitrate,
02037 bool ac3_lfe)
02038 {
02039 int in_maxChannels = 0;
02040 int out_maxChannels = 0;
02041 char capture_driver_name[256];
02042 char playback_driver_name[256];
02043
02044 fCaptureLatency = capture_latency;
02045 fPlaybackLatency = playback_latency;
02046 fIOUsage = float(async_output_latency) / 100.f;
02047 fComputationGrain = float(computation_grain) / 100.f;
02048 fHogged = hogged;
02049 fClockDriftCompensate = clock_drift;
02050
02051 SInt32 major;
02052 SInt32 minor;
02053 Gestalt(gestaltSystemVersionMajor, &major);
02054 Gestalt(gestaltSystemVersionMinor, &minor);
02055
02056 vector<int> parsed_chan_in_list;
02057 vector<int> parsed_chan_out_list;
02058
02059
02060 if (major == 10 && minor >= 6) {
02061 CFRunLoopRef theRunLoop = NULL;
02062 AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
02063 OSStatus osErr = AudioObjectSetPropertyData (kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
02064 if (osErr != noErr) {
02065 jack_error("Open kAudioHardwarePropertyRunLoop error");
02066 printError(osErr);
02067 }
02068 }
02069
02070 if (SetupDevices(capture_driver_uid, playback_driver_uid, capture_driver_name, playback_driver_name, sample_rate, ac3_encoding) < 0) {
02071 goto error;
02072 }
02073
02074
02075 if (JackAudioDriver::Open(buffer_size, sample_rate,
02076 capturing, playing,
02077 inchannels, outchannels,
02078 monitor,
02079 capture_driver_name,
02080 playback_driver_name,
02081 capture_latency,
02082 playback_latency) != 0) {
02083 goto error;
02084 }
02085
02086 if (SetupChannels(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, !ac3_encoding) < 0) {
02087 goto error;
02088 }
02089
02090 ParseChannelList(chan_in_list, parsed_chan_in_list, in_maxChannels);
02091 if (parsed_chan_in_list.size() > 0) {
02092 jack_info("Explicit input channel list size = %d", parsed_chan_in_list.size());
02093 inchannels = parsed_chan_in_list.size();
02094 }
02095
02096 ParseChannelList(chan_out_list, parsed_chan_out_list, out_maxChannels);
02097 if (parsed_chan_out_list.size() > 0) {
02098 jack_info("Explicit output channel list size = %d", parsed_chan_out_list.size());
02099 outchannels = parsed_chan_out_list.size();
02100 }
02101
02102 if (SetupBufferSize(buffer_size) < 0) {
02103 goto error;
02104 }
02105
02106 if (SetupSampleRate(sample_rate) < 0) {
02107 goto error;
02108 }
02109
02110 if (ac3_encoding) {
02111
02112 if (!fDigitalPlayback) {
02113 jack_error("AC3 encoding can only be used with a digital device");
02114 goto error;
02115 }
02116
02117 JackAC3EncoderParams params;
02118 memset(¶ms, 0, sizeof(JackAC3EncoderParams));
02119 params.bitrate = ac3_bitrate;
02120 params.channels = outchannels;
02121 params.sample_rate = sample_rate;
02122 params.lfe = ac3_lfe;
02123 fAC3Encoder = new JackAC3Encoder(params);
02124
02125 if (!fAC3Encoder || !fAC3Encoder->Init(sample_rate)) {
02126 jack_error("Cannot allocate or init AC3 encoder");
02127 goto error;
02128 }
02129
02130
02131 fPlaybackChannels = outchannels;
02132 if (ac3_lfe) {
02133 fPlaybackChannels++;
02134 }
02135
02136 if (fPlaybackChannels < 2 || fPlaybackChannels > 6) {
02137 jack_error("AC3 encoder channels must be between 2 and 6");
02138 goto error;
02139 }
02140
02141
02142 outchannels = out_maxChannels = 2;
02143
02144 } else {
02145 fPlaybackChannels = outchannels;
02146 }
02147
02148
02149 fCaptureChannels = inchannels;
02150
02151 if (OpenAUHAL(capturing, playing, inchannels, outchannels, in_maxChannels, out_maxChannels, parsed_chan_in_list, parsed_chan_out_list, buffer_size, sample_rate) < 0) {
02152 goto error;
02153 }
02154
02155 if (capturing && inchannels > 0) {
02156 if (SetupBuffers(inchannels) < 0) {
02157 goto error;
02158 }
02159 }
02160
02161 if (AddListeners() < 0) {
02162 goto error;
02163 }
02164
02165 return noErr;
02166
02167 error:
02168 Close();
02169 return -1;
02170 }
02171
02172 int JackCoreAudioDriver::Close()
02173 {
02174 jack_log("JackCoreAudioDriver::Close");
02175
02176
02177 int res = JackAudioDriver::Close();
02178
02179 RemoveListeners();
02180 DisposeBuffers();
02181 CloseAUHAL();
02182 DestroyAggregateDevice();
02183 return res;
02184 }
02185
02186 void JackCoreAudioDriver::UpdateLatencies()
02187 {
02188 UInt32 size;
02189 OSStatus err;
02190 jack_latency_range_t input_range;
02191 jack_latency_range_t output_range;
02192 jack_latency_range_t monitor_range;
02193
02194
02195 size = sizeof(UInt32);
02196 UInt32 value1 = 0;
02197 UInt32 value2 = 0;
02198 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertyLatency, &size, &value1);
02199 if (err != noErr) {
02200 jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
02201 }
02202 err = AudioDeviceGetProperty(fDeviceID, 0, true, kAudioDevicePropertySafetyOffset, &size, &value2);
02203 if (err != noErr) {
02204 jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
02205 }
02206
02207 input_range.min = input_range.max = fEngineControl->fBufferSize + value1 + value2 + fCaptureLatency;
02208
02209
02210 vector<int> input_latencies;
02211 err = GetStreamLatencies(fDeviceID, true, input_latencies);
02212
02213 for (int i = 0; i < fCaptureChannels; i++) {
02214 if (err != noErr) {
02215 input_range.min += input_latencies[i];
02216 input_range.max += input_latencies[i];
02217 }
02218 fGraphManager->GetPort(fCapturePortList[i])->SetLatencyRange(JackCaptureLatency, &input_range);
02219 }
02220
02221
02222 size = sizeof(UInt32);
02223 value1 = 0;
02224 value2 = 0;
02225 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertyLatency, &size, &value1);
02226 if (err != noErr) {
02227 jack_error("AudioDeviceGetProperty kAudioDevicePropertyLatency error");
02228 }
02229 err = AudioDeviceGetProperty(fDeviceID, 0, false, kAudioDevicePropertySafetyOffset, &size, &value2);
02230 if (err != noErr) {
02231 jack_error("AudioDeviceGetProperty kAudioDevicePropertySafetyOffset error");
02232 }
02233
02234
02235 vector<int> output_latencies;
02236 err = GetStreamLatencies(fDeviceID, false, output_latencies);
02237
02238
02239 output_range.min = output_range.max = fEngineControl->fBufferSize + ((fEngineControl->fSyncMode)
02240 ? 0 : fEngineControl->fBufferSize * fIOUsage) + value1 + value2 + fPlaybackLatency;
02241
02242 for (int i = 0; i < fPlaybackChannels; i++) {
02243 if (err != noErr) {
02244 output_range.min += output_latencies[i];
02245 output_range.max += output_latencies[i];
02246 }
02247 fGraphManager->GetPort(fPlaybackPortList[i])->SetLatencyRange(JackPlaybackLatency, &output_range);
02248
02249
02250 if (fWithMonitorPorts) {
02251 monitor_range.min = monitor_range.max = fEngineControl->fBufferSize;
02252 fGraphManager->GetPort(fMonitorPortList[i])->SetLatencyRange(JackCaptureLatency, &monitor_range);
02253 }
02254 }
02255 }
02256
02257 int JackCoreAudioDriver::Attach()
02258 {
02259 OSStatus err;
02260 JackPort* port;
02261 jack_port_id_t port_index;
02262 UInt32 size;
02263 Boolean isWritable;
02264 char channel_name[64];
02265 char name[REAL_JACK_PORT_NAME_SIZE];
02266 char alias[REAL_JACK_PORT_NAME_SIZE];
02267
02268 jack_log("JackCoreAudioDriver::Attach : fBufferSize %ld fSampleRate %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate);
02269
02270 for (int i = 0; i < fCaptureChannels; i++) {
02271
02272 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, &isWritable);
02273 if (err != noErr) {
02274 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
02275 }
02276 if (err == noErr && size > 0) {
02277 err = AudioDeviceGetProperty(fDeviceID, i + 1, true, kAudioDevicePropertyChannelName, &size, channel_name);
02278 if (err != noErr) {
02279 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
02280 }
02281 snprintf(alias, sizeof(alias), "%s:%s:out_%s%u", fAliasName, fCaptureDriverName, channel_name, i + 1);
02282 } else {
02283 snprintf(alias, sizeof(alias), "%s:%s:out%u", fAliasName, fCaptureDriverName, i + 1);
02284 }
02285
02286 snprintf(name, sizeof(name), "%s:capture_%d", fClientControl.fName, i + 1);
02287
02288 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02289 jack_error("Cannot register port for %s", name);
02290 return -1;
02291 }
02292
02293 port = fGraphManager->GetPort(port_index);
02294 port->SetAlias(alias);
02295 fCapturePortList[i] = port_index;
02296 }
02297
02298 for (int i = 0; i < fPlaybackChannels; i++) {
02299
02300 err = AudioDeviceGetPropertyInfo(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, &isWritable);
02301 if (err != noErr) {
02302 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetPropertyInfo kAudioDevicePropertyChannelName error");
02303 }
02304 if (err == noErr && size > 0) {
02305 err = AudioDeviceGetProperty(fDeviceID, i + 1, false, kAudioDevicePropertyChannelName, &size, channel_name);
02306 if (err != noErr) {
02307 jack_log("JackCoreAudioDriver::Attach : AudioDeviceGetProperty kAudioDevicePropertyChannelName error");
02308 }
02309 snprintf(alias, sizeof(alias), "%s:%s:in_%s%u", fAliasName, fPlaybackDriverName, channel_name, i + 1);
02310 } else {
02311 snprintf(alias, sizeof(alias), "%s:%s:in%u", fAliasName, fPlaybackDriverName, i + 1);
02312 }
02313
02314 snprintf(name, sizeof(name), "%s:playback_%d", fClientControl.fName, i + 1);
02315
02316 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02317 jack_error("Cannot register port for %s", name);
02318 return -1;
02319 }
02320
02321 port = fGraphManager->GetPort(port_index);
02322 port->SetAlias(alias);
02323 fPlaybackPortList[i] = port_index;
02324
02325
02326 if (fWithMonitorPorts) {
02327 jack_log("JackCoreAudioDriver::Attach : create monitor port");
02328 snprintf(name, sizeof(name), "%s:monitor_%u", fClientControl.fName, i + 1);
02329 if (fEngine->PortRegister(fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE, MonitorDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
02330 jack_error("Cannot register monitor port for %s", name);
02331 return -1;
02332 } else {
02333 fMonitorPortList[i] = port_index;
02334 }
02335 }
02336 }
02337
02338 if (fAC3Encoder) {
02339
02340 for (int i = 0; i < fPlaybackChannels; i++) {
02341 fAC3Encoder->GetChannelName("coreaudio", "", alias, i);
02342 port = fGraphManager->GetPort(fPlaybackPortList[i]);
02343 port->SetAlias(alias);
02344 }
02345 }
02346
02347 UpdateLatencies();
02348
02349
02350 for (int i = 0; i < fCaptureChannels; i++) {
02351 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
02352 }
02353
02354 return 0;
02355 }
02356
02357 int JackCoreAudioDriver::Start()
02358 {
02359 jack_log("JackCoreAudioDriver::Start");
02360 if (JackAudioDriver::Start() == 0) {
02361
02362
02363 fState = false;
02364 int count = 0;
02365
02366 if (AudioOutputUnitStart(fAUHAL) == noErr) {
02367
02368 while (!fState && count++ < WAIT_COUNTER) {
02369 usleep(100000);
02370 jack_log("JackCoreAudioDriver::Start : wait count = %d", count);
02371 }
02372
02373 if (count < WAIT_COUNTER) {
02374 jack_info("CoreAudio driver is running...");
02375 return 0;
02376 }
02377
02378 jack_error("CoreAudio driver cannot start...");
02379 }
02380 JackAudioDriver::Stop();
02381 }
02382 return -1;
02383 }
02384
02385 int JackCoreAudioDriver::Stop()
02386 {
02387 jack_log("JackCoreAudioDriver::Stop");
02388 int res = (AudioOutputUnitStop(fAUHAL) == noErr) ? 0 : -1;
02389 if (JackAudioDriver::Stop() < 0) {
02390 res = -1;
02391 }
02392 return res;
02393 }
02394
02395 int JackCoreAudioDriver::SetBufferSize(jack_nframes_t buffer_size)
02396 {
02397 if (SetupBufferSize(buffer_size) < 0) {
02398 return -1;
02399 }
02400
02401 JackAudioDriver::SetBufferSize(buffer_size);
02402
02403
02404 UpdateLatencies();
02405
02406
02407 for (int i = 0; i < fCaptureChannels; i++) {
02408 fJackInputData->mBuffers[i].mNumberChannels = 1;
02409 fJackInputData->mBuffers[i].mDataByteSize = fEngineControl->fBufferSize * sizeof(jack_default_audio_sample_t);
02410 fJackInputData->mBuffers[i].mData = GetInputBuffer(i);
02411 }
02412
02413 return 0;
02414 }
02415
02416 bool JackCoreAudioDriver::TakeHogAux(AudioDeviceID deviceID, bool isInput)
02417 {
02418 pid_t hog_pid;
02419 UInt32 propSize = sizeof(hog_pid);
02420
02421 OSStatus err = AudioDeviceGetProperty(deviceID, 0, isInput, kAudioDevicePropertyHogMode, &propSize, &hog_pid);
02422 if (err) {
02423 jack_error("Cannot read hog state...");
02424 printError(err);
02425 }
02426
02427 jack_log("JackCoreAudioDriver::TakeHogAux : deviceID = %d", deviceID);
02428
02429 if (hog_pid != getpid()) {
02430 hog_pid = getpid();
02431 err = AudioDeviceSetProperty(deviceID, 0, 0, isInput, kAudioDevicePropertyHogMode, propSize, &hog_pid);
02432 if (err != noErr) {
02433 jack_error("Can't hog device = %d because it's being hogged by another program or cannot be hogged", deviceID);
02434 return false;
02435 }
02436 }
02437
02438 return true;
02439 }
02440
02441 bool JackCoreAudioDriver::TakeHog()
02442 {
02443 OSStatus err = noErr;
02444 AudioObjectID sub_device[32];
02445 UInt32 outSize = sizeof(sub_device);
02446 err = AudioDeviceGetProperty(fDeviceID, 0, kAudioDeviceSectionGlobal, kAudioAggregateDevicePropertyActiveSubDeviceList, &outSize, sub_device);
02447
02448 if (err != noErr) {
02449 jack_log("JackCoreAudioDriver::TakeHog : device does not have subdevices");
02450 return TakeHogAux(fDeviceID, true);
02451 } else {
02452 int num_devices = outSize / sizeof(AudioObjectID);
02453 jack_log("JackCoreAudioDriver::TakeHog : device does has %d subdevices", num_devices);
02454 for (int i = 0; i < num_devices; i++) {
02455 if (!TakeHogAux(sub_device[i], true)) {
02456 return false;
02457 }
02458 }
02459 return true;
02460 }
02461 }
02462
02463 bool JackCoreAudioDriver::IsAggregateDevice(AudioDeviceID device)
02464 {
02465 UInt32 deviceType, outSize = sizeof(UInt32);
02466 OSStatus err = AudioDeviceGetProperty(device, 0, kAudioDeviceSectionGlobal, kAudioDevicePropertyTransportType, &outSize, &deviceType);
02467
02468 if (err != noErr) {
02469 jack_log("JackCoreAudioDriver::IsAggregateDevice kAudioDevicePropertyTransportType error");
02470 return false;
02471 } else {
02472 return (deviceType == kAudioDeviceTransportTypeAggregate);
02473 }
02474 }
02475
02476
02477 }
02478
02479
02480 #ifdef __cplusplus
02481 extern "C"
02482 {
02483 #endif
02484
02485 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor()
02486 {
02487 jack_driver_desc_t * desc;
02488 jack_driver_desc_filler_t filler;
02489 jack_driver_param_value_t value;
02490
02491 desc = jack_driver_descriptor_construct("coreaudio", JackDriverMaster, "Apple CoreAudio API based audio backend", &filler);
02492
02493 value.i = -1;
02494 jack_driver_descriptor_add_parameter(desc, &filler, "channels", 'c', JackDriverParamInt, &value, NULL, "Maximum number of channels", "Maximum number of channels. If -1, max possible number of channels will be used");
02495 jack_driver_descriptor_add_parameter(desc, &filler, "in-channels", 'i', JackDriverParamInt, &value, NULL, "Maximum number of input channels", "Maximum number of input channels. If -1, max possible number of input channels will be used");
02496 jack_driver_descriptor_add_parameter(desc, &filler, "out-channels", 'o', JackDriverParamInt, &value, NULL, "Maximum number of output channels", "Maximum number of output channels. If -1, max possible number of output channels will be used");
02497
02498 value.str[0] = 0;
02499 jack_driver_descriptor_add_parameter(desc, &filler, "input-list", 'n', JackDriverParamString, &value, NULL, "Input channel list for channel mapping", "List of input channel number to be opened (syntax like : \"0 3 2\")");
02500 jack_driver_descriptor_add_parameter(desc, &filler, "output-list", 'N', JackDriverParamString, &value, NULL, "Output channel list for channel mapping", "List of output channel number to be opened (syntax like : \"0 3 2\")");
02501
02502 value.str[0] = 0;
02503 jack_driver_descriptor_add_parameter(desc, &filler, "capture", 'C', JackDriverParamString, &value, NULL, "Input CoreAudio device name", NULL);
02504 jack_driver_descriptor_add_parameter(desc, &filler, "playback", 'P', JackDriverParamString, &value, NULL, "Output CoreAudio device name", NULL);
02505
02506 value.i = 0;
02507 jack_driver_descriptor_add_parameter(desc, &filler, "monitor", 'm', JackDriverParamBool, &value, NULL, "Provide monitor ports for the output", NULL);
02508
02509 #ifndef __ppc__
02510 value.i = 0;
02511 jack_driver_descriptor_add_parameter(desc, &filler, "AC3-encoding", 'a', JackDriverParamBool, &value, NULL, "AC3 multi-channels encoding", NULL);
02512
02513 value.i = 448;
02514 jack_driver_descriptor_add_parameter(desc, &filler, "AC3-bitrate", 'b', JackDriverParamUInt, &value, NULL, "AC3 bitrate", NULL);
02515
02516 value.i = 0;
02517 jack_driver_descriptor_add_parameter(desc, &filler, "AC3-LFE", 'f', JackDriverParamBool, &value, NULL, "AC3 LFE channel", NULL);
02518 #endif
02519 value.i = true;
02520 jack_driver_descriptor_add_parameter(desc, &filler, "duplex", 'D', JackDriverParamBool, &value, NULL, "Provide both capture and playback ports", NULL);
02521
02522 value.ui = 44100U;
02523 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
02524
02525 value.ui = 256U;
02526 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
02527
02528 value.str[0] = 0;
02529 jack_driver_descriptor_add_parameter(desc, &filler, "device", 'd', JackDriverParamString, &value, NULL, "CoreAudio device name", NULL);
02530
02531 value.ui = 0;
02532 jack_driver_descriptor_add_parameter(desc, &filler, "input-latency", 'I', JackDriverParamUInt, &value, NULL, "Extra input latency (frames)", NULL);
02533 jack_driver_descriptor_add_parameter(desc, &filler, "output-latency", 'O', JackDriverParamUInt, &value, NULL, "Extra output latency (frames)", NULL);
02534
02535 value.i = false;
02536 jack_driver_descriptor_add_parameter(desc, &filler, "list-devices", 'l', JackDriverParamBool, &value, NULL, "Display available CoreAudio devices", NULL);
02537
02538 value.i = false;
02539 jack_driver_descriptor_add_parameter(desc, &filler, "hog", 'H', JackDriverParamBool, &value, NULL, "Take exclusive access of the audio device", NULL);
02540
02541 value.ui = 100;
02542 jack_driver_descriptor_add_parameter(desc, &filler, "async-latency", 'L', JackDriverParamUInt, &value, NULL, "Extra output latency in asynchronous mode (percent)", NULL);
02543
02544 value.ui = 100;
02545 jack_driver_descriptor_add_parameter(desc, &filler, "grain", 'G', JackDriverParamUInt, &value, NULL, "Computation grain in RT thread (percent)", NULL);
02546
02547 value.i = false;
02548 jack_driver_descriptor_add_parameter(desc, &filler, "clock-drift", 's', JackDriverParamBool, &value, NULL, "Clock drift compensation", "Whether to compensate clock drift in dynamically created aggregate device");
02549
02550 return desc;
02551 }
02552
02553 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
02554 {
02555 jack_nframes_t srate = 44100;
02556 jack_nframes_t frames_per_interrupt = 256;
02557 bool capture = false;
02558 bool playback = false;
02559 int chan_in = -1;
02560 int chan_out = -1;
02561 const char* chan_in_list = "";
02562 const char* chan_out_list = "";
02563 bool monitor = false;
02564 const char* capture_driver_uid = "";
02565 const char* playback_driver_uid = "";
02566 const JSList *node;
02567 const jack_driver_param_t *param;
02568 jack_nframes_t systemic_input_latency = 0;
02569 jack_nframes_t systemic_output_latency = 0;
02570 int async_output_latency = 100;
02571 int computation_grain = -1;
02572 bool hogged = false;
02573 bool clock_drift = false;
02574 bool ac3_encoding = false;
02575 int ac3_bitrate = 448;
02576 bool ac3_lfe = false;
02577
02578 for (node = params; node; node = jack_slist_next(node)) {
02579 param = (const jack_driver_param_t *) node->data;
02580
02581 switch (param->character) {
02582
02583 case 'd':
02584 capture_driver_uid = param->value.str;
02585 playback_driver_uid = param->value.str;
02586 break;
02587
02588 case 'D':
02589 capture = true;
02590 playback = true;
02591 break;
02592
02593 case 'c':
02594 chan_in = chan_out = param->value.i;
02595 break;
02596
02597 case 'i':
02598 chan_in = param->value.i;
02599 break;
02600
02601 case 'o':
02602 chan_out = param->value.i;
02603 break;
02604
02605 case 'n':
02606 chan_in_list = param->value.str;
02607 break;
02608
02609 case 'N':
02610 chan_out_list = param->value.str;
02611 break;
02612
02613 case 'C':
02614 capture = true;
02615 if (strcmp(param->value.str, "none") != 0) {
02616 capture_driver_uid = param->value.str;
02617 }
02618 break;
02619
02620 case 'P':
02621 playback = true;
02622 if (strcmp(param->value.str, "none") != 0) {
02623 playback_driver_uid = param->value.str;
02624 }
02625 break;
02626
02627 case 'm':
02628 monitor = param->value.i;
02629 break;
02630
02631 #ifndef __ppc__
02632 case 'a':
02633 ac3_encoding = param->value.i;
02634 break;
02635
02636 case 'b':
02637 ac3_bitrate = param->value.i;
02638 break;
02639
02640 case 'f':
02641 ac3_lfe = param->value.i;
02642 break;
02643 #endif
02644
02645 case 'r':
02646 srate = param->value.ui;
02647 break;
02648
02649 case 'p':
02650 frames_per_interrupt = (unsigned int)param->value.ui;
02651 break;
02652
02653 case 'I':
02654 systemic_input_latency = param->value.ui;
02655 break;
02656
02657 case 'O':
02658 systemic_output_latency = param->value.ui;
02659 break;
02660
02661 case 'l':
02662 Jack::DisplayDeviceNames();
02663
02664 return NULL;
02665
02666 case 'H':
02667 hogged = true;
02668 break;
02669
02670 case 'L':
02671 async_output_latency = param->value.ui;
02672 break;
02673
02674 case 'G':
02675 computation_grain = param->value.ui;
02676 break;
02677
02678 case 's':
02679 clock_drift = true;
02680 break;
02681 }
02682 }
02683
02684
02685 if (!capture && !playback) {
02686 capture = true;
02687 playback = true;
02688 }
02689
02690 if (strcmp(chan_in_list, "") != 0 && chan_in >= 0) {
02691 printf("Input channel list and in channels are both specified, input channel list will take over...\n");
02692 }
02693
02694 if (strcmp(chan_out_list, "") != 0 && chan_out >= 0) {
02695 printf("Output channel list and out channels are both specified, output channel list will take over...\n");
02696 }
02697
02698 Jack::JackCoreAudioDriver* driver = new Jack::JackCoreAudioDriver("system", "coreaudio", engine, table);
02699 if (driver->Open(frames_per_interrupt,
02700 srate, capture,
02701 playback, chan_in,
02702 chan_out, chan_in_list,
02703 chan_out_list, monitor,
02704 capture_driver_uid,
02705 playback_driver_uid,
02706 systemic_input_latency,
02707 systemic_output_latency,
02708 async_output_latency,
02709 computation_grain,
02710 hogged, clock_drift,
02711 ac3_encoding, ac3_bitrate, ac3_lfe) == 0) {
02712 return driver;
02713 } else {
02714 delete driver;
02715 return NULL;
02716 }
02717 }
02718
02719 #ifdef __cplusplus
02720 }
02721 #endif
02722
02723